
    pi                     J    d Z ddlZddlmZmZ  G d dej
                        Zy)zDefine SpaceToDepth fusion.    N   )fusions
onnx_modelc                       e Zd ZdZdej
                  f fdZdej                  de	e
eej                     f   de	e
ej                  f   fdZdej                  de	e
eej                     f   de	e
ej                  f   fdZ xZS )	FusionSpaceToDepthzFusion for SpaceToDepth.modelc                 (    t         |   |dd       y)zXInitialize.

        Args:
            model: An onnx_model.ONNXModel instance.
        SpaceToDepthReshapeN)super__init__)selfr   	__class__s     /opt/services/ai/voice_agent/venv/lib/python3.12/site-packages/onnxruntime/quantization/execution_providers/qnn/fusion_spacetodepth.pyr   zFusionSpaceToDepth.__init__   s     		:    nodeinput_name_to_nodesoutput_name_to_nodec           	          |}fd} ||d      x}7 ||d      x}, ||d      x}! ||d      x}	 ||	d      x}
 ||
d      x}y fd} ||j                   d         x}\ ||j                  d         x}E ||j                  d         x}. ||	j                  d         x} ||j                  d         x}y j                  |d      } j                  |d      } j                  |
d      }t        |      dk7  s8t        |      d	k7  s*t        |      dk7  st        |      d
k7  st        |      dk7  ry|\  }}}}|d   }|||||z  |||z  |gk7  sR|g dk7  sK|||||z  ||z  z  |dz  gk7  s6|g dk7  s/||||dz  ||z  ||z  gk7  s|g dk7  s|||dz  |z  ||z  ||z  gk7  ry j                  j                  |||||	|
|g       t        j                  j                   j                   j                         |j                   d   g|j                  d   g|      } j                  j                  |       y)at  Fuse for early version of YOLO.

        Pattern:

                |     [N, C, H, W]
             Reshape
                |     [N, C, H/blk, blk, W/blk, blk]
            Transpose
                |     [N, C, H/blk, W/blk, blk, blk]
             Reshape
                |     [N, C, H/blk * W/blk, blk * blk]
            Transpose
                |     [N, C, blk * blk, H/blk * W/blk]
             Reshape
                |     [N, C, blk * blk, H/blk, W/blk]
            Transpose
                |     [N, blk * blk, C, H/blk, W/blk]
             Reshape
                |     [N, blk * blk * C, H/blk, W/blk]

        This sequence can be fused into a single SpaceToDepth with blocksize `blk`. Note that unlike DepthToSpace
        supporting DCR or CRD mode, SpaceToDepth only supports DCR mode in its latest opset version (13), which matches
        the pattern here.
        c                     | j                   d   vry| j                   d      }t        |      dkD  s|d   j                  |k7  ry|d   S )zGet target child of given node.r   N   )outputlenop_type)parent_nodetarget_op_typechildrenr   s      r   get_target_childz7FusionSpaceToDepth._fuse_yolo.<locals>.get_target_child8   sY    !!!$,??*;+=+=a+@AH8}q HQK$7$7>$IA;r   	Transposer   Fc                 l    j                   j                  |       }|syj                  |      }|sy|S )z Get shape for given tensor name.N)r   get_tensor_typetensor_shape_to_list)tensor_nametensor_typetensor_shaper   s      r   get_tensor_shapez7FusionSpaceToDepth._fuse_yolo.<locals>.get_tensor_shapeM   s9    **44[AK44[ALr   r   perm         r   )r   r      r(   r   r*   r+   )r   r   r   r+   )r   r+   r   r   r(   )nameinputsoutputs	blocksizeT)inputr   get_node_attributer   nodes_to_removeextendonnxhelper	make_nodefused_op_typecreate_unique_node_namenodes_to_addappend)r   r   r   r   reshape_node1r   transpose_node1reshape_node2transpose_node2reshape_node3transpose_node3reshape_node4r&   input_shapereshape_shape1reshape_shape2reshape_shape3reshape_shape4transpose_perm1transpose_perm2transpose_perm3batchchannelheightwidthr/   s2d_nodes   ` `                        r   
_fuse_yolozFusionSpaceToDepth._fuse_yolo   s   < 		 !1 LL_U!1/9!MMV#3M;#OOX!1/9!MMV#3M;#OOX!1/9!MMV
	  -]-@-@-CDD[M"2=3G3G3J"KKT"2=3G3G3J"KKT"2=3G3G3J"KKT"2=3G3G3J"KKT11/6J11/6J11/6J !>"a'>"a'>"a'>"a' )4%w"1%	ugv/BIuXaOaclmm"44%6Y3F5T]K]2^`ikl`l!mm,.%)Q,)@SUZ^gUg!hh/1%A)?9ATV[_hVh!ii##
	
 ;;((--/!''*+"))!,- ) 
 	  *r   c                 *    | j                  |||       y)a\  Fuse a sequence of Reshape and Transpose nodes into a single SpaceToDepth node.

        Args:
            node: An onnx.NodeProto matching the specified search type (i.e., Reshape).
            input_name_to_nodes: A dict mapping tensor name to consumed nodes.
            output_name_to_node: A dict mapping tensor name to produced node.
        N)rO   )r   r   r   r   s       r   fusezFusionSpaceToDepth.fuse   s     	13FGr   )__name__
__module____qualname____doc__r   	ONNXModelr   r4   	NodeProtodictstrlistrO   rQ   __classcell__)r   s   @r   r   r      s    ";j22 ;{nn{ "#tDNN';";<{ "#t~~"56	{zHnnH "#tDNN';";<H "#t~~"56	Hr   r   )rU   r4    r   r   Fusionr    r   r   <module>r_      s$    "  #UH UHr   