
     Ng.                    L    d dl mZ d dlmZ d dlZddlmZ  G d d          ZdS )    )annotations)dequeN   )	ONNXModelc                      e Zd ZdZdCdZdDdZdEdZd ZedFd            Z	edGd            Z
edHd            ZedId            ZdJd ZdKdLd%ZdKdMd&ZdNd)Zd*g fdOd/Zd*d*g d*fdPd5Z	 	 	 dQdRd9ZdSd=Z	 	 dTdUdBZd*S )VFusionz!
    Base class for fusions.
    modelr   fused_op_typestrsearch_op_typec                    || _         || _        || _        g | _        g | _        | j        dz   | j         z   dz   | _        d | _        d S )N_fused__)r   r
   r	   nodes_to_removenodes_to_add_new_node_name_prefix_new_node_name_suffix)selfr	   r
   r   s       c/var/www/html/ai-engine/env/lib/python3.11/site-packages/onnxruntime/quantization/fusions/fusion.py__init__zFusion.__init__   sU    #1"/ %
%'"$%)%7)%CdFY%Y\_%_"%)"""    nodeonnx.NodeProtoinput_name_to_nodesdict[str, list[onnx.NodeProto]]output_name_to_nodedict[str, onnx.NodeProto]c                    t           )z
        Interface function for derived fusion classes. Tries to fuse a node sequence containing
        the specified node.
        )NotImplementedError)r   r   r   r   s       r   fusezFusion.fuse   s
     "!r   returnboolc                   | j                                         }| j                                         }| j                                         D ])}|j        | j        k    r|                     |||           *| j                             | j                   | j         	                    | j
                   t          | j        p| j
                  }|r| j                                          |S )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   applyzFusion.apply*   s     #j<<>>"j<<>>J$$&& 	J 	JD|t222		$ 35HIII
 4555
T.///T1FT5FGG 	0J--///r   c                    | j         }| j        $| j                            |          }|dz   | _        | | j        }| xj        dz  c_        |S )N   )r   r   r	   get_largest_node_name_suffix)r   prefixlargest_suffixnew_names       r   create_unique_node_namezFusion.create_unique_node_name?   sa    +%-"&*"I"I&"Q"QN)7!);D&<d8<<""a'""r   r   list[onnx.NodeProto]keep_outputs	list[str]c                ^    | D ])}|j         D ]}||v r||v r||         D ]}|| vr   dS  *dS NFT)output)r   r3   r   r   node_to_removeoutput_to_removeimpacted_nodes          r   is_safe_to_fuse_nodeszFusion.is_safe_to_fuse_nodesK   s~     . 		) 		)N$2$9 ) ) #|33#':::)<=M)N ) )(??#(5555 @) tr   attribute_namec                v    | j         D ]0}|j        |k    r#t          j                            |          }|c S 1d S )N)	attributenameonnxhelperget_attribute_value)r   r<   attrvalues       r   get_node_attributezFusion.get_node_attribute^   sJ    N 	 	DyN**77== + tr   node_output
child_nodeintc                N    t          |j                  D ]\  }}|| k    r|c S dS )N)	enumerateinput)rF   rG   index
input_names       r   input_indexzFusion.input_indexf   s?    !*:+;!<!< 	 	E:[(( )rr   	list[int]c                   g }| j         j        D ]w}|                    d          r|                    |j                   2|                    d          r|                    |j                   b|                    d           x|S )N	dim_value	dim_param?)shapedimHasFieldappendrR   rS   )tensor_type
shape_listds      r   tensor_shape_to_listzFusion.tensor_shape_to_listm   s    
"& 	' 	'Azz+&& '!!!+....K(( '!!!+....!!#&&&&r   c                ~    t          |j                  D ]'\  }}| j                            |          }|||fc S (dS )NNN)rK   rL   r	   get_constant_value)r   r   iinprD   s        r   get_constant_inputzFusion.get_constant_inputy   sS    
++ 	  	 FAsJ11#66E %x ! zr   ư>expected_valuefloatdeltac                    |                      |          \  }}|#|j        dk    rt          ||z
            |k     r|S dS )Nr,   rJ   )rb   sizeabs)r   r   rd   rf   r`   rD   s         r   find_constant_inputzFusion.find_constant_input   sK    **4005qS9O5P5PSX5X5XHrr   c                8    |                      |||          dk    S Nr   )rj   )r   r   rd   rf   s       r   has_constant_inputzFusion.has_constant_input   s    ''neDDIIr   output_namerankc                v    | j                             |          }|dS t          |j                  |k    rdS dS r6   )r	   r_   lenrU   )r   rn   ro   rD   s       r   is_constant_with_specified_rankz&Fusion.is_constant_with_specified_rank   s@    
--k::=5u{t##5tr   Nparent_op_type dict[str, onnx.NodeProto] | Noneexclude(tuple[onnx.NodeProto | None, int | None]c                    || j                                         }t          |j                  D ]&\  }}||v r||         }|j        |k    r
||vr||fc S 'dS )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.
        Nr^   )r	   r   rK   rL   r%   )r   r   rs   r   ru   r`   ra   parents           r   match_first_parentzFusion.match_first_parent   s~    ( &"&*"@"@"B"B
++ 	% 	%FAs))),S1>^33g8M8M!19$$$zr   rO   
int | Nonereturn_indicelist[int] | Noneonnx.NodeProto | Nonec                V   |J ||dk    sJ || j                                         }|4|                     ||||          \  }}||                    |           |S |t	          |j                  k    rdS | j                             |||          }||j        |k    r||vr|S dS )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.
        Nr   )r	   r   ry   rX   rq   rL   
get_parentr%   )	r   r   rs   rO   r   ru   r{   rx   rM   s	            r   match_parentzFusion.match_parent   s    2 "kQ&6&6&6&6&"&*"@"@"B"B 33D.J]_fggMFE($$U+++M#dj//))4&&t[:MNN&.N"B"BvU\G\G\Mtr   parent_op_typesparent_input_indexlist[onnx.NodeProto] | Nonec           	     8   |"t          |          t          |          k    sJ || j                                        }|}g }t          |          D ]F\  }}	|                     ||	|||         nd|g |          }
|
 dS |                    |
           |
}G|S )aJ  
        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)ru   r{   )rq   r	   r   rK   r   rX   )r   r   r   r   r   r{   current_nodematched_parentsr`   r%   matched_parents              r   match_parent_pathzFusion.match_parent_path   s    0 ))**c/.B.BBBBB&"&*"@"@"B"B#O44 	* 	*JAw!..);)G"1%%T#+ /  N %tt"">222)LLr   paths!list[tuple[list[str], list[int]]]9tuple[int, list[onnx.NodeProto] | None, list[int] | None]c                    t          |          D ]5\  }}g }|                     ||d         |d         ||          }|r|||fc S 6dS )z@
        Find a matching parent path to the given node.
        r   r,   )rJ   NN)rK   r   )r   r   r   r   r`   pathr{   matcheds           r   match_parent_pathszFusion.match_parent_paths  sn     !'' 	1 	1GAtM,,T47DGEXZghhG 1'=00001~r   T
child_type&dict[str, list[onnx.NodeProto]] | None	recursivec                V   | j                             ||          }t          |          }t          |          dk    rk|                                }|j        |k    r|S |r5| j                             ||          }|D ]}|                    |           t          |          dk    kd S rl   )r	   get_childrenr   rq   popr%   
appendleft)	r   r   r   r   r   childrendqr   childs	            r   find_first_child_by_typezFusion.find_first_child_by_type$  s     :**41DEE8__"ggkk6688L#z11## ):22<ATUU% ) )EMM%(((( "ggkk tr   )r	   r   r
   r   r   r   )r   r   r   r   r   r   )r!   r"   )
r   r2   r3   r4   r   r   r   r   r!   r"   )r   r   r<   r   )rF   r   rG   r   r!   rH   )r!   rP   )r   r   )rc   )r   r   rd   re   rf   re   r!   rH   )r   r   rd   re   rf   re   r!   r"   )rn   r   ro   rH   r!   r"   )
r   r   rs   r   r   rt   ru   r2   r!   rv   )r   r   rs   r   rO   rz   r   rt   ru   r2   r{   r|   r!   r}   )NNN)r   r   r   r4   r   r|   r   rt   r{   r|   r!   r   )r   r   r   r   r   r   r!   r   )NT)
r   r   r   r   r   r   r   r"   r!   r}   )__name__
__module____qualname____doc__r   r    r*   r1   staticmethodr;   rE   rO   r\   rb   rj   rm   rr   ry   r   r   r   r    r   r   r   r      s        * * * *
" 
" 
" 
"   *
 
 
    \$    \    \ 	 	 	 \	       J J J J J    AE(*    F #'@D(**.- - - - -f 04@D*./ / / / /b   ( GK      r   r   )
__future__r   collectionsr   r@   
onnx_modelr   r   r   r   r   <module>r      s    # " " " " "        " " " " " "h h h h h h h h h hr   