U
    U?h3                     @  s@   d dl mZ d dlZddlmZ ddlmZ G dd deZdS )	    )annotationsN   )	ONNXModel   )Fusionc                      s4   e Zd Zdd fddZddddd	d
Z  ZS )FusionLayerNormalizationr   )modelc                   s   t  |dd d S )NLayerNormalization
ReduceMean)super__init__)selfr   	__class__ c/var/www/html/venv/lib/python3.8/site-packages/onnxruntime/quantization/fusions/fusion_layernorm.pyr      s    z!FusionLayerNormalization.__init__zonnx.NodeProtozdict[str, list[onnx.NodeProto]]zdict[str, onnx.NodeProto])reduce_mean_nodeinput_name_to_nodesoutput_name_to_nodec                 C  s  | j ||}t|dks&t|dkr*dS |jd }|d jdksT|d jd |krXdS t|dkr|d jdks|d jd |krdS d}|D ]"}| j|d|dd}|dk	r qq|dkrdS | |d	d
dddgdddddgfd	d
ddddgddddddgfg|\}}	}
|dk rdS |	d }||kr0dS |	d }| |\}}|dksd|dksd|dkrhdS |	d }| |ddkrdS ||j	d  d }|jdkrdS ||j	d  d }|jd
krdS |g}|
| |
|	dd  |
|||g | ||j	||sdS |jd| |j	d |  }| |dsBdS |jd| |j	d |  }| |dspdS | j
| tjjd|  |jd ||g|j	d gd}|j
tjdt|g | j| dS )a  
        Interface function that tries to fuse a node sequence containing a ReduceMean node into a single
        LayerNormalization node.

              +----------------------+
              |                      |
              |                      v
          [Root] --> ReduceMean -->  Sub  --> Pow --> ReduceMean --> Add --> Sqrt --> Div --> Mul --> Add
                     (axis=2 or -1)  |      (Y=2)   (axis=2 or -1)  (E-6 or E-12 or 0) ^
                                     |                                                 |
                                     +-------------------------------------------------+

         It also handles cases of duplicated sub nodes exported from older version of PyTorch:

              +----------------------+
              |                      v
              |           +-------> Sub-----------------------------------------------+
              |           |                                                           |
              |           |                                                           v
          [Root] --> ReduceMean -->  Sub  --> Pow --> ReduceMean --> Add --> Sqrt --> Div  --> Mul --> Add
              |                      ^
              |                      |
              +----------------------+
        r   r   NSubr   DivF)	recursiveZSqrtAddr
   PowZCastg-C6?   g       @ZMulr	   )nameinputsoutputsepsilon)r   Zget_childrenleninputZop_typeZfind_first_child_by_typeZmatch_parent_pathsZget_constant_inputZfind_constant_inputoutputextendZis_safe_to_fuse_nodesZinput_indexZis_constant_with_specified_rankZnodes_to_removeonnxhelperZ	make_nodeZcreate_unique_node_name	attributeZmake_attributefloatZnodes_to_addappend)r   r   r   r   childrenZ
root_inputZdiv_nodechildZpath_idZparent_nodes_Zsub_nodeZsecond_add_nodeiZ
add_weightZpow_nodeZmul_nodeZlast_add_nodeZsubgraph_nodesZweight_inputZ
bias_inputZnormalize_noder   r   r   fuse   s    
  




zFusionLayerNormalization.fuse)__name__
__module____qualname__r   r-   __classcell__r   r   r   r   r      s   r   )
__future__r   r$   Z
onnx_modelr   Zfusionr   r   r   r   r   r   <module>   s   