
    'iC+                         d dl Z d dlZd dlmZmZmZmZ d dlmZ d dl	m
Z
 d dlmZmZ dedefdZ G d	 d
      Z G d de      Zy)    N)AnyDictListOptional)EinopsError)_product)ParsedExpression	_ellipsisaxesreport_messagec                 T    t        |       dkD  rt        |j                  |             y )Nr   )lenr   format)r   r   s     O/var/www/stems/demucs_env/lib/python3.12/site-packages/einops/layers/_einmix.py_report_axesr   
   s(    
4y1}.//566     c            	            e Zd Zddededee   def fdZdededee   defdZdee   dee	   d	ee   d
ee	   fdZ
d Zd Z xZS )_EinmixMixinpatternweight_shape
bias_shapeaxes_lengthsc                     t         |           || _        || _        || _        || _        | j                  ||||       y)a	  
        EinMix - Einstein summation with automated tensor management and axis packing/unpacking.

        EinMix is a combination of einops and MLP, see tutorial:
        https://github.com/arogozhnikov/einops/blob/main/docs/3-einmix-layer.ipynb

        Imagine taking einsum with two arguments, one of each input, and one - tensor with weights
        >>> einsum('time batch channel_in, channel_in channel_out -> time batch channel_out', input, weight)

        This layer manages weights for you, syntax highlights a special role of weight matrix
        >>> EinMix('time batch channel_in -> time batch channel_out', weight_shape='channel_in channel_out')
        But otherwise it is the same einsum under the hood. Plus einops-rearrange.

        Simple linear layer with a bias term (you have one like that in your framework)
        >>> EinMix('t b cin -> t b cout', weight_shape='cin cout', bias_shape='cout', cin=10, cout=20)
        There is no restriction to mix the last axis. Let's mix along height
        >>> EinMix('h w c-> hout w c', weight_shape='h hout', bias_shape='hout', h=32, hout=32)
        Example of channel-wise multiplication (like one used in normalizations)
        >>> EinMix('t b c -> t b c', weight_shape='c', c=128)
        Multi-head linear layer (each head is own linear layer):
        >>> EinMix('t b (head cin) -> t b (head cout)', weight_shape='head cin cout', ...)

        ... and yes, you need to specify all dimensions of weight shape/bias shape in parameters.

        Use cases:
        - when channel dimension is not last, use EinMix, not transposition
        - patch/segment embeddings
        - when need only within-group connections to reduce number of weights and computations
        - next-gen MLPs (follow tutorial link above to learn more!)
        - in general, any time you want to combine linear layer and einops.rearrange

        Uniform He initialization is applied to weight tensor.
        This accounts for the number of elements mixed and produced.

        Parameters
        :param pattern: transformation pattern, left side - dimensions of input, right side - dimensions of output
        :param weight_shape: axes of weight. A tensor of this shape is created, stored, and optimized in a layer
               If bias_shape is not specified, bias is not created.
        :param bias_shape: axes of bias added to output. Weights of this shape are created and stored. If `None` (the default), no bias is added.
        :param axes_lengths: dimensions of weight tensor
        )r   r   r   r   N)super__init__r   r   r   r   initialize_einmix)selfr   r   r   r   	__class__s        r   r   z_EinmixMixin.__init__   sL    T 	($(,:\h 	 	
r   c                 
   |j                  d      \  }}t        |      }t        |      }t        |      }	t        t        j	                  |j
                  h |j
                  |	j
                        d       |	j                  rt        d      |j                  s|j                  r@|j                  r|j                  st        d|       |j                  rt        d|       t        d |||	fD              rt        d      d|v sd	|v rt        d
|       d }
d }d }t        d |j                  D              rrg }|j                  D ]  }||z  }	 |D cg c]  }|t        k7  r|nd }}dj                  |      }| d| }
|j                         D ci c]  \  }}||v s|| }}}t        d |j                  D              s|j                  rJg }|j                  D ]  }||z  }	 |D cg c]  }|t        k7  r|nd }}dj                  |      }| d| }| j                  |
||i        |	j
                  D ]  }||vst        d| d       t        t        j	                  t        |      h |j
                  |	j
                        d       t        t        j	                  |	j
                  h |j
                  |j
                        d       t        |	j
                        dk(  rt!        j"                  dd       |	j                  D cg c]	  \  }||    }}t%        |	j                  D cg c]  \  }||j
                  vs||    c}      }|t'        |t(              st        d      t        |      }t        t        j	                  |j
                  |j
                        d       t        t        j	                  |j
                  t        |            d       g }d}|j                  D ]m  }|t        k(  r|st        d      |D ]O  }|t        k(  r|st        d      ||j
                  v r|j+                  ||          d}?|j+                  d       Q o nd }d |z  d!z  }d|z  d!z  }| j-                  ||||       h |j
                  |j
                  |	j
                  }t        |v r|j/                  t               t1        |      }t3        t4        j6                  |      D ci c]  \  }}||
 c}}dt        <   d"t        ffd#} ||       d$ ||	       d ||       | _        y c c}w c c}}w c c}w c c}w c c}w c c}}w )%Nz->z7Unrecognized identifiers on the right side of EinMix {}zKEllipsis is not supported in weight, as its shape should be fully specifiedz,Ellipsis in EinMix should be on both sides, z3Ellipsis on left side can't be in parenthesis, got c              3   4   K   | ]  }|j                     y wN)has_non_unitary_anonymous_axes).0xs     r   	<genexpr>z1_EinmixMixin.initialize_einmix.<locals>.<genexpr>S   s     OAq//Os   z2Anonymous axes (numbers) are not allowed in EinMix()z,Parenthesis is not allowed in weight shape: c              3   8   K   | ]  }t        |      d k7    yw   Nr   r#   groups     r   r%   z1_EinmixMixin.initialize_einmix.<locals>.<genexpr>[   s     =5s5zQ=   ... z-> c              3   8   K   | ]  }t        |      d k7    ywr)   r+   r,   s     r   r%   z1_EinmixMixin.initialize_einmix.<locals>.<genexpr>d   s     >5s5zQ>r.   z ->z
Dimension z of weight should be specifiedzAxes {} are not used in patternzWeight axes {} are redundantr   zCEinMix: weight has no dimensions (means multiplication by a number)   )
stacklevelzAbias shape should be string specifying which axes bias depends onz"Bias axes {} not present in outputz#Sizes not provided for bias axes {}Fz:all bias dimensions should go after ellipsis in the outputTr*      g      ?r   c                     g }| j                   D ]Q  }t        |t              r#|j                  |D cg c]  }|   	 c}       6|t        k(  sJ |j                  d       S dj                  |      S c c}w )Nr/    )composition
isinstancelistextendr
   appendjoin)r   resultcomposed_axisaxismapping2letterss       r   write_flat_remappedz;_EinmixMixin.initialize_einmix.<locals>.write_flat_remapped   ss    F!%!1!1 )mT2MM]"ST?4#8"ST(I555MM%() 776?"	 #Ts   A5
,)splitr	   r   set
differenceidentifiershas_ellipsisr   has_ellipsis_parenthesizedanyr7   r
   r<   items_create_rearrange_layersr   warningswarnr   r8   strr;   _create_parametersremovesortedzipstringascii_lowercaseeinsum_pattern) r   r   r   r   r   left_patternright_patternleftrightweightpre_reshape_patternpre_reshape_lengthspost_reshape_patternnamesr-   namer7   lengthr?   _weight_shape_fan_inbias_bias_shapeused_non_trivial_sizer   weight_bound
bias_boundmapped_identifiersletterkrA   r@   s                                   @r   r   z_EinmixMixin.initialize_einmixC   s   &-mmD&9#m- /!,/NN5,,.V0@0@.V6CUCU.VWE	
 kll 2 2%%%*<*<!$PQXPY"Z[[..!$WX_W`"abbO$v9NOORSS,#"5 L\N[\\""#=D,<,<==!E)) FKLdTY.TE9LEL((5/K%1N#k]"CDPDVDVDX"jLD&\`di\i4<"j"j>E,=,=>>%BbBbE** FKLdTY.TE9LEL((5/K&1]#m_#E %%&9;NPdfhi&& 	UD<'!Jtf4R"STT	U 	NN3|,.V0@0@.V6CUCU.VW-	
 	NN6--/V1A1A/VEDUDU/VWYw	
 v!!"a'MM_lmn;A;M;MNd+NNf>P>Pr7DTX`e`q`qTqL.rs!j#.!"eff#J/Dt//1B1BC4 t//\1BC5
 K$)!)) 29$,)*fgg !% 29,4&12n&o o!T%5%55'..|D/AB481'..q122  KG+'kc)
|[*U Zt//Y%2C2CYfFXFXY**%%i0#$6769&:P:PRd6ef1f9f%*	"	#&6 	# #4()+>v+F*GrJ]^cJdIef 	q M #k M& OrZ gs0   UU*U6UU?U"U"U'r[   r\   r]   post_reshape_lengthsc                     t        d      )N.Should be defined in framework implementationsNotImplementedErrorr   r[   r\   r]   rk   s        r   rK   z%_EinmixMixin._create_rearrange_layers   s     ""RSSr   c                     t        d      )zShape and implementationsrm   rn   r   r   rf   r   rg   s        r   rO   z_EinmixMixin._create_parameters   s    !"RSSr   c                 "   t        | j                        }|d| j                   dz  }| j                  |d| j                   dz  }| j                  j                         D ]  \  }}|d| d| z  } | j                  j                   d| dS )Nz, ''z, =r&   r'   )reprr   r   r   r   rJ   r   __name__)r   paramsr?   r`   s       r   __repr__z_EinmixMixin.__repr__   s    dll#C))*!,,??&DOO,A..F --335 	+LD&4&&**F	+..))*!F8155r   r!   )rw   
__module____qualname__rN   r   r   r   dictr   r   rK   rO   ry   __classcell__)r   s   @r   r   r      s    1
 1
3 1
HSM 1
jm 1
fv
 v
C v
XVY] v
jn v
pT%c]T &d^T 'sm	T
 'tnTT6r   r   c            	       F    e Zd ZdZdee   dee   dee   dee   fdZd Zy)	_EinmixDebuggerzUsed only to test mixinr[   r\   r]   rk   c                 <    || _         || _        || _        || _        y r!   )r[   r\   r]   rk   rp   s        r   rK   z(_EinmixDebugger._create_rearrange_layers   s$     $7 #6 $8!$8!r   c                      || _         || _        y r!   )saved_weight_shapesaved_bias_shaperr   s        r   rO   z"_EinmixDebugger._create_parameters   s    ". *r   N)	rw   rz   r{   __doc__r   rN   r   rK   rO    r   r   r   r      sE    !
9%c]
9 &d^
9 'sm	
9
 'tn
9+r   r   )rS   rL   typingr   r   r   r   einopsr   einops.einopsr   einops.parsingr	   r
   rD   rN   r   r   r   r   r   r   <module>r      sF      , ,  " 67s 7C 7
@6 @6F+l +r   