o
    i                     @   sL   d dl mZ d dlmZ d dlmZ d dlmZ eeZ	G dd deZ
dS )    )	getLogger)Fusion)NumpyHelper)	OnnxModelc                       sF   e Zd Zdef fddZ fddZdd Zdd	 Zd
d Z  Z	S )FusionConstantFoldmodelc                    s   t  |ddg d| _d S )N 	Transposer   )super__init__count)selfr   	__class__ g/home/kim/smarthome/.venv/lib/python3.10/site-packages/onnxruntime/transformers/fusion_constant_fold.pyr      s   
zFusionConstantFold.__init__c                    s.   t    | jdkrtd| j  d S d S )Nr   zConstant Folded: )r
   applyr   loggerinfo)r   r   r   r   r      s   

zFusionConstantFold.applyc                 C   s    |  ||| | ||| dS )zX
        Apply multiple fusions on Transpose nodes that can be constant folded.
        N)fuse_1fuse_2)r   nodeinput_name_to_nodesoutput_name_to_noder   r   r   fuse   s   zFusionConstantFold.fusec                 C   s  t |jdkst |jdkrtd dS | j|jd }|du r)td dS d}||jd  D ]}|jdkr@t |jdksDd} nq2|rNtd	 dS ||jd  D ]}|jd
kse|jdksed} nqU|rotd dS t	|}t |j
dkrtd dS |j}|j}	| | | j||	|j
d |j
d g|jd ||jd  D ]H}tt |jD ]>}
|j|
 |jd kr|jd |j|
< |jd
kr|
dks|
dkr|
dkrdnd}t|jD ]\}}|j|krd|j| _qqq| j| |  jd7  _dS )z
        Constant fold any initializer data representing a MatMul's
        weights that are stored in a Transpose op

        Ex: Transpose --> Gemm or Transpose --> MatMul
           :fuse_constant_fold: node has more than one input or outputNr   z8fuse_constant_fold: failed to identify initializer inputFr	   TzAfuse_constant_fold: other non-Transpose nodes use the initializerZGemmZMatMulzOfuse_constant_fold: other non-Gemm and non-MatMul nodes use the transposed data   z7fuse_constant_fold: shape of initializer data is not 2D)name	data_typedimsvalsZtransAZtransB)leninputoutputr   debugr   Zget_initializerZop_typer   Zto_arrayshaper   r   Zremove_initializerZadd_initializerTrange	enumerate	attributeinodes_to_removeappendr   )r   r   r   r   protoskip
child_nodeweightr   Zdtyper+   keyjZattr_keyr   r   r   r       sd   






	
zFusionConstantFold.fuse_1c                 C   s   t |jdkst |jdkrtd dS | j|dd}|du r(td dS t |jdks6t |jdkr=td dS |jd j}|jd j}||krTtd dS |jd }||jd  }|D ]}	t	|	jD ]\}
}||jd kry||	j|
< qiqb| j
| | j
| |  jd7  _dS )	z
        Constant fold any Transpose --> Transpose ops since the root input
        is the final result

        Ex: root_input --> Transpose --> Transpose --> next_node to root_input --> next_node
        r   r   Nr	   r   z<fuse_constant_fold: failed to identify parent Transpose nodezAfuse_constant_fold: parent node has more than one input or outputz@fuse_constant_fold: Transpose node permutations aren't identical)r"   r#   r$   r   r%   r   Zmatch_parentr*   Zintsr)   r,   r-   r   )r   r   r   r   Zparent_nodeZ	node_permZparent_node_permZ
root_inputZoutput_nodesZoutput_noder+   Zinput_r   r   r   r   h   s4   





zFusionConstantFold.fuse_2)
__name__
__module____qualname__r   r   r   r   r   r   __classcell__r   r   r   r   r      s    Hr   N)loggingr   Zfusion_baser   Zfusion_utilsr   Z
onnx_modelr   r4   r   r   r   r   r   r   <module>   s   