
    iP                     j   S SK r S SKJr  S SKJr  S SKJrJrJrJ	r	J
r
  S SK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  S SKJrJr  S SKJrJ r J!r!  S SK"J#r#J$r$  S\\RJ                     S\&4S jr'S\&4S jr(S\\   S\	\RR                  \RR                  4   4S jr*S\R&                  RV                  S\\   4S jr,S\	\   S\&4S jr-S\R&                  R\                  S\\   4S jr/ S#S\\R\                  -  S\\0\RR                  S4      S \$S!\&S\R\                  4
S" jjr1g)$    N)OrderedDict)Iterable)AnyDictListTupleType)FuseBatchNormWithLinearPass)(AddSimulatedLinearBatchNormFusionQATPass+RemoveSimulatedLinearBatchNormFusionQATPass)QuantizeFusedConvBnBiasAtenPass)fx)
OpOverload)ExportedProgram)check_subgraphs_connectedSourcePartition)move_exported_model_to_evalObserverOrFakeQuantize)convert_pt2eprepare_pt2eprepare_qat_pt2e)Q_ANNOTATION_KEY	Quantizernodesreturnc                     SnU  HC  nU=(       d7    [         UR                  ;   =(       a    UR                  [            R                  nME     U$ )NF)r   meta
_annotated)r   	annotatednodes      f/var/www/html/ai-image-ml/venv/lib/python3.13/site-packages/executorch/backends/nxp/quantizer/utils.pyis_annotatedr"   -   sG    I 
		)Tdii8H.I.T.T 	      c                     U SS  HF  n[        UR                  5      S:w  a    g[        UR                  S   R                  5      S:w  d  MF    g   g)zO
Checks if each partition other than the last does not have any outside users.
N   Fr   T)lenoutput_nodesusers)fused_partitionsource_partitions     r!   no_outside_usersr,   6   sT     ,CR0,,-2,,Q/556!;	 1
 r#   
obs_or_fqsc                     U S   R                  5       u  pU S   R                  5       u  p2X-  n[        R                  " U[        R                  S9nXE4$ )Nr   r&   )dtype)calculate_qparamstorch
zeros_likeint64)r-   	act_scale_weight_scale
bias_scalebias_zero_points         r!   get_bias_qparamsr9   B   sS     a=224LI m557OL)J&&zEO&&r#   graphwanted_original_aten_opc                    0 nU R                    H|  nUR                  R                  S5      =nc  M#  US   nUR                  U;  a  M:  UR	                  US   0 5      nUR	                  UR
                  / 5      nUR                  U5        M~     S[        [        R                  R                     S[        S[        4S jn0 n	UR                  5        H-  u  pUR                  5        Vs/ s H
  ox" Xz5      PM     snX'   M/     U	$ s  snf )a(  
Args:
    graph: The graph we want to partition
    wanted_original_aten_op: List of original_aten ops (OpOverload)

Returns:
    Dictionary mapping aten ops that were given to a list of SourcePartitions
    that correspond to the list of nodes that were decomposed from the given
    aten ops.
source_fn_stackr%   r&   r   module_typer   c           	         [        5       n[        5       n[        5       nU  H  nUR                   HF  n[        U[        R                  R
                  5      (       d  M.  X`;  d  M5  UR                  U5        MH     UR                  S:X  a  UR                  U5        UR                  R                  5        H  nXp;  d  M
  UR                  U5        M     M     [        U U[        U5      [        U5      [        U5      5      $ )Nget_attr)setargs
isinstancer1   r   Nodeaddopr)   keysr   list)r   r>   input_nodesr(   paramsr    argusers           r!   make_partition7get_aten_node_target_partitions.<locals>.make_partitionm   s     euDyyc588==11c6FOOC( ! ww*$

4 

)$ $$T* *  L
 	
r#   )r   r   gettarget
setdefaultnameappendr   r1   r   rD   r	   r   itemsvalues)r:   r;   modulesr    source_fn_st	source_fndiff_modules	partitionrM   retkvs               r!   get_aten_node_target_partitionsr^   L   s     ;=G !IIMM*;<<LE $	;;55)))A,; ++DIIr:	 "
EHHMM"
15
	
4 35C@A
K
9..
K   J Ls   *D
partitionsc                 H    S nU  H  nUb  [        X5      (       d    gUnM     g)NFT)r   )r_   prev_partitionrZ   s      r!   _partitions_sequentialrb      s6    N	%.G/
 /
 "   r#   gmpartition_typesc                 ~   [        5       nU HR  n[        U R                  U/5      n[        [        R
                  R                  UR                  5       5      5      X#'   MT     [        UR                  5       5      n[        R                  " U6 n/ nU H&  n[        U5      (       d  M  UR                  U5        M(     U$ )N)r   r^   r:   rH   	itertoolschainfrom_iterablerU   productrb   rS   )	rc   rd   typed_partitionspartition_typer_   typed_partitions_listfusion_candidatesfused_partitions	candidates	            r!   find_sequential_partitions_atenrp      s     AL)4RXX?OP
+/OO))**;*;*=>,
( * !!1!8!8!:;!))+@A&	!),,##I. ' r#   modelcalibration_inputs.	quantizeris_qatc                    [        U [        5      (       a  U R                  5       n U(       a1  [        X5      n[	        5       " U5      R
                  n[        U5      nO[        X5      nU H  nU" U6   M
     U(       a4  [        5       " U5      R
                  n[        5       " U5      R
                  n[        U5      n[        SS9" U5      R
                  nU$ )a&  Quantize the provided model.

:param model: Aten model (or it's GraphModule representation) to quantize.
:param calibration_inputs: Either a tuple of calibration input tensors where each element corresponds to a model
                            input. Or an iterator over such tuples.
:param quantizer: Quantizer to use.
:param is_qat: Whether quantization is done using Quantization Aware Training (QAT) or not.
                Note: In QAT mode, training is not performed. Only calibration (in eval mode) is done.

:return: Quantized GraphModule.
T)default_zero_bias)rC   r   moduler   r   graph_moduler   r   r   r
   r   r   )rq   rr   rs   rt   mdatas         r!   calibrate_and_quantizer{      s    $ %))U.46q9FF'**"	4 # 79!<II')!,99QA'$?BOOAHr#   )F)2rf   collectionsr   collections.abcr   typingr   r   r   r   r	   r1   Dexecutorch.backends.nxp.aten_passes.fuse_batch_norm_with_linear_passr
   Eexecutorch.backends.nxp.aten_passes.simulated_linear_bn_fusion_passesr   r   >executorch.backends.transforms.quantize_fused_convbn_bias_passr   r   
torch._opsr   torch.exportr   *torch.fx.passes.utils.source_matcher_utilsr   r   torchao.quantization.pt2er   r   'torchao.quantization.pt2e.quantize_pt2er   r   r   -torchao.quantization.pt2e.quantizer.quantizerr   r   rD   boolr"   r,   Tensorr9   Graphr^   rb   GraphModulerp   tupler{    r#   r!   <module>r      sZ    # $ / /   ! ( 
 VRWW $ 	 	'+,'
5<<%&'@88>>@!*-@Fu_'= $ #Y0 	'R^^+' u||S'8!9:' ' 	'
 ^^'r#   