
    3jC+                         S SK r S SKrS SKJrJrJrJr  S SKJr  S SK	J
r
  S SKJrJr  S\S\4S jr " S	 S
5      r " S S\5      rg)    N)AnyDictListOptional)EinopsError)_product)ParsedExpression	_ellipsisaxesreport_messagec                 V    [        U 5      S:  a  [        UR                  U 5      5      eg )Nr   )lenr   format)r   r   s     O/home/wildlama/miniconda3/lib/python3.13/site-packages/einops/layers/_einmix.py_report_axesr   
   s(    
4y1}.//566     c            	          ^  \ rS rSrSS\S\S\\   S\4U 4S jjjrS\S\S\\   S\4S jr	S\\   S	\\
   S
\\   S\\
   4S jrS rS rSrU =r$ )_EinmixMixin   patternweight_shape
bias_shapeaxes_lengthsc                 r   > [         TU ]  5         Xl        X l        X0l        X@l        U R                  XX4S9  g)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   _EinmixMixin.__init__   s?    T 	($(: 	 	
r   c                   ^ UR                  S5      u  pV[        U5      n[        U5      n[        U5      n	[        [        R	                  UR
                  1 UR
                  kU	R
                  k5      S5        U	R                  (       a  [        S5      eUR                  (       d  UR                  (       aO  UR                  (       a  UR                  (       d  [        SU 35      eUR                  (       a  [        SU 35      e[        S XxU	4 5       5      (       a  [        S5      eSU;   d  S	U;   a  [        S
U 35      eS n
S nS n[        S UR                   5       5      (       a{  / nUR                   H  nX-  nM	     U Vs/ s H  o[        :w  a  UOSPM     nnSR                  U5      nU SU 3n
UR                  5        VVs0 s H  u  nnX;   d  M  UU_M     nnn[        S UR                   5       5      (       d  UR                  (       aN  / nUR                   H  nX-  nM	     U Vs/ s H  o[        :w  a  UOSPM     nnSR                  U5      nU SU 3nU R                  XU0 5        U	R
                   H  nUU;  d  M  [        SU S35      e   [        [        R	                  [        U5      1 UR
                  kU	R
                  k5      S5        [        [        R	                  U	R
                  1 UR
                  kUR
                  k5      S5        [        U	R
                  5      S:X  a  [         R"                  " SSS9  U	R                   Vs/ s H
  u  nUU   PM     nn[%        U	R                   Vs/ s H  u  nUUR
                  ;  d  M  UU   PM     sn5      nUGb(  ['        U[(        5      (       d  [        S5      e[        U5      n[        [        R	                  UR
                  UR
                  5      S5        [        [        R	                  UR
                  [        U5      5      S5        / nSnUR                   H  nU[        :X  a  U(       a  [        S5      eM!  U HZ  nU[        :X  a  U(       a  [        S5      eM!  UUR
                  ;   a  UR+                  UU   5        SnMI  UR+                  S5        M\     M     OS nS U-  S!-  nSU-  S!-  nU R-                  UUUU5        1 UR
                  kUR
                  kU	R
                  kn[        U;   a  UR/                  [        5        [1        U5      n[3        [4        R6                  U5       VVs0 s H	  u  nnUU_M     snnmST[        '   S"[        4U4S# jjnU" U5       S$U" U	5       SU" U5       3U l        g s  snf s  snnf s  snf s  snf s  snf s  snnf )%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   8   #    U  H  oR                   v   M     g 7fN)has_non_unitary_anonymous_axes).0xs     r   	<genexpr>1_EinmixMixin.initialize_einmix.<locals>.<genexpr>S   s     O9NA//9Ns   z2Anonymous axes (numbers) are not allowed in EinMix()z,Parenthesis is not allowed in weight shape: c              3   >   #    U  H  n[        U5      S :g  v   M     g7f   Nr   r%   groups     r   r'   r(   [   s     =,<5s5zQ,<   ... z-> c              3   >   #    U  H  n[        U5      S :g  v   M     g7fr,   r.   r/   s     r   r'   r(   d   s     >,=5s5zQ,=r1   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                   > / nU R                    H\  n[        U[        5      (       a'  UR                  U Vs/ s H  nTU   PM
     sn5        M?  U[        :X  d   eUR                  S5        M^     SR                  U5      $ s  snf )Nr2    )composition
isinstancelistextendr
   appendjoin)r   resultcomposed_axisaxismapping2letterss       r   write_flat_remapped;_EinmixMixin.initialize_einmix.<locals>.write_flat_remapped   su    F!%!1!1mT22MM]"S]T?4#8]"ST(I555MM%( "2 776?"	 #Ts   B
,)splitr	   r   set
differenceidentifiershas_ellipsisr   has_ellipsis_parenthesizedanyr:   r
   r?   items_create_rearrange_layersr   warningswarnr   r;   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namesr0   namer:   lengthrB   _weight_shape_fan_inbias_bias_shapeused_non_trivial_sizer   weight_bound
bias_boundmapped_identifiersletterkrD   rC   s                                   @r   r   _EinmixMixin.initialize_einmixC   s   &-mmD&9#- /!,/NN5,,.V0@0@.V6CUCU.VWE	
 kll 2 2%%%*<*<!$PQXPY"Z[[..!$WX_W`"abbO$v9NOOORSS,#"5 L\N[\\""#=D,<,<===!E)) *FKLedY.TE9eEL((5/K%1N#k]"CDPDVDVDX"jDXLD&\`\i<4<DX"j>E,=,=>>>%BbBbE** +FKLedY.TE9eEL((5/K&1]#m_#E %%&9Pdfhi&&D<'!Jtf4R"STT ' 	NN3|,.V0@0@.V6CUCU.VW-	
 	NN6--/V1A1A/VEDUDU/VWYw	
 v!!"a'MM_lmn;A;M;MN;Md+;MNf>P>Pr>P7DTX`e`q`qTq.L.>Prs!j#..!"eff#J/Dt//1B1BC4 t//\1BC5
 K$)!))9$,)*fgg - !%9,4&12n&o o  5!T%5%55'..|D/AB481'..q1 !% *  KG+'kc)
|[*U Zt//Y%2C2CYfFXFXY**%%i0#$6769&:P:PRd6ef6e1f96ef%*	"	#&6 	# #4()+>v+F*GrJ]^cJdIef 	q M #k M& OrZ gs0   V;W W 4WWW	W.Wr_   r`   ra   post_reshape_lengthsc                     [        S5      e)N.Should be defined in framework implementationsNotImplementedErrorr   r_   r`   ra   rp   s        r   rO   %_EinmixMixin._create_rearrange_layers   s     ""RSSr   c                     [        S5      e)zShape and implementationsrr   rs   r   r   rj   r   rk   s        r   rS   _EinmixMixin._create_parameters   s    !"RSSr   c                 &   [        U R                  5      nUSU R                   S3-  nU R                  b  USU R                   S3-  nU R                  R                  5        H  u  p#USU SU 3-  nM     U R                  R                   SU S3$ )Nz, ''z, =r)   r*   )reprr   r   r   r   rN   r   __name__)r   paramsrB   rd   s       r   __repr___EinmixMixin.__repr__   s    dll#C))*!,,??&DOO,A..F --335LD4&&**F 6..))*!F8155r   )r   r   rY   r   r   r#   )r~   
__module____qualname____firstlineno__rR   r   r   r   dictr   r   rO   rS   r   __static_attributes____classcell__)r   s   @r   r   r      s    1
 1
3 1
HSM 1
jm 1
 1
fv
 v
C v
XVY] v
jn v
pT%c]T &d^T 'sm	T
 'tnTT6 6r   r   c            	       P    \ rS rSrSrS\\   S\\   S\\   S\\   4S jrS r	S	r
g
)_EinmixDebugger   zUsed only to test mixinr_   r`   ra   rp   c                 4    Xl         X l        X0l        X@l        g r#   )r_   r`   ra   rp   ru   s        r   rO   (_EinmixDebugger._create_rearrange_layers   s     $7 #6 $8!$8!r   c                     Xl         X0l        g r#   )saved_weight_shapesaved_bias_shaperx   s        r   rS   "_EinmixDebugger._create_parameters   s    ". *r   )rp   ra   r`   r_   r   r   N)r~   r   r   r   __doc__r   rR   r   rO   rS   r    r   r   r   r      sE    !
9%c]
9 &d^
9 'sm	
9
 'tn
9+r   r   )rW   rP   typingr   r   r   r   einopsr   einops.einopsr   einops.parsingr	   r
   rH   rR   r   r   r   r   r   r   <module>r      sF      , ,  " 67s 7C 7
@6 @6F+l +r   