+
    G-j.  ã                  óF   € ^ RI Ht ^ RIHt ^ RIt^RIHt  ! R R4      tR# )é    )Úannotations)ÚdequeN)Ú	ONNXModelc                  ó,  € ] tR t^tRtR R ltR R ltR R ltR t]	R	 R
 l4       t
]	R R l4       t]	R R l4       t]	R R l4       tR R ltR%R R lltR%R R lltR R ltR. 3R R lltRR. R3R R lltR&R R lltR  R! ltR'R" R# lltR$tR# )(ÚFusionz
Base class for fusions.
c               ó$   € V ^8„  d   QhRRRRRR/# )é   Úmodelr   Úfused_op_typeÚstrÚsearch_op_type© )Úformats   "Úx/Volumes/fast/ai/experiments/nudenet-smoke/.venv/lib/python3.14/site-packages/onnxruntime/quantization/fusions/fusion.pyÚ__annotate__ÚFusion.__annotate__   s!   € ÷ *ñ *˜ið *¸ð *ÈSñ *ó    c                	ó´   € W0n         W n        Wn        . V n        . V n        V P                  R ,           V P                   ,           R,           V n        RV n        R# )Ú_fused_Ú_N)r   r   r
   Únodes_to_removeÚnodes_to_addÚ_new_node_name_prefixÚ_new_node_name_suffix)Úselfr
   r   r   s   &&&&r   Ú__init__ÚFusion.__init__   sO   € Ø#1ÔØ"/ÔØ %Œ
Ø%'ˆÔØ"$ˆÔà%)×%7Ñ%7¸)Õ%CÀd×FYÑFYÕ%YÐ\_Õ%_ˆÔ"Ø%)ˆÖ"r   c               ó$   € V ^8„  d   QhRRRRRR/# )r	   Únodeúonnx.NodeProtoÚinput_name_to_nodesúdict[str, list[onnx.NodeProto]]Úoutput_name_to_nodeúdict[str, onnx.NodeProto]r   )r   s   "r   r   r      s(   € ÷ 
"ñ 
"àð
"ð =ð
"ð 7ñ	
"r   c                ó   € \         h)zm
Interface function for derived fusion classes. Tries to fuse a node sequence containing
the specified node.
)ÚNotImplementedError)r   r   r!   r#   s   &&&&r   ÚfuseÚFusion.fuse   s
   € ô "Ð!r   c               ó   € V ^8„  d   QhRR/# )r	   ÚreturnÚboolr   )r   s   "r   r   r   *   s   € ÷ ñ �tñ r   c                ó8  € V P                   P                  4       pV P                   P                  4       pV P                   P                  4        F2  pVP                  V P
                  8X  g   K   V P                  W1V4       K4  	  V P                   P                  V P                  4       V P                   P                  V P                  4       \        V P                  ;'       g    V P                  4      pV'       d   V P                   P                  4        V# )z/
Apply graph fusion on the entire model graph.
)r
   r!   r#   ÚnodesÚop_typer   r'   Úremove_nodesr   Ú	add_nodesr   r+   Úremove_unused_constant)r   r!   r#   r   Úgraph_updateds   &    r   ÚapplyÚFusion.apply*   sË   € ð #Ÿj™j×<Ñ<Ó>ÐØ"Ÿj™j×<Ñ<Ó>Ðà—J‘J×$Ñ$Ö&ˆDØ�|‰|˜t×2Ñ2Ö2Ø—	‘	˜$Ð5HÖIñ 'ð 	�
‰
×Ñ × 4Ñ 4Ô5Ø�
‰
×Ñ˜T×.Ñ.Ô/ä˜T×1Ñ1×FÐF°T×5FÑ5FÓGˆçØ�J‰J×-Ñ-Ô/àÐr   c                	óà   € V P                   pV P                  f*   V P                  P                  V4      pV^,           V n        V V P                  : 2pV ;P                  ^,          un        V# ©N)r   r   r
   Úget_largest_node_name_suffix)r   ÚprefixÚlargest_suffixÚnew_names   &   r   Úcreate_unique_node_nameÚFusion.create_unique_node_name?   se   € Ø×+Ñ+ˆà×%Ñ%Ò-Ø"&§*¡*×"IÑ"IÈ&Ó"QˆNØ)7¸!Õ);ˆDÔ&à�X˜d×8Ñ8Ñ;Ð<ˆØ×"Ò" aÕ'Õ"àˆr   c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r	   r   úlist[onnx.NodeProto]Úkeep_outputsú	list[str]r!   r"   r#   r$   r*   r+   r   )r   s   "r   r   r   L   s:   € ÷ ñ Ø-ðàðð =ðð 7ð	ð
 
ñr   c                	ó’   € V  F@  pVP                    F-  pWQ9   d   K  WR9   g   K  W%,           F  pW`9  g   K     R # 	  K/  	  KB  	  R# )FT)Úoutput)r   r?   r!   r#   Únode_to_removeÚoutput_to_removeÚimpacted_nodes   &&&&   r   Úis_safe_to_fuse_nodesÚFusion.is_safe_to_fuse_nodesK   sM   € ó .ˆNØ$2×$9Ô$9Ð Ø#Ô3Ùà#Ö:Ø)<×)NÐ)N˜Ø(Ö?ä#(ó *Oó %:ñ .ñ r   c               ó    € V ^8„  d   QhRRRR/# )r	   r   r    Úattribute_namer   r   )r   s   "r   r   r   _   s   € ÷ ñ  ð Àñ r   c                	ó”   € V P                    F7  pVP                  V8X  g   K  \        P                  P	                  V4      pVu # 	  R # r6   )Ú	attributeÚnameÚonnxÚhelperÚget_attribute_value)r   rI   ÚattrÚvalues   &&  r   Úget_node_attributeÚFusion.get_node_attribute^   s:   € à—N”NˆDØ�y‰y˜NÖ*ÜŸ™×7Ñ7¸Ó=�Ø’ñ #ñ r   c               ó$   € V ^8„  d   QhRRRRRR/# )r	   Únode_outputr   Ú
child_noder    r*   Úintr   )r   s   "r   r   r   g   s!   € ÷ ñ  ð °.ð ÀSñ r   c                	óV   € \        VP                  4       F  w  r#W08X  g   K  Vu # 	  R# )é   éÿÿÿÿ)Ú	enumerateÚinput)rU   rV   ÚindexÚ
input_names   &&  r   Úinput_indexÚFusion.input_indexf   s,   € ä!*¨:×+;Ñ+;Ö!<ÑˆEØÖ(Ø’ñ "=ð ˆ	r   c               ó   € V ^8„  d   QhRR/# )r	   r*   z	list[int]r   )r   s   "r   r   r   n   s   € ÷ 	ñ 	¨Yñ 	r   c                	ó6  € . pV P                   P                   F|  pVP                  R 4      '       d   VP                  VP                  4       K7  VP                  R4      '       d   VP                  VP
                  4       Kk  VP                  R4       K~  	  V# )Ú	dim_valueÚ	dim_paramÚ?)ÚshapeÚdimÚHasFieldÚappendrc   rd   )Útensor_typeÚ
shape_listÚds   &  r   Útensor_shape_to_listÚFusion.tensor_shape_to_listm   su   € àˆ
Ø×"Ñ"×&Ô&ˆAØ�z‰z˜+×&Ò&Ø×!Ñ! !§+¡+Ö.Ø—‘˜K×(Ò(Ø×!Ñ! !§+¡+Ö.à×!Ñ! #Ö&ñ 'ð Ðr   c               ó   € V ^8„  d   QhRR/# )r	   r   r    r   )r   s   "r   r   r   y   s   € ÷ ñ  ~ñ r   c                	óŠ   € \        VP                  4       F)  w  r#V P                  P                  V4      pVf   K&  W$3u # 	  R# )N©NN)r[   r\   r
   Úget_constant_value)r   r   ÚiÚinprQ   s   &&   r   Úget_constant_inputÚFusion.get_constant_inputy   s@   € Ü §
¡
Ö+‰FˆAØ—J‘J×1Ñ1°#Ó6ˆEØÔ Ø�x’ñ ,ð
 Ðr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r	   r   r    Úexpected_valueÚfloatÚdeltar*   rW   r   )r   s   "r   r   r   �   s*   € ÷ ñ ¨ð Èð ÐV[ð Ðknñ r   c                	ó†   € V P                  V4      w  rEVe*   VP                  ^8X  d   \        WR,
          4      V8  d   V# R# )NrZ   )ru   ÚsizeÚabs)r   r   rx   rz   rs   rQ   s   &&&&  r   Úfind_constant_inputÚFusion.find_constant_input�   s>   € Ø×*Ñ*¨4Ó0‰ˆØÒ §¡¨q¤´S¸Õ9OÓ5PÐSXÔ5XØˆHàˆ	r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r	   r   r    rx   ry   rz   r*   r+   r   )r   s   "r   r   r   ˆ   s0   € ÷ Jñ J ~ð JÀuð JÐUZð JÐjnñ Jr   c                	ó,   € V P                  WV4      ^ 8¬  # )r   )r~   )r   r   rx   rz   s   &&&&r   Úhas_constant_inputÚFusion.has_constant_inputˆ   s   € Ø×'Ñ'¨¸eÓDÈÑIÐIr   c               ó$   € V ^8„  d   QhRRRRRR/# )r	   Úoutput_namer   ÚrankrW   r*   r+   r   )r   s   "r   r   r   ‹   s!   € ÷ ñ ¸3ð Àcð Èdñ r   c                	ó€   € V P                   P                  V4      pVf   R# \        VP                  4      V8w  d   R# R# )NFT)r
   rr   Úlenrf   )r   r…   r†   rQ   s   &&& r   Úis_constant_with_specified_rankÚ&Fusion.is_constant_with_specified_rank‹   s5   € Ø—
‘
×-Ñ-¨kÓ:ˆØŠ=Ùäˆu�{‰{Ó˜tÔ#Ùár   Nc          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r	   r   r    Úparent_op_typer   r#   ú dict[str, onnx.NodeProto] | NoneÚexcluder>   r*   z(tuple[onnx.NodeProto | None, int | None]r   )r   s   "r   r   r   •   s<   € ÷ ñ àðð ðð >ð	ð
 &ðð 
2ñr   c                óÚ   € Vf   V P                   P                  4       p\        VP                  4       F3  w  rVWc9   g   K  W6,          pVP                  V8X  g   K(  Wt9  g   K0  Wu3u # 	  R# )aÄ  
Find parent node based on constraints on op_type.

Args:
    node: current node.
    parent_op_type (str): constraint of parent node op_type.
    output_name_to_node (dict): dictionary with output name as key, and node as value.
    exclude (list): list of nodes that are excluded (not allowed to match as parent).

Returns:
    parent: The matched parent node. None if not found.
    index: The input index of matched parent node. None if not found.
rq   )r
   r#   r[   r\   r.   )r   r   rŒ   r#   rŽ   rs   rt   Úparents   &&&&&   r   Úmatch_first_parentÚFusion.match_first_parent•   sa   € ð( Ò&Ø"&§*¡*×"@Ñ"@Ó"BÐä §
¡
Ö+‰FˆAØÖ)Ø,Õ1�Ø—>‘> ^Ö3¸Ö8MØ!˜9Ò$ñ	 ,ð Ðr   c               ó4   € V ^8„  d   QhRRRRRRRRR	R
RRRR/# )r	   r   r    rŒ   r   r_   z
int | Noner#   r�   rŽ   r>   Úreturn_indiceúlist[int] | Noner*   úonnx.NodeProto | Noner   )r   s   "r   r   r   ´   sP   € ÷ -ñ -àð-ð ð-ð  ð	-ð
 >ð-ð &ð-ð (ð-ð 
ñ-r   c                óp  € Vf   Q hVe
   V^ 8¼  g   Q hVf   V P                   P                  4       pVf,   V P                  WWE4      w  rxVe   VP                  V4       V# V\	        VP
                  4      8¼  d   R# V P                   P                  WV4      pVe   VP                  V8X  d	   Wu9  d   V# R# )aÂ  
Find parent node based on constraints on op_type and index.
When input_index is None, we will find the first parent node based on constraints,
and return_indice will be appended the corresponding input index.

Args:
    node (str): current node name.
    parent_op_type (str): constraint of parent node op_type.
    input_index (int or None): only check the parent given input index of current node.
    output_name_to_node (dict): dictionary with output name as key, and node as value.
    exclude (list): list of nodes that are excluded (not allowed to match as parent).
    return_indice (list): a list to append the input index when input_index is None.

Returns:
    parent: The matched parent node.
N)r
   r#   r‘   ri   rˆ   r\   Ú
get_parentr.   )	r   r   rŒ   r_   r#   rŽ   r”   r�   r]   s	   &&&&&&&  r   Úmatch_parentÚFusion.match_parent´   s¸   € ð2 ÒÐÐØÒ" k°QÔ&6Ð6Ð6àÒ&Ø"&§*¡*×"@Ñ"@Ó"BÐàÒØ ×3Ñ3°DÐJ]Óg‰MˆFØÒ(Ø×$Ñ$ UÔ+ØˆMàœ#˜dŸj™j›/Ô)áà—‘×&Ñ& tÐ:MÓNˆØÒ &§.¡.°NÔ"BÀvÔG\ØˆMár   c               ó0   € V ^8„  d   QhRRRRRRRRR	RR
R/# )r	   r   r    Úparent_op_typesr@   Úparent_input_indexr•   r#   r�   r”   r*   zlist[onnx.NodeProto] | Noner   )r   s   "r   r   r   ã   sF   € ÷ /ñ /àð/ð #ð/ð -ð	/ð
 >ð/ð (ð/ð 
%ñ/r   c           
     ó*  € Ve   \        V4      \        V4      8X  g   Q hVf   V P                  P                  4       pTp. p\        V4       FB  w  r‰T P	                  TT	Ve	   W8,          MRV. VR7      p
V
f    R# VP                  V
4       T
pKD  	  V# )aâ  
Find a sequence of input edges based on constraints on parent op_type and index.
When input_index is None, we will find the first parent node based on constraints,
and return_indice will be appended the corresponding input index.

Args:
    node (str): current node name.
    parent_op_types (str): constraint of parent node op_type of each input edge.
    parent_input_index (list): constraint of input index of each input edge. None means no constraint.
    output_name_to_node (dict): dictionary with output name as key, and node as value.
    return_indice (list): a list to append the input index
                          When there is no constraint on input index of an edge.

Returns:
    parents: a list of matched parent node.
N)rŽ   r”   )rˆ   r
   r#   r[   r™   ri   )r   r   rœ   r�   r#   r”   Úcurrent_nodeÚmatched_parentsrs   r.   Úmatched_parents   &&&&&&     r   Úmatch_parent_pathÚFusion.match_parent_pathã   s¯   € ð0 Ò)ÜÐ)Ó*¬c°/Ó.BÔBÐBÐBàÒ&Ø"&§*¡*×"@Ñ"@Ó"BÐàˆØˆÜ# OÖ4‰JˆAØ!×.Ñ.ØØØ);Ò)GÐ"Ö%ÈTØ#ØØ+ð /ó ˆNð Ò%Úà×"Ñ" >Ô2Ø)ŠLñ 5ð Ðr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r	   r   r    Úpathsz!list[tuple[list[str], list[int]]]r#   r$   r*   z9tuple[int, list[onnx.NodeProto] | None, list[int] | None]r   )r   s   "r   r   r     s3   € ÷ ñ àðð 1ðð 7ð	ð
 
Cñr   c                ó�   € \        V4       F6  w  rE. pV P                  W^ ,          V^,          W64      pV'       g   K2  WGV3u # 	  R# )z0
Find a matching parent path to the given node.
)rZ   NN)r[   r¢   )r   r   r¥   r#   rs   Úpathr”   Úmatcheds   &&&&    r   Úmatch_parent_pathsÚFusion.match_parent_paths  sO   € ô ! Ö'‰GˆAØˆMØ×,Ñ,¨T¸µ7¸DÀ½GÐEXÓhˆGß‰wØ =Ð0Ò0ñ	 (ð
 Ðr   c          
     ó,   € V ^8„  d   QhRRRRRRRRR	R
/# )r	   r   r    Ú
child_typer   r!   z&dict[str, list[onnx.NodeProto]] | NoneÚ	recursiver+   r*   r–   r   )r   s   "r   r   r   $  s=   € ÷ ñ àðð ðð Dð	ð
 ðð 
ñr   c                	ó:  € V P                   P                  W4      p\        V4      p\        V4      ^ 8”  de   VP	                  4       pVP
                  V8X  d   V# V'       g   K=  V P                   P                  Ws4      pV F  pVP                  V4       K  	  Kt  R# )r   N)r
   Úget_childrenr   rˆ   Úpopr.   Ú
appendleft)	r   r   r¬   r!   r­   ÚchildrenÚdqrŸ   Úchilds	   &&&&&    r   Úfind_first_child_by_typeÚFusion.find_first_child_by_type$  s   € ð —:‘:×*Ñ*¨4ÓEˆÜ�8‹_ˆÜ�"‹g˜ŒkØŸ6™6›8ˆLØ×#Ñ# zÔ1Ø#Ð#ç‰yØŸ:™:×2Ñ2°<ÓU�Û%�EØ—M‘M %Ö(ó &ñ r   )r   r   r   r
   r   r   r   )g�íµ ÷Æ°>)NNN)NT)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   r'   r3   r;   ÚstaticmethodrF   rR   r_   rm   ru   r~   r‚   r‰   r‘   r™   r¢   r©   rµ   Ú__static_attributes__r   r   r   r   r      s¹   † ñõ*õ
"õò*
ð ôó ðð$ ôó ðð ôó ðð ô	ó ð	õ÷÷Jõð AEØ(*÷ðF #'Ø@DØ(*Ø*.÷-÷^/õb÷ ó r   r   )Ú
__future__r   Úcollectionsr   rM   Ú
onnx_modelr   r   r   r   r   Ú<module>rÁ      s   ðõ #å ã å "÷hó hr   