
    קg/%                        d dl Z d dlmZmZ d dlZg dZej        j        ej        j        ej        j	        hZ
ej        j        j        j        ej        j        j        j        ej        j        j        j        hZe
                    e          ZddZddZdefdZd Zd	 ZddZddZddZd ZddZd Zd ZddZ ddZ!dS )    N)AnyDict)set_module_weightset_module_biashas_biasget_module_weightget_module_biasmax_over_ndimmin_over_ndimchannel_rangeget_name_by_modulecross_layer_equalization#process_paired_modules_list_to_name$expand_groups_in_paired_modules_listequalize	convergedreturnc                     t          |           t          v r&t          j                            |          | _        d S t          j                            |          | d         _        d S Nr   )type_supported_typestorchnn	Parameterweight)moduler   s     [/var/www/html/ai-engine/env/lib/python3.11/site-packages/torch/ao/quantization/_equalize.pyr   r   "   sQ    F||'''**622 8--f55q	    c                     t          |           t          v r&t          j                            |          | _        d S t          j                            |          | d         _        d S r   )r   r   r   r   r   bias)r   r    s     r   r   r   )   sN    F||'''h((..++D11q	r   c                 ^    t          |           t          v r	| j        d uS | d         j        d uS r   r   r   r    r   s    r   r   r   0   s2    F||'''{$&&ay~T))r   c                 V    t          |           t          v r| j        S | d         j        S r   )r   r   r   r#   s    r   r   r   7   s)    F||'''}ayr   c                 V    t          |           t          v r| j        S | d         j        S r   r"   r#   s    r   r	   r	   >   s(    F||'''{ay~r   Fc                 n    |                     d           |D ]}|                     ||          \  } }| S )z&Apply 'torch.max' over the given axes.Treverse)sortmaxinput	axis_listkeepdimaxis_s        r   r
   r
   E   C    NN4N    , ,99T7++qqLr   c                 n    |                     d           |D ]}|                     ||          \  } }| S )z&Apply 'torch.min' over the given axes.Tr'   )r)   minr+   s        r   r   r   M   r1   r   c                 (   | j         }t          t          |                    }|                    |           t	          | |          }t          | |          }|                    d          |                     |          k    s
J d            ||z
  S )z=Find the range of weights associated with a specific channel.r   zKDimensions of resultant channel range does not match size of requested axis)ndimlistrangeremover   r
   size)r,   r/   size_of_tensor_dimr-   minsmaxss         r   r   r   U   s    U-..//IT	**D	**D99Q<<5::    T   $;r   c                 d    |                                  D ]\  }}||u r|c S t          d          )zGet the name of a module within a model.

    Args:
        model: a model (nn.module) that equalization is to be applied on
        module: a module within the model

    Returns:
        name: the name of the module within the model
    zmodule is not in the model)named_modules
ValueError)modelr   namems       r   r   r   d   sI     &&((  a;;KKK 
1
2
22r      c                    t          |           t          vst          |          t          vr,t          dt          |           dt          |                    t          |           }d}t	          |           }t	          |          }|                    |          |                    |          k    rt          d          |rt          |           }t          ||          }t          ||          }	|	dz  }	t          j
        ||	z            }
t          j        |
          }|r||z  }dg|j        z  }|                    |          ||<   dg|j        z  }|                    |          ||<   t          j        |
|          }
t          j        ||          }||z  }||
z  }t          | |           |rt          | |           t          ||           dS )zScale the range of Tensor1.output to equal Tensor2.input.

    Given two adjacent tensors', the weights are scaled such that
    the ranges of the first tensors' output channel are equal to the
    ranges of the second tensors' input channel
    zmodule type not supported: Nz_Number of output channels of first arg do not match         number input channels of second argg&.>rC   )r   _all_supported_typesr?   r   r   r9   	TypeErrorr	   r   r   sqrt
reciprocalr5   reshaper   r   )module1module2output_axis
input_axisconv1_has_biasr    weight1weight2weight1_rangeweight2_rangescaling_factorsinverse_scaling_factorssize1size2s                 r   r   r   t   s    	W111== 444($w--d7mm
 
 	
 g&&ND((G((G||K  GLL$<$<<<-
 
 	

  (w''!';77M!':66M TMj!>??O#.?? .-- C',E k22E+C',EZ00E*mOU;;O#m,CUKK//G'Ggw''' '&&&gw'''''r   c                     |D ]n}t          |          D ]\\  }}t          |t          j        j                  rt          | |          ||<   8t          |t                    st          d          ]o|S )zHProcesses a list of paired modules to a list of names of paired modules.z$item must be a nn.Module or a string)	enumerate
isinstancer   r   Moduler   strrG   )r@   paired_modules_listgroupiitems        r   r   r      s     % H H '' 	H 	HGAt$00 H-eT::ac** H FGGGH	H
 r   c                 `   g }| D ]}t          |          dk    rt          d          t          |          dk    r|                    |           Mt          |          dk    rHt          t          |          dz
            D ](}|                    ||         ||dz            g           )|S )zFExpands module pair groups larger than two into groups of two modules.rC   z$Group must have at least two modules   )lenr?   appendr7   )r]   new_listr^   r_   s       r   r   r      s    H$ : :u::??CDDDZZ1__OOE""""ZZ!^^3u::>** : :q5Q< 89999Or   -C6?Tc                 "   t          | |          }|st          j        |           } t          |          }i }i }d |D             }|                                 D ]\  }}||v r
|||<   d||<   t          |||          s|D ]|}	t          j        ||	d                            ||	d         <   t          j        ||	d                            ||	d         <   t          ||	d                  ||	d                             }t          |||          | S )a  Equalize modules until convergence is achieved.

    Given a list of adjacent modules within a model, equalization will
    be applied between each pair, this will repeated until convergence is achieved

    Keeps a copy of the changing modules from the previous iteration, if the copies
    are not that different than the current modules (determined by converged_test),
    then the modules have converged enough that further equalizing is not necessary

    Reference is section 4.1 of this paper https://arxiv.org/pdf/1906.04721.pdf

    Args:
        model: a model (nn.Module) that equalization is to be applied on
            paired_modules_list (List(List[nn.module || str])): a list of lists
            where each sublist is a pair of two submodules found in the model,
            for each pair the two modules have to be adjacent in the model,
            with only piece-wise-linear functions like a (P)ReLU or LeakyReLU in between
            to get expected results.
            The list can contain either modules, or names of modules in the model.
            If you pass multiple modules in the same list, they will all be equalized together.
            threshold (float): a number used by the converged function to determine what degree
            of similarity between models is necessary for them to be called equivalent
        inplace (bool): determines if function is inplace or not
    c                     h | ]	}|D ]}|
S  ri   ).0pairrA   s      r   	<setcomp>zequalize.<locals>.<setcomp>   s%    FFFFFFFFFr   Nr   rC   )r   copydeepcopyr   r>   r   r   )
r@   r]   	thresholdinplacename_to_moduleprevious_name_to_modulename_setrA   r   rk   s
             r   r   r      sS   4 >"   %e$$>?RSS13N.0FF!4FFFH++-- 1 1f8#)N4 ,0#D)(?KK W' 	W 	WD/3}^DQRG=T/U/U#DG,/3}^DQRG=T/U/U#DG,$^DG%<nTRSW>UVVVV (?KK W Lr   c                    |                                  |                                 k    rt          d          t          j        d          }d|                                v rdS |                                  D ]X}t          | |                   }t          ||                   }|                    |          }|t          j        |          z  }Yt          ||k               S )a  Test whether modules are converged to a specified threshold.

    Tests for the summed norm of the differences between each set of modules
    being less than the given threshold

    Takes two dictionaries mapping names to modules, the set of names for each dictionary
    should be the same, looping over the set of names, for each name take the difference
    between the associated modules in each dictionary

    zIThe keys to the given mappings must have the same set of names of modulesg        NF)	keysr?   r   tensorvaluesr   subnormbool)curr_modulesprev_modulesro   summed_normsrA   curr_weightprev_weight
differences           r   r   r     s     l//1111W
 
 	
 <$$L|""$$$$u!!## / /'T(:;;'T(:;; __[11

:...y()))r   )r   N)F)r   )r   rC   )rf   T)rf   )"rm   typingr   r   r   __all__r   Conv2dLinearConv1dr   ao	intrinsic
ConvReLU2d
LinearReLU
ConvReLU1d_supported_intrinsic_typesunionrF   r   r   rz   r   r   r	   r
   r   r   r   r   r   r   r   r   ri   r   r   <module>r      s              " HOUX_ehoF 	HK$	HK$	HK$ 
 (--.HII 6 6 6 62 2 2 2* * * * *                3 3 3 9( 9( 9( 9(x	 	 	   2 2 2 2j* * * * * *r   