
    ȅiX                     ~   S SK r S SKrS SKJr  S SKrS SKJs  Js  Js  J	r
  S SKJs  Js  J	r  S SKJr  S SKJrJr  S SKJr  S SKJr  S SKJr  S SKJr  SS	KJrJr  \R8                  R                  r " S
 S\ R<                  5      rS\S\S\S\ \!\"\   4   S\#\\4   4
S jr$S\S\S\ \!\"\   4   S\#\RJ                  \&-  \RJ                  \'-  4   S-  4S jr(S\S\S\4S jr)S\S\S\'4S jr*S\S\+\'   4S jr,S\S\S\!4S jr-S\S\!S\4S jr.S\SS4S jr/S r0\0S\RJ                  S\RJ                  S\RJ                  4S j5       r1\0S\RJ                  S\RJ                  S\RJ                  4S j5       r2\0S\RJ                  S\RJ                  S\RJ                  4S  j5       r3S\S\44S! jr5S\S\S"\'S\4S# jr6g)$    N)Callable)FakeQuantizeBaseObserverBase)_is_activation_post_process)getattr_from_fqn)GraphModule)Node   )NSNodeTargetTypeNSResultsTypec                       \ rS rSr\R
                  " 5       r\R
                  " 5       r\R
                  " 5       r\R
                  " 5       r	\R
                  " 5       r
Srg)NodeInputOrOutputType    N)__name__
__module____qualname____firstlineno__enumautoFP32INT8FP16UNKNOWNFP32_OR_INT8__static_attributes__r       N/home/james-whalen/.local/lib/python3.13/site-packages/torch/ao/ns/fx/utils.pyr   r      s;    99;D99;D99;DiikG
 99;Lr   r   nodegm
logger_clsnode_type_to_io_type_mapreturnc                 4	  ^ US   nUS   nUS   nUS   nUS   nUS   n	US   n
US   nU R                   S	:X  Ga
  U R                  U;   a   [        R                  [        R                  4$ U R                  U;   a   [        R                  [        R                  4$ U R                  U;   a   [        R
                  [        R
                  4$ U R                  U;   aJ  [        XS
5      n[        U[        5      (       d  [        S[        U5       35      e[        XX#5      u  nnX4$ [        R                  [        R                  4$ U R                   S:X  Ga  U R                   S:w  a  [        SU R                    S35      e[        U R                  [        5      (       d!  [        S[        U R                  5       35      e[        XR                  5      m[        U4S jU
 5       5      n[        TU[         ["        45      (       d  U(       aJ  [        XS
5      n[        U[        5      (       d  [        S[        U5       35      e[        XX#5      u  nnX4$ [        U4S jU 5       5      n[        U4S jU	 5       5      nU(       a   [        R                  [        R                  4$ U(       a   [        R
                  [        R
                  4$ [        R                  [        R                  4$ U R                   S:X  Ga{  U R                  S:X  aZ  [        XS
5      n[        U[        5      (       d  [        S[        U5       35      e[        UXU5      u  nnU[        R                  4$ U R                  S:X  a  [        XS
5      n[        U[        5      (       d  [        S[        U5       35      e[        UXU5      u  nn[        XS5      nU[$        R&                  La  [        U S35      eU[        R                  4$ U R                  U;   aJ  [        XS
5      n[        U[        5      (       d  [        S[        U5       35      e[        XX#5      u  nnX4$ [        R                  [        R                  4$ [        R                  [        R                  4$ )Nfuns_io_type_fp32funs_io_type_fp16funs_io_type_int8funs_io_type_fp32_or_int8mods_io_type_fp32mods_io_type_int8mods_io_type_fp32_or_int8meths_io_type_fp32_or_int8call_functionr   Expected Node, got call_modulezExpected call_module, got ''zExpected str, but got c              3   <   >#    U  H  n[        TU5      v   M     g 7fN
isinstance.0target_typemods     r   	<genexpr>7get_node_first_input_and_output_type.<locals>.<genexpr>R   s"      1
8 sK((8   c              3   <   >#    U  H  n[        TU5      v   M     g 7fr2   r3   r5   s     r   r9   r:   f   "      )
0 sK((0r;   c              3   <   >#    U  H  n[        TU5      v   M     g 7fr2   r3   r5   s     r   r9   r:   j   r=   r;   call_method
dequantizetor
   z handling needs to be added)optargetr   r   r   r   get_normalized_nth_inputr4   r	   AssertionErrortype$get_node_first_input_and_output_typer   strr   anyr   r   torchfloat16)r   r    r!   r"   FUNS_IO_TYPE_FP32FUNS_IO_TYPE_FP16FUNS_IO_TYPE_INT8FUNS_IO_TYPE_FP32_OR_INT8MODS_IO_TYPE_FP32MODS_IO_TYPE_INT8MODS_IO_TYPE_FP32_OR_INT8METHS_IO_TYPE_FP32_OR_INT8	first_arg_prev_node_input_typeprev_node_output_type"is_known_fp32_or_int8_input_moduleis_known_fp32_input_moduleis_known_int8_input_module	prev_nodecur_node_dtype_targetr8   s                       @r   rG   rG   &   s    11DE01DE01DE 89T U01DE01DE 89T U!9:V!Www/!;;++)..0E0J0JKK;;++)..0E0J0JKK[[--)..0E0J0JKK[[5501=Ii..$':4	?:K%LMM 5z%% *AA)113H3P3PQQ	M	!77m# #>twwiq!IJJ$++s++ #9$t{{:K9L!MNNr;;/-0 1
81
 .
*
 sZ7GHII1 11=Ii..$':4	?:K%LMM 5z%% *AA%( )
0)
 &
" &) )
0)
 &
" &)..0E0J0JKK')..0E0J0JKK)113H3P3PQQ	M	!;;,& 11=Ii..$':4	?:K%LMM 52+C%% *+@+E+EFF[[D 
 11=Ii..$':4	?:K%LMM 52+C%%
 %=Tq$I!$EMM9$,--HI  *+@+E+EFF[[6601=Ii..$':4	?:K%LMM 5z%% *AA%--/D/L/LMM%--/D/L/LMMr   c                   ^ [        XS5      n[        U[        5      (       d  gUS   nS nUR                  S:X  a~  UR                  [
        R                  L a
  U" X1SS5      $ UR                  [        R                  [        R                  [        R                  [        R                  4;   a
  U" X1SS5      $ gUR                  S	:X  Ga  [        UR                  [        5      (       d!  [        S
[        UR                  5       35      e[        XR                  5      m[        T[         R"                  [         R$                  [         R&                  [(        R*                  [         R,                  [         R.                  [         R0                  [         R2                  [         R4                  [         R6                  [         R8                  [         R:                  [         R<                  [         R>                  [         R@                  [         RB                  [         RD                  [         RF                  [(        RH                  [(        RJ                  [(        RL                  [(        R*                  [(        RN                  [(        RP                  45      (       a  TRR                  TRT                  4$ [W        U4S jU 5       5      nU(       a  [Y        X1U5      $ g)zo
Returns the qparams (scale, zero_point) of the first input to `node`,
if they can be inferred from the graph.
r   Nr+   c                 <   [        XU5      n[        XU5      n[        U[        5      (       d  [        S[	        U5       35      e[        UR
                  [        5      (       d!  [        S[	        UR
                  5       35      e[        U[        5      (       d  [        S[	        U5       35      e[        UR
                  [        5      (       d!  [        S[	        UR
                  5       35      e[        XR
                  5      n[        XR
                  5      nXg4$ )Nr.   Expected str, got )rD   r4   r	   rE   rF   rC   rH   r   )r   r    scale_arg_idx
zp_arg_idx
scale_nodezp_node	scale_objzp_objs           r    _get_scale_zp_from_function_args@get_node_input_qparams.<locals>._get_scale_zp_from_function_args   s    -dF
*4Z@*d++ #6tJ7G6H!IJJ*++S11 #5d:;L;L6M5N!OPP'4(( #6tG}o!FGG'..#.. #5d7>>6J5K!LMM$R):):;	!"nn5""r   r-   r
         r/   r^   c              3   <   >#    U  H  n[        TU5      v   M     g 7fr2   r3   )r6   r7   
module_objs     r   r9   )get_node_input_qparams.<locals>.<genexpr>   s"      1
8 z;//8r;   )-rD   r4   r	   rB   rC   rJ   quantize_per_tensortoqaddadd_relumulmul_relurH   rE   rF   r   nnqLinearConv1dConv2dnniq
ConvReLU2dConv3dBatchNorm2dBatchNorm3dConvTranspose1dConvTranspose2dELU	GroupNormInstanceNorm1dInstanceNorm2dInstanceNorm3d	LayerNorm	Hardswish	LeakyReLUReLU6BNReLU2dBNReLU3d
ConvReLU1d
ConvReLU3d
LinearReLUscale
zero_pointrI   get_node_input_qparams)r   r    r"   rZ   rR   re   rW   rj   s          @r   r   r      s    )15Ii&& 89T U# ||&u8883I1aHH#''3<<#,,!OO3I1aHH 
	&)**C00 #5d9;K;K6L5M!NOO%b*:*:;








####""""""		1
 
: $$j&;&;<<-0 1
81
 .
* .))9QRRr   c                 z   U R                   S:X  Ga  [        XR                  5      n[        U5      (       Ga  [	        U R
                  5      S:w  a!  [        S[	        U R
                  5       35      e[        U R
                  S   [        5      (       d$  [        S[        U R
                  S   5       35      eU R
                  S   n [        U R                  [        5      (       d!  [        S[        U R                  5       35      e[        XR                  5      n[        U5      (       a  [	        U R
                  5      S:w  a!  [        S[	        U R
                  5       35      e[        U R
                  S   [        5      (       d$  [        S[        U R
                  S   5       35      eU R
                  S   n U $ )ak  
If node is not an observer, returns it.  If node is an observer,
navigates up the graph and returns the first parent which is not an
observer.  For example,

graph: (node_non_obs), node = node_non_obs : returns node_non_obs
graph: (node_non_obs -> obs0), node = obs0 : returns node_non_obs
graph: (node_non_obs -> obs0 -> fq0), node = fq0 : returns node_non_obs
r/   r
   z)Expected node.args to have length 1, got r   r.   r^   )rB   r   rC   r   lenargsrE   r4   r	   rF   rH   r   r    node_objs      r   return_first_non_observer_noder     s_    ww-#B4&x00499~"$?DII?OP  diilD11$':4		!;M:N%OPP99Q<Ddkk3//$'9$t{{:K9L%MNN'KK8H*844tyy>Q&(CC		NCST  "$))A,55(+>tDIIaL?Q>R)STTyy|Kr   c                     U R                   S:X  a5  [        XR                  5      n[        U[        R
                  5      (       a  gg)a/  
Assumes that all non-param args occur first. Returns the number of
non-param args expected for a node.  For example, for

  F.linear(x, weight, bias)

Returns 1, because x is a non-param arg and weight and bias are params.
For

  lstm_mod(x, hid)

Returns 2, because both x and hid are non-param args.
r/   rg   r
   )rB   r   rC   r4   nnLSTMr   s      r   get_number_of_non_param_argsr   +  s7    " ww-#B4h(( r   c                 (   [        U R                  5      S:X  a  / $ U R                  S:X  a  U R                  [        R
                  [        R                  R                  R
                  [        R
                  4;   dQ  U R                  [        R                  [        R                  R                  R                  [        R                  4;   a>  [        S5       Vs/ s H&  n[        U R                  U   5      [        L d  M$  UPM(     nnU$ S/$ s  snf )a	  
Returns the indices of args of the node which we should attach
loggers to, if input logging is enabled.

For example,
* for (x + y), returns [0, 1]
* for (1 + y), returns [1]
* for (x + 1), returns [0]
* for (linear(x, w, b)) returns [0]
* by default, returns [0]
r   r-   rg   )r   r   rB   rC   rJ   rn   ops	quantizedoperatorrp   rangerF   r	   )r   iresults      r    get_arg_indices_of_inputs_to_logr   E  s     499~	ww/!		599#6#6#:#:HLLII;;599eii&9&9&=&=x||LL"1XDXdiil);t)C!XD3J Es   #DDc                 d   SnU R                   S;   a"  [        R                  " U R                  5      nU$ U R                   S:X  ak  [	        U R                  [
        5      (       d!  [        S[        U R                  5       35      e[        XR                  5      n[        R                  " U5      nU$ )z|
Returns a string representation of the type of the function or module
pointed to by this node, or '' for other node types.
 )r-   r?   r/   r^   )	rB   rJ   typenamerC   r4   rH   rE   rF   r   )r   r    r7   
target_mods       r   get_target_type_strr   ]  s    
 Kww22nnT[[1  
M	!$++s++ #5d4;;6G5H!IJJ%b++6
nnZ0r   results
model_namec                    0 nU R                  5        Hm  u  p4SnUR                  5        HE  nUR                  5        H.  u  pxXq:X  a$  [        U5      S:X  a  [        S5      eUS   S   nM.  M0     MG     Ub  XBU'   Mi  XBU'   Mo     U$ )a  
Rekeys the layer name of a results dictionary to use node names
from `model_name`.

For example, transforms

    {'base_op_1_0': {'node_output': {'model_a':
      [{'ref_node_name': 'linear1', ...}]}}}

into

    {'linear1': {'node_output': {'model_a':
      [{'ref_node_name': 'linear1', ...}]}}}

Note: we cannot use these node names directly because they are not
guaranteed to be consistent across models. This is why we extract
the results first and rekey afterwards.
Nr   z(Expected list_of_results to be not emptyref_node_name)itemsvaluesr   rE   )	r   r   new_resultsold_layer_nameresult_type_to_resultsnew_layer_namemodel_name_to_resultscur_model_namelist_of_resultss	            r   'rekey_logger_info_on_node_name_of_modelr   m  s    , K29--/.%;%B%B%D!3H3N3N3P/!/?+q0,-WXX%4Q%7%HN 4Q &E %*@'*@' 3B r   c                    SnU R                  5        HQ  nUR                  5        H:  nUR                  5        H#  u  pE[        U5      S:  d  M  US   S   c  M!  Un  O     O     O   U(       a|  U R                  5        Hg  nUR                  5        HP  nX1   nUR                  5        H5  u  pEXA:X  a  M  [        [        U5      5       H  nXg   S   nXU   S'   M     M7     MR     Mi     gg)aa  
If `fqn` entries are filled in for one of the models in `results`, copies
them over to any models which do not have them filled out.

A common use case benefitting from this is comparing a model prepared by
quantization to a quantized model. In this case, the model prepared by
quantization would have `fqn` entries, and the quantized model would not.
Nr   fqn)r   r   r   r   )	r   model_name_with_fqnsr   r   r   model_resultsref_model_resultsr   r   s	            r   maybe_add_missing_fqnsr     s      ").."2%;%B%B%D!-B-H-H-J)
}%)$Q'.:/9,	 .K
  &E 	 #3 &-nn&6")?)F)F)H%$9$O!1F1L1L1N-J!9 "3}#56/25925a(/ 7	 2O *I '7 r   c                    ^ ^ U U4S jmT$ )Nc                    > U tp#n[        U[        5      (       a  [        U[        5      (       d*  [        U[        5      (       aJ  [        U[        5      (       a5  / n[        X#5       H"  u  pgXg/UQ7nUR	                  T
" U0 UD65        M$     U$ [        U[
        R                  5      (       aa  [        U[
        R                  5      (       aB  UR                  (       a  UR                  5       nUR                  (       a  UR                  5       nUR                  [
        R                  :w  d  UR                  [
        R                  :w  a  g X#/UQ7nT	" U0 UD6$ r2   )r4   tuplelistzipappendrJ   Tensoris_quantizedr@   dtypefloat)r   kwargsa0a1a_otherr   el0el1new_argsfinners            r   r   Gmaybe_dequantize_first_two_tensor_args_and_handle_tuples.<locals>.inner  s   r5!!jU&;&;r4  ZD%9%9GK/w/uh9&9: ( NELL))jU\\.J.J]]_]]_ 88u{{"bhh%++&=%W%(%f%%r   r   )r   r   s   `@r   8maybe_dequantize_first_two_tensor_args_and_handle_tuplesr     s    &2 Lr   xyc                     [         R                  " U 5      n[         R                  " X-
  5      nS[         R                  " X#-  5      -  $ )z
Computes the SQNR between `x` and `y`.

Args:
    x: Tensor or tuple of tensors
    y: Tensor or tuple of tensors

Return:
    float or tuple of floats
   )rJ   normlog10)r   r   PsPns       r   compute_sqnrr     s7     
AB	AE	BBG$$$r   c                 |    [         R                  " X-
  S-  R                  5       U S-  R                  5       -  5      $ )z
Computes the normalized L2 error between `x` and `y`.

Args:
    x: Tensor or tuple of tensors
    y: Tensor or tuple of tensors

Return:
    float or tuple of floats
rg   )rJ   sqrtsumr   r   s     r   compute_normalized_l2_errorr     s1     ::!|((*adZZ\9::r   c                     U R                  SS5      n UR                  SS5      n[        R                  R                  R	                  X5      $ )z
Computes the cosine similarity between `x` and `y`.

Args:
    x: Tensor or tuple of tensors
    y: Tensor or tuple of tensors

Return:
    float or tuple of floats
r
   )reshaperJ   r   
functionalcosine_similarityr   s     r   compute_cosine_similarityr     s?     	
		!RA			!RA880066r   c                     U R                   S:X  ak  U R                  [        R                  [        R                  [
        R                  [
        R                  [        R                  [        R                  4;   a  gg)Nr-   FT)rB   rC   rJ   rn   rp   r   catstack)r   s    r   op_type_supports_shadowingr   
  sQ    ww/!;;IIIILLLLIIKK
 
 r   idxc           
      t    U R                  USS9nUbt  Uu  pE[        U5      [        U5      -   U::  a&  [        SU S[        U5      [        U5      -    35      eU[        U5      :  a  XB   $ [        UR	                  5       5      U   $ [        U R
                  5      [        U R                  5      -   U::  a:  [        SU S[        U R
                  5      [        U R                  5      -    35      eU[        U R
                  5      :  a  U R
                  U   $ U[        U R
                  5      -   n[        U R                  R	                  5       5      U   $ ! [         a    [        U R
                  5      [        U R                  5      -   U::  a;  [        SU S[        U R
                  5      [        U R                  5      -    35      SeU[        U R
                  5      :  a  U R
                  U   s $ U[        U R
                  5      -   n[        U R                  R	                  5       5      U   s $ f = f)zi
Given a node, gets the n'th input to that node, normalizing
args and kwargs to the best of its ability.
T)normalize_to_only_use_kwargsNzIndex z out of range: total = )normalized_argumentsr   rE   r   r   r   r   RuntimeError)r   r    r   norm_args_and_kwargs	norm_argsnorm_kwargs
kwargs_idxs          r   rD   rD     s   
%:#88T  9  
  +%9"I9~K 00C7$SE!8Y#kJZ9Z8[\  S^# ~% K..01#66499~DKK 00C7$SE!8TYY#dkkJZ9Z8[\  S^#yy~% 3tyy>1
DKK..01*== : tyy>C,,3 4S^c$++FV5V4WX TYY99S>!s499~-J**,-j99:s,   A*E -E 	BE =E BH76>H76H7)7r   r   collections.abcr   rJ   torch.ao.nn.intrinsic.quantizedaor   	intrinsicr   rv   torch.ao.nn.quantizedrr   torch.nntorch.ao.quantizationr   r   torch.ao.quantization.observerr   torch.ao.quantization.utilsr   torch.fxr   torch.fx.graphr	   ns_typesr   r   r   rm   Enumr   dictrH   setr   rG   r   r   intr   r   r   r   r   r   r   r   r   r   r   r   boolr   rD   r   r   r   <module>r      s     $  . . # #  @ F 8    5 ii
	DII 	DN
DNDN DN #3,<(=#=>	DN
  "778DNNU
UU #3,<(=#=>U 5<<%!334t;	Up#
## 
#L
 	44 DI 0d    %%% %P 6M  6d  6F: :%ELL %U\\ %ell % :%  :;5<< ;ELL ;U\\ ; :; :7 7%,, 75<< 7 :7&T d *:4 *:[ *:s *:t *:r   