o
    Xiz;                     @  sZ  d Z ddlmZ ddlmZmZ ddlZddlm	Z	 ddl
mZ ddlmZ ddlmZmZ G d	d
 d
eZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZe Ze Ze Ze Z e Z!e Z"e Z#e Z$e Z%e Z&d!dd Z'dS )"a  Basic rewrite rules for general optimization patterns.

This module contains fundamental optimization rules that are generally applicable
to most ONNX models, including cast elimination, transpose simplification,
shape operation fusion, and other common patterns.
    )annotations)ClassVarSequenceN)ir)	_ir_utils)MatchResult)RewriteRuleClassBaseRewriteRuleSetc                      s<   e Zd ZdZ fddZdd Zddd	ZdddZ  ZS )SqueezeReshapezReplaces ``Reshape(Squeeze(x), [-1]])`` with ``Identity(x)`` for 1D x.

    This pattern arises from the translation of pytorch symints.
    c                   s   t  jddd d S )NSqueezeReshape1dF)remove_nodes)super__init__)self	__class__ a/home/ubuntu/.local/lib/python3.10/site-packages/onnxscript/rewriter/rules/common/_basic_rules.pyr         zSqueezeReshape.__init__c                 C  s   | ||dgS )N)ReshapeSqueezer   opxr   r   r   pattern   r   zSqueezeReshape.patternr   ir.Valuec                 C  
   | |S NIdentityr   r   r   r   rewrite"      
zSqueezeReshape.rewritereturnr   c                 C  s"   ~t  }t|ds|dS |S )N   zInput is not 1D)r   ir_utilshas_rankfail)r   contextr   check_resultr   r   r   check%   s
   
zSqueezeReshape.checkr   r   r#   r   )	__name__
__module____qualname____doc__r   r   r!   r*   __classcell__r   r   r   r   r
      s    
r
   c                   @  ,   e Zd ZdZdd Zddd	ZdddZdS )CastIdentityz8Replaces ``Cast(., to=to)`` by ``Identity`` if possible.c                 C     |j ||dS N)toCastr   r   r   r6   r   r   r   r   0      zCastIdentity.patternr   r   r6   ir.Attrc                 C  r   r   r   r9   r   r   r   r!   3   r"   zCastIdentity.rewriter#   r   c                 C  s"   t  }|j| kr|dS |S )Nz'Input and output types are not the same)r   dtypeas_intr'   )r   r(   r   r6   r)   r   r   r   r*   6   s   
zCastIdentity.checkN)r   r   r6   r;   r,   r-   r.   r/   r0   r   r!   r*   r   r   r   r   r3   -   
    
r3   c                   @  sZ   e Zd ZU dZeejjejjfejjejj	fhZ
ded< dd ZdddZdddZdS )CastCastz=Replaces ``Cast(Cast(X, ...), to=to)`` by ``Cast(X, to=to)``.r   _allowed_type2_type3c                 C  s   |j |j ||d|dS r5   r7   r   r   r   r6   
to_ignoredr   r   r   r   L      zCastCast.patternr   r   r6   r;   rC   r#   r   c                 C  s@   t  }| }| }||f| jvr|d| d| dS |S )Nz;Intermediate cast elimination not recognized as valid from z to z8. Cast-Cast rule may be incomplete for this combination.)r   r=   rA   r'   )r   r(   r   r6   rC   r)   type2type3r   r   r   r*   O   s   zCastCast.checkc                 C  r4   r5   r7   rB   r   r   r   r!   Z   r:   zCastCast.rewriteN)r   r   r6   r;   rC   r;   r#   r   )r   r   r6   r;   rC   r;   )r-   r.   r/   r0   	frozensetr   DataTypeFLOATFLOAT16BFLOAT16rA   __annotations__r   r*   r!   r   r   r   r   r@   =   s   
 
r@   c                   @  s,   e Zd ZdZdd ZdddZdddZdS )ExpandIdentityz<Replaces ``Expand(..., shape)`` by ``Identity`` if possible.c                 C  s   | ||S r   )Expandr   r   r   shaper   r   r   r   a   s   zExpandIdentity.patternr   r   rP   c                 C  r   r   r   rO   r   r   r   r!   d   r"   zExpandIdentity.rewriter#   r   c                 C  sr   t  }|jd u r|dS |j }d u r|dS |jt|j  kr7|d|j d|j   dS |S )Nz.Shape is not a constant and cannot be guessed.zInput shape is not known.zInput shape z does not match the shape .)r   const_valuer'   rP   dimstuplenumpytolist)r   r(   r   rP   r)   x_shaper   r   r   r*   g   s   


zExpandIdentity.checkN)r   r   rP   r   r,   r>   r   r   r   r   rM   ^   r?   rM   c                   @  r2   )ReshapeReshapezReplaces ``Reshape(Reshape(X, ...), shape)`` by ``Reshape(X, shape)``.
    The pattern matches only if second reshape reshapes into a shape
    with positive values.
    c                 C     | | |||S r   )r   )r   r   r   shape_ignoredrP   r   r   r   r   |   r   zReshapeReshape.patternr   r   rZ   rP   c                 C  s*   | tj| j|jd}|j||| jdS )Nname)	allowzero)initializerr   Tensor
_new_shaper\   r   
_allowzero)r   r   r   rZ   rP   	new_shaper   r   r   r!      s   zReshapeReshape.rewriter#   r   c           
      C  s  t  }t| }d u r|dS t||j| _|jd j	 }d ur:t
|D ]\}}	t|	tr9|	dkr9|	| j|< q'|jd jdd| _| jdkrSt| jdkrS|S t| jdkrft| jdk rf|dS t| jdkdkru|dS d | _t| jdkd| j| _|S )NzShape is not a constant.r   r]   r$   z.Shape cannot contain both 0 and -1 dimensions.z/Shape cannot contain more than one 0 dimension.r   )r   r%   get_numpy_valuer'   nparrayr<   r`   output_valuesrP   	enumerate
isinstanceintnodes
attributesget_intra   anycount_nonzerowhere)
r   r(   r   rZ   rP   r)   np_shapereshape_outputidimr   r   r   r*      s&   



zReshapeReshape.checkN)r   r   rZ   r   rP   r   r,   r>   r   r   r   r   rX   v   s
    
rX   c                   @  s*   e Zd ZdZdd ZdddZdd	 Zd
S )SlicesSplitzTReplaces ``Slice(x, ...), Slice(x, ...)``
    by ``Split(x, ...)`` if possible.
    c	           	      C  s    | ||||| ||||fS r   )Slice	r   r   r   begin0end0axes0begin1end1axes1r   r   r   r      s    zSlicesSplit.patternr#   r   c	                 C  s  t  }	|jd u s|jd u s|j  |j  kr |	dS |j  }
t|
dkr2|	dS |jd ur=t|j}n|	dS |
d dkrU|
d |d krU|	dS |jd u si|jd u si|jd u si|jd u rn|	dS |j  dgkr}|	d	S |j  |j  |j  }}}|d |d kr|	d
S |j}|d u r|	dS |d }t|ts|	dS ||d kr|	dS |d |d kr|	dS |	S )Nz#Axes are not equal or not constant.r$   z!Axes has more than one dimension.zInput rank is not known.r   r   z!Axes is not -1 or last dimension.z%Begin or end are not constant values.zFirst begin value is not 0.zEnd0 is not equal to Begin1.zShape is not known.zLast dimension is not known.z$Last dimension is not equal to End1.   z&Last dimension is not equal to Begin1.)	r   rR   rU   rV   r'   lenrP   rh   ri   )r   r(   r   rw   rx   ry   rz   r{   r|   r)   axesranke0b1e1rP   last_dimr   r   r   r*      sJ   



















zSlicesSplit.checkc	           	      C  s   |j |ddddS )Nr}   r   )num_outputsaxis_outputs)Splitrv   r   r   r   r!      s   zSlicesSplit.rewriteNr,   r-   r.   r/   r0   r   r*   r!   r   r   r   r   rt      s
    
-rt   c                   @  s,   e Zd ZdZdd Zdd
dZdddZdS )TransposeIdentityzNReplaces ``Transpose(. perm=perm)``
    when the permutation is identity.
    c                 C  r4   N)perm	Transposer   r   r   r   r   r   r   r      r:   zTransposeIdentity.patternr   r   r   r;   r#   r   c                 C  sT   t  }| r|dS |jtjjkr%t| }|tt	t
|kr%|S |dS )N%Permutation is a reference attribute.zPermutation is not identity.)r   is_refr'   typer   AttributeTypeINTSrT   as_intsranger~   )r   r(   r   r   r)   	perm_intsr   r   r   r*      s   

zTransposeIdentity.checkc                 C  r   r   r   r   r   r   r   r!      r"   zTransposeIdentity.rewriteN)r   r   r   r;   r#   r   )r   r   r   r;   r   r   r   r   r   r      s
    

r   c                   @  sD   e Zd ZdZdd ZdddZdddZ	ddddZdddZdS ) TransposeTransposeziReplaces ``Transpose(Transpose(., perm=perm1), perm=perm2)``
    when both permutations are inverse.
    c                 C  s   |j |j ||d|dS r   r   )r   r   r   perm1perm2r   r   r   r      rD   zTransposeTranspose.patternr   r   r   r;   r   r#   r   c                 C  s$   t  }| s| r|dS |S )Nr   )r   r   r'   )r   r(   r   r   r   r)   r   r   r   r*      s   
zTransposeTranspose.checkr   Sequence[int]on	list[int]c                 C  sH   t |t |ksJ ddd |D }t|D ]
\}}|| ||< q|S )Nzlength mismatchc                 S  s   g | ]}d qS )r   r   ).0rr   r   r   r   
<listcomp>  s    z7TransposeTranspose._apply_transpose.<locals>.<listcomp>)r~   rg   )r   r   r   resrr   pr   r   r   _apply_transpose   s
   z#TransposeTranspose._apply_transposeNpermslist[Sequence[int]]list[int] | Nonec                 C  s6   |d u rt tt|d }|D ]}| ||}q|S )Nr   )listr   r~   r   )r   r   r   r   r   r   r   _apply_transposes  s
   z$TransposeTranspose._apply_transposesc                 C  sJ   t tt| }| | | g}||kr||S |j||dS r   )r   r   r~   r   r   r    r   )r   r   r   r   r   firstlastr   r   r   r!     s
   
zTransposeTranspose.rewrite)r   r   r   r;   r   r;   r#   r   )r   r   r   r   r#   r   r   )r   r   r   r   r#   r   )r   r   r   r;   r   r;   )	r-   r.   r/   r0   r   r*   r   r   r!   r   r   r   r   r      s    

	r   c                   @  r2   )UnsqueezeUnsqueezezFReplaces ``Unsqueeze(Unsqueeze(., axes1), axes2)`` with one Unsqueeze.c                 C  rY   r   )	Unsqueeze)r   r   r   r|   axes2r   r   r   r     r   zUnsqueezeUnsqueeze.patternr   r   r|   r   c                 C  sR   t |}t |}||k r||gn||d g}|||jtj|tjjddS )Nr$   )r<   )value)r%   get_singleton_valuer   Constantr   tensorrH   INT64)r   r   r   r|   r   v1v2r   r   r   r   r!     s   

"zUnsqueezeUnsqueeze.rewriter#   r   c                 C  sV   t  }~~t|}t|}|d u s|d u r|dS |dk s$|dk r)|dS |S )NzAxes are not constant.r   zAxes are negative.)r   r%   r   r'   )r   r(   r   r|   r   r)   r   r   r   r   r   r*   #  s   



zUnsqueezeUnsqueeze.checkN)r   r   r|   r   r   r   r,   r>   r   r   r   r   r     s
    
r   c                   @  s.   e Zd ZdZdddZdddZdd
dZdS )Flatten2Reshapez"Convert ``Flatten(x)`` to Reshape.r   r   c                 C  r   r   )Flattenr   r   r   r   r   4  r"   zFlatten2Reshape.patternc                 C  s*   | tj| j|j dd}|||S )Nz/shaper[   )r^   r   r_   r`   r\   r   )r   r   r   rb   r   r   r   r!   7  s   zFlatten2Reshape.rewriter#   r   c           
      C  sT  t  }tddgd| _|jjdd}d }|j }d ur)t|}|dk r)||7 }|dkr3d| jd< n|dkr=d| jd< n	||krFd| jd< |j	d j }d urct
|D ]\}}	t|	trb|	| j|< qT|d urtdd |d | D rt|d | | jd< tdd ||d  D rt||d  | jd< t| jdkdkr|d	S |S )
Nr   int64r   r$   r   c                 s      | ]}t |tV  qd S r   rh   ri   r   rs   r   r   r   	<genexpr>W      z(Flatten2Reshape.check.<locals>.<genexpr>c                 s  r   r   r   r   r   r   r   r   Y  r   z Impossible to compute new shape.)r   rd   re   r`   rootrk   rl   rP   r~   rf   rg   rh   ri   allprodrn   r'   )
r   r(   r   r)   r   
input_rankinput_shapeoutput_shaperr   rs   r   r   r   r*   ;  s6   



zFlatten2Reshape.checkNr+   )r   r   r#   r   r>   r   r   r   r   r   1  s
    

r   r#   r	   c                   C  s   t ttttttttt	t
g
S )a  Returns a set of basic optimization rules.

    These rules perform fundamental optimizations such as:
    - Eliminating redundant cast operations
    - Simplifying consecutive operations of the same type
    - Removing identity operations
    - Optimizing shape manipulation operations

    These rules are generally safe to apply as a first optimization pass
    before other more specialized optimizations.

    Returns:
        RewriteRuleSet: A collection of basic optimization rules
    )r	   cast_cast_ruleno_op_cast_ruleno_op_expand_ruleflatten_to_reshape_rulereshape_reshape_ruleslice_split_ruleno_op_transpose_ruletranspose_transpose_ruleunsqueeze_unsqueeze_rulesqueeze_reshape_1d_ruler   r   r   r   basic_optimization_ruleso  s   r   )r#   r	   )(r0   
__future__r   typingr   r   rU   rd   
onnxscriptr   onnxscript.rewriterr   r%   onnxscript.rewriter._basicsr   !onnxscript.rewriter._rewrite_ruler   r	   r
   r3   r@   rM   rX   rt   r   r   r   r   ruler   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s:   !,9&2