
    oVh,                   @   d dl mZ d dlZd dlZd dlmZmZ d dlmZ d dl	Z	d dl	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 d d
lmZ d dlmZ d dlmZmZ d dlmZ d dlmZ d dlm Z  d dl!m"Z"m#Z# d dl$m%Z% d dl&m'Z' d dl(m)Z) d dl*m+Z+ d dl,m-Z-m.Z.m/Z/m0Z0 d dl1m2Z2 d dl3m4Z4 d dl5m6Z6m7Z7 d dl(m8Z8 d dl9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z? d dl@mAZA d dlBmCZC d dlDmEZE  G d de      ZF G d  d!eF      ZG G d" d#e      ZH G d$ d%eF      ZI G d& d'eF      ZJ G d( d)e      ZK G d* d+eK      ZL G d, d-eK      ZM G d. d/eK      ZN G d0 d1eK      ZO G d2 d3eK      ZP G d4 d5eK      ZQ G d6 d7eK      ZR G d8 d9      ZS G d: d;      ZT G d< d=      ZUd> ZVd? ZWd@ ZXdA ZYdB ZZdC Z[dD Z\dE Z]dF Z^dG Z_dH Z`y)I    )annotationsN)defaultdictCounter)reduce)
accumulate)Integer)EqualityKroneckerDelta)Basic)Tuple)Expr)FunctionLambda)Mul)Sdefault_sort_key)DummySymbol)
MatrixBase)diagonalize_vector)
MatrixExpr)
ZeroMatrix)permutedimstensorcontractiontensordiagonaltensorproduct)ImmutableDenseNDimArray)	NDimArray)IndexedIndexedBase)MatrixElement)$_apply_recursively_over_nested_lists_sort_contraction_indices_get_mapping_from_subranks*_build_push_indices_up_func_transformation_get_contraction_links,_build_push_indices_down_func_transformationPermutation)
_af_invert)_sympifyc                  $    e Zd ZU ded<   d Zd Zy)
_ArrayExprztuple[Expr, ...]shapec                    t        |t        j                  j                        s|f}t        j                  | |       | j                  |      S N)
isinstancecollectionsabcIterableArrayElement_check_shape_getselfitems     `/home/dcms/DCMS/lib/python3.12/site-packages/sympy/tensor/array/expressions/array_expressions.py__getitem__z_ArrayExpr.__getitem__*   s;    $ 8 897D!!$-yy    c                    t        | |      S r2   )_get_array_element_or_slicer:   s     r=   r9   z_ArrayExpr._get0   s    *466r?   N)__name__
__module____qualname____annotations__r>   r9    r?   r=   r/   r/   '   s    7r?   r/   c                  B    e Zd ZdZdZddZed        Zed        Zd Z	y)	ArraySymbolz1
    Symbol representing an array expression
    Fc                    t        |t              rt        |      }t        t	        t
        |       }t        j                  | ||      }|S r2   )r3   strr   r   mapr-   r   __new__)clssymbolr0   objs       r=   rL   zArraySymbol.__new__;   s=    fc"F^Fs8U+,ll3.
r?   c                     | j                   d   S Nr   _argsr;   s    r=   namezArraySymbol.nameC       zz!}r?   c                     | j                   d   S N   rR   rT   s    r=   r0   zArraySymbol.shapeG   rV   r?   c                .   t        d | j                  D              st        d      t        j                  | j                  D cg c]  }t        |       c} D cg c]  }| |   	 }} t        |      j                  | j                   S c c}w c c}w )Nc              3  4   K   | ]  }|j                     y wr2   
is_Integer.0is     r=   	<genexpr>z*ArraySymbol.as_explicit.<locals>.<genexpr>L        4A1<<4   z1cannot express explicit array with symbolic shape)allr0   
ValueError	itertoolsproductranger   reshape)r;   jr`   datas       r=   as_explicitzArraySymbol.as_explicitK   s{    444PQQ!*!2!2tzz4R!U1X4R!STAQTT4&t,44djjAA 5STs   BBN)r0   ztyping.Iterablereturnz'ArraySymbol')
rB   rC   rD   __doc__	_iterablerL   propertyrU   r0   rl   rF   r?   r=   rH   rH   4   sA     I    Br?   rH   c                  X    e Zd ZdZdZdZdZd Zed        Z	e
d        Ze
d        Zd Zy)	r7   z!
    An element of an array.
    Tc                   t        |t              rt        |      }t        |      }t        |t        j
                  j                        s|f}t        t        |            }| j                  ||       t        j                  | ||      }|S r2   )r3   rJ   r   r-   r4   r5   r6   tupler8   r   rL   )rM   rU   indicesrO   s       r=   rL   zArrayElement.__new__[   sn    dC $<D~';??#;#;<jG5>*w'll3g.
r?   c                *   t        |      }t        |d      r_t        d      }t        |      t        |j                        k7  r|t        d t        ||j                        D              rt        d      t        d |D              rt        d      y )Nr0   z3number of indices does not match shape of the arrayc              3  2   K   | ]  \  }}||k\  d k(    yw)TNrF   )r_   r`   ss      r=   ra   z,ArrayElement._check_shape.<locals>.<genexpr>m   s     I1AFt#Is   zshape is out of boundsc              3  ,   K   | ]  }|d k  dk(    yw)r   TNrF   r^   s     r=   ra   z,ArrayElement._check_shape.<locals>.<genexpr>o   s     01A$0s   zshape contains negative values)rs   hasattr
IndexErrorlenr0   anyzipre   )rM   rU   rt   index_errors       r=   r8   zArrayElement._check_shapef   s~    .4!$%Z[K7|s4::.!!IGTZZ0HII !9::000=>> 1r?   c                     | j                   d   S rQ   rR   rT   s    r=   rU   zArrayElement.namer   rV   r?   c                     | j                   d   S rX   rR   rT   s    r=   rt   zArrayElement.indicesv   rV   r?   c                2   t        |t              st        j                  S || k(  rt        j                  S |j
                  | j
                  k7  rt        j                  S t        j                  d t        | j                  |j                        D              S )Nc              3  :   K   | ]  \  }}t        ||        y wr2   r
   r_   r`   rj   s      r=   ra   z0ArrayElement._eval_derivative.<locals>.<genexpr>   s     ZTQN1a0Z   )
r3   r7   r   ZeroOnerU   r   fromiterr}   rt   )r;   rw   s     r=   _eval_derivativezArrayElement._eval_derivativez   sb    !\*66M955L66TYY66M||ZSqyy=YZZZr?   N)rB   rC   rD   rn   	_diff_wrt	is_symbolis_commutativerL   classmethodr8   rp   rU   rt   r   rF   r?   r=   r7   r7   R   s_     IIN	 	? 	?    
[r?   r7   c                  2    e Zd ZdZd Zed        Zd Zd Zy)	ZeroArrayzM
    Symbolic array of zeros. Equivalent to ``ZeroMatrix`` for matrices.
    c                    t        |      dk(  rt        j                  S t        t        |      }t        j                  | g| }|S rQ   )r{   r   r   rK   r-   r   rL   rM   r0   rO   s      r=   rL   zZeroArray.__new__   s:    u:?66MHe$ll3''
r?   c                    | j                   S r2   rR   rT   s    r=   r0   zZeroArray.shape       zzr?   c                    t        d | j                  D              st        d      t        j                  | j                   S )Nc              3  4   K   | ]  }|j                     y wr2   r\   r^   s     r=   ra   z(ZeroArray.as_explicit.<locals>.<genexpr>   rb   rc   /Cannot return explicit form for symbolic shape.)rd   r0   re   r   zerosrT   s    r=   rl   zZeroArray.as_explicit   s5    444NOO&,,djj99r?   c                "    t         j                  S r2   )r   r   r:   s     r=   r9   zZeroArray._get   s    vvr?   N	rB   rC   rD   rn   rL   rp   r0   rl   r9   rF   r?   r=   r   r      s*      :
r?   r   c                  2    e Zd ZdZd Zed        Zd Zd Zy)OneArrayz!
    Symbolic array of ones.
    c                    t        |      dk(  rt        j                  S t        t        |      }t        j                  | g| }|S rQ   )r{   r   r   rK   r-   r   rL   r   s      r=   rL   zOneArray.__new__   s:    u:?55LHe$ll3''
r?   c                    | j                   S r2   rR   rT   s    r=   r0   zOneArray.shape   r   r?   c           	     ,   t        d | j                  D              st        d       t        t	        t        t        j                  | j                              D cg c]  }t        j                   c}      j                  | j                   S c c}w )Nc              3  4   K   | ]  }|j                     y wr2   r\   r^   s     r=   ra   z'OneArray.as_explicit.<locals>.<genexpr>   rb   rc   r   )rd   r0   re   r   rh   r   operatormulr   r   ri   )r;   r`   s     r=   rl   zOneArray.as_explicit   si    444NOOh&uVHLLRVR\R\=]7^'_!'_`hhjnjtjtuu'_s   B
c                "    t         j                  S r2   )r   r   r:   s     r=   r9   zOneArray._get   s    uur?   Nr   rF   r?   r=   r   r      s+      v
r?   r   c                  8    e Zd Zed        Zd Zed        Zd Zy)_CodegenArrayAbstractc                     | j                   dd S )a  
        Returns the ranks of the objects in the uppermost tensor product inside
        the current object.  In case no tensor products are contained, return
        the atomic ranks.

        Examples
        ========

        >>> from sympy.tensor.array import tensorproduct, tensorcontraction
        >>> from sympy import MatrixSymbol
        >>> M = MatrixSymbol("M", 3, 3)
        >>> N = MatrixSymbol("N", 3, 3)
        >>> P = MatrixSymbol("P", 3, 3)

        Important: do not confuse the rank of the matrix with the rank of an array.

        >>> tp = tensorproduct(M, N, P)
        >>> tp.subranks
        [2, 2, 2]

        >>> co = tensorcontraction(tp, (1, 2), (3, 4))
        >>> co.subranks
        [2, 2, 2]
        N)	_subranksrT   s    r=   subranksz_CodegenArrayAbstract.subranks   s    4 ~~a  r?   c                ,    t        | j                        S )z*
        The sum of ``subranks``.
        )sumr   rT   s    r=   subrankz_CodegenArrayAbstract.subrank   s     4==!!r?   c                    | j                   S r2   _shaperT   s    r=   r0   z_CodegenArrayAbstract.shape       {{r?   c           
         |j                  dd      }|rE | j                  | j                  D cg c]  } |j                  di | c} j	                         S | j	                         S c c}w )NdeepTrF   )getfuncargsdoit_canonicalize)r;   hintsr   args       r=   r   z_CodegenArrayAbstract.doit   sa    yy&499DIIFSxsxx0%0FGUUWW%%'' Gs   A*N)rB   rC   rD   rp   r   r   r0   r   rF   r?   r=   r   r      s2    ! !6"  (r?   r   c                  2    e Zd ZdZd Zd Zed        Zd Zy)ArrayTensorProductzF
    Class to represent the tensor product of array-like objects.
    c                   |D cg c]  }t        |       }}|j                  dd      }|D cg c]  }t        |       }}t        j                  | g| }||_        |D cg c]  }t        |       }}t        d |D              rd |_        nt        d |D              |_        |r|j                         S |S c c}w c c}w c c}w )NcanonicalizeFc              3  $   K   | ]  }|d u  
 y wr2   rF   r^   s     r=   ra   z-ArrayTensorProduct.__new__.<locals>.<genexpr>        )QqDy)   c              3  .   K   | ]  }|D ]  }|   y wr2   rF   r   s      r=   ra   z-ArrayTensorProduct.__new__.<locals>.<genexpr>   s     <Q!<Qq<q<s   )r-   popget_rankr   rL   r   	get_shaper|   r   rs   r   )	rM   r   kwargsr   r   ranksrO   r`   shapess	            r=   rL   zArrayTensorProduct.__new__   s    )-.#..zz.%8*./3#//mmC'$'(,-1)A,--)&))CJ<&<<CJ$$&&
! / 0 .s   B=C$Cc                ,
   | j                   }| j                  |      }|D cg c]  }t        |       }}g }t        |      D ]w  \  }t	        |t
              s|j                  |j                  j                  D cg c]!  }|D cg c]  }|t        |d        z    c}# c}}       |j                  |<   y |r3t        t        | t        t        |      dz
        t        |      z        S t        |      dk(  r|d   S t        d |D              r:t!        t"        j$                  |D cg c]  }t'        |       c}d      }t)        | S t        |      D ci c]  \  }}t	        |t*              s|| }	}}|	r|D cg c](  }t	        |t*              rt-        |      n
t        |      * }}t/        t1        dg|z               d d t        |D cg c]   }t	        |t*              r|j                  n|" c} }
|	j3                         D cg c]+  \  }|j4                  D ]  }t7        fd|D               - }}}}t9        |
g| S t        |      D ci c]  \  }}t	        |t:              s|| }}}|r!g }g }|D cg c]  }t        |       }}t/        t1        dg|z               d d t        |      D ]  \  }t	        |t:              rt        |      t        |j<                        z
  }t        |j<                        }|j                  t?        |      D cg c]
  }   |z    c}       |j                  t?        |||z         D cg c]
  }   |z    c}       |j                  t?        t        |            D cg c]
  }   |z    c}        |j                  |       t        |D cg c]   }t	        |t:              r|j                  n|" c} }
|D cg c](  }t	        |t:              rt-        |      n
t        |      * }}t/        t1        dg|z               d d |j3                         D cg c]+  \  }|j<                  D ]  }t7        fd|D               - }}}}t        tA        |
g| tC        |            S  | jD                  |dd	iS c c}w c c}w c c}}w c c}w c c}}w c c}w c c}w c c}}}w c c}}w c c}w c c}w c c}w c c}w c c}w c c}w c c}}}w )
NrY   r   c              3  H   K   | ]  }t        |t        t        f        y wr2   )r3   r   r   )r_   r   s     r=   ra   z3ArrayTensorProduct._canonicalize.<locals>.<genexpr>  s     HCz#	:67Hs    "rF   c              3  .   K   | ]  }   |z     y wr2   rF   )r_   kcumulative_ranksr`   s     r=   ra   z3ArrayTensorProduct._canonicalize.<locals>.<genexpr>  s     (LQ)9!)<q)@(L   c              3  .   K   | ]  }   |z     y wr2   rF   )r_   r   cumulative_ranks2r`   s     r=   ra   z3ArrayTensorProduct._canonicalize.<locals>.<genexpr>4  s     %J1&7&:Q&>%Jr   r   F)#r   _flattenr   	enumerater3   PermuteDimsextendpermutationcyclic_formr   expr_permute_dims_array_tensor_productr+   r{   r|   r   r   addr   r   ArrayContraction_get_subranklistr   itemscontraction_indicesrs   _array_contractionArrayDiagonaldiagonal_indicesrh   _array_diagonalr,   r   )r;   r   r   r   permutation_cyclesrj   r   r`   r   contractionstpr   	diagonalsinverse_permutation	last_permi1i2ranks2r   r   r   s          `           @@r=   r   z ArrayTensorProduct._canonicalize   s   yy}}T"*./3#//  o 	FAsc;/%%PSP_P_PkPk&l1A'FqCbq	N(:'F&lmhhDG		
  !6!={3u:VW<?XYdewYx?xyyt9>7N H4HHHLL*FA9Q<*FKFf%% .7t_b61c
3P`@a3bbjnocf*S:J*K\#&QYZ]Q^^oEo#JsU{$;<SbA&ko(pdgZEU5V\_)_(pqB[g[m[m[o  #R  #RQWQRTWy|  zQ  zQ  #Rtu5(L!(L#L  #R#L  #R  #R%b?+>??*3D/\3Z]=[QV\	\"$I.23sXc]3E3#JsU{$;<SbA#D/ h3c=1!#S-A-A)BBBS112B'..QVWYQZ/[A0@0Ca0G/[\$$uRQSVXQXGY%Z!&6q&9A&=%Z['..QVW_`cWdQe/fA0@0Ca0G/fgh  &&y1&hl(madZ]5SY\)\(mnBhlmad:c=+Il3'xX[}\mFm $Zf%= >s CYbYhYhYj   J   JvqRUtw  uI  uI   Jop%J%J J   J J   J   J !G6F!GTgIhiityy$3U33g 0 (G&l +G
 co(p #R ] 4 0\%Z/f(mm  Jsw   R?	S	
S"S	2S
"S;S	-S%S0S$(S+S+S12S6
$S;
T 
%T;-T
0TS	c                t    |D cg c]$  }t        ||       r|j                  n|gD ]  }| & }}}|S c c}}w r2   )r3   r   )rM   r   r   r`   s       r=   r   zArrayTensorProduct._flatten9  s?    !Yc
38LCHHSVRWYaYYY Zs   )4c           	         t        | j                  D cg c]   }t        |d      r|j                         n|" c} S c c}w Nrl   )r   r   ry   rl   r;   r   s     r=   rl   zArrayTensorProduct.as_explicit>  s9    dhdmdmn]`GC4Os0UXXnoons   %=N)	rB   rC   rD   rn   rL   r   r   r   rl   rF   r?   r=   r   r      s,    &74r  pr?   r   c                  2    e Zd ZdZd Zd Zed        Zd Zy)ArrayAddz0
    Class for elementwise array additions.
    c                8   |D cg c]  }t        |       }}|D cg c]  }t        |       }}t        t        |            }t	        |      dk7  rt        d      |D cg c]  }|j                   }}t	        |D ch c]  }||	 c}      dkD  rt        d      |j                  dd      }t        j                  | g| }||_
        t        d |D              rd |_        n
|d   |_        |r|j                         S |S c c}w c c}w c c}w c c}w )NrY   z!summing arrays of different rankszmismatching shapes in additionr   Fc              3  $   K   | ]  }|d u  
 y wr2   rF   r^   s     r=   ra   z#ArrayAdd.__new__.<locals>.<genexpr>U  r   r   r   )r-   r   r   setr{   re   r0   r   r   rL   r   r|   r   r   )	rM   r   r   r   r   r   r`   r   rO   s	            r=   rL   zArrayAdd.__new__G  s   )-.#..*./3#//SZ u:?@AA'+,#)),,63aQ]34q8=>>zz.%8mmC'$')&))CJCJ$$&&
' // -3s   DD"D DDc                   | j                   }| j                  |      }|D cg c]  }t        |       }}|D cg c]  }t        |t        t
        f      r| }}t        |      dk(  r(t        d |D              rt        d      t	        |d    S t        |      dk(  r|d   S  | j                  |ddiS c c}w c c}w )Nr   c              3  &   K   | ]	  }||  y wr2   rF   r^   s     r=   ra   z)ArrayAdd._canonicalize.<locals>.<genexpr>f  s     2	12s   zIcannot handle addition of ZeroMatrix/ZeroArray and undefined shape objectrY   r   F)
r   _flatten_argsr   r3   r   r   r{   r|   NotImplementedErrorr   )r;   r   r   r   s       r=   r   zArrayAdd._canonicalize]  s    yy !!$',01S)C.11#T:cIz;R+STTt9>2f22)*uvvfQi((Y!^7Ntyy$3U33 2Ts   B7B<B<c                    g }|D ]?  }t        |t              r|j                  |j                         /|j	                  |       A |S r2   )r3   r   r   r   append)rM   r   new_argsr   s       r=   r   zArrayAdd._flatten_argsm  sC     	%C#x()$		%
 r?   c           
         t        t        j                  | j                  D cg c]   }t	        |d      r|j                         n|" c}      S c c}w r   )r   r   r   r   ry   rl   r   s     r=   rl   zArrayAdd.as_explicitw  sD    LLRVR[R[\3'#}"=S__3F\^ 	^\s   %A
N)	rB   rC   rD   rn   rL   r   r   r   rl   rF   r?   r=   r   r   B  s+    ,4   ^r?   r   c                      e Zd ZdZddZd Zed        Zed        Ze	d        Z
e	d        Ze	d	        Ze	d
        Zd Ze	d        Zd Ze	d        Ze	d        Zy)r   a  
    Class to represent permutation of axes of arrays.

    Examples
    ========

    >>> from sympy.tensor.array import permutedims
    >>> from sympy import MatrixSymbol
    >>> M = MatrixSymbol("M", 3, 3)
    >>> cg = permutedims(M, [1, 0])

    The object ``cg`` represents the transposition of ``M``, as the permutation
    ``[1, 0]`` will act on its indices by switching them:

    `M_{ij} \Rightarrow M_{ji}`

    This is evident when transforming back to matrix form:

    >>> from sympy.tensor.array.expressions.from_array_to_matrix import convert_array_to_matrix
    >>> convert_array_to_matrix(cg)
    M.T

    >>> N = MatrixSymbol("N", 3, 2)
    >>> cg = permutedims(N, [1, 0])
    >>> cg.shape
    (2, 3)

    There are optional parameters that can be used as alternative to the permutation:

    >>> from sympy.tensor.array.expressions import ArraySymbol, PermuteDims
    >>> M = ArraySymbol("M", (1, 2, 3, 4, 5))
    >>> expr = PermuteDims(M, index_order_old="ijklm", index_order_new="kijml")
    >>> expr
    PermuteDims(M, (0 2 1)(3 4))
    >>> expr.shape
    (3, 1, 2, 5, 4)

    Permutations of tensor products are simplified in order to achieve a
    standard form:

    >>> from sympy.tensor.array import tensorproduct
    >>> M = MatrixSymbol("M", 4, 5)
    >>> tp = tensorproduct(M, N)
    >>> tp.shape
    (4, 5, 3, 2)
    >>> perm1 = permutedims(tp, [2, 3, 1, 0])

    The args ``(M, N)`` have been sorted and the permutation has been
    simplified, the expression is equivalent:

    >>> perm1.expr.args
    (N, M)
    >>> perm1.shape
    (3, 2, 5, 4)
    >>> perm1.permutation
    (2 3)

    The permutation in its array form has been simplified from
    ``[2, 3, 1, 0]`` to ``[0, 1, 3, 2]``, as the arguments of the tensor
    product `M` and `N` have been switched:

    >>> perm1.permutation.array_form
    [0, 1, 3, 2]

    We can nest a second permutation:

    >>> perm2 = permutedims(perm1, [1, 0, 2, 3])
    >>> perm2.shape
    (2, 3, 5, 4)
    >>> perm2.permutation.array_form
    [1, 0, 3, 2]
    Nc                   ddl m} t        |      }t        |      }| j	                  |||       |      j
                  }||k7  rt        d      |j                  dd      }	t        j                  | |      }
t        |      g|
_
        t        |      d |
_        n,t        fdt        t                    D              |
_        |	r|
j!                         S |
S )Nr   r*   z8Permutation size must be the length of the shape of exprr   Fc              3  4   K   | ]  } |           y wr2   rF   )r_   r`   r   r0   s     r=   ra   z&PermuteDims.__new__.<locals>.<genexpr>  s     Pu[^4P   )sympy.combinatoricsr+   r-   r   _get_permutation_from_argumentssizere   r   r   rL   r   r   r   rs   rh   r{   r   )rM   r   r   index_order_oldindex_order_newr   r+   	expr_rankpermutation_sizer   rO   r0   s     `        @r=   rL   zPermuteDims.__new__  s    3~TN	99+Xgirs!+.&++y(WXXzz.%8mmC{3!$($=CJPeCJ>OPPCJ$$&&
r?   c                   | j                   }| j                  }t        |t              r|j                   }|j                  }||z  }|}t        |t              r| j                  ||      \  }}t        |t              r| j                  ||      \  }}t        |t        t        f      r-t        |j                  D cg c]  }|j                  |    c} S |j                  }|t        |      k(  r|S | j                  ||d      S c c}w )NF)r   )r   r   r3   r   r   '_PermuteDims_denestarg_ArrayContractionr   )_PermuteDims_denestarg_ArrayTensorProductr   r   
array_formr0   sortedr   )r;   r   r   subexprsubpermr`   plists          r=   r   zPermuteDims._canonicalize  s    yy&&dK(iiG&&G%/KDd,- $ L LTS^ _D+d./ $ N NtU` aD+dY
34k6L6LMtzz!}MNN&&F5M!Kyy{y??	 Ns   ;Dc                     | j                   d   S rQ   r   rT   s    r=   r   zPermuteDims.expr      yy|r?   c                     | j                   d   S rX   r  rT   s    r=   r   zPermuteDims.permutation  r  r?   c           
        t        |j                        }t        |j                        }t        t	        dg|j
                  z               }t        t        |            D cg c]  }|||   ||dz        }}t        |      D cg c]  \  }}|t        |      f }	}}|	j                  d        |	D cg c]  }|d   	 }
}|
D cg c]  }||   	 }}|
D cg c]  }||   	 }}t        t        |D cg c]  }|D ]  }|  c}}            }t        | |fS c c}w c c}}w c c}w c c}w c c}w c c}}w )Nr   rY   c                    | d   S rX   rF   xs    r=   <lambda>zGPermuteDims._PermuteDims_denestarg_ArrayTensorProduct.<locals>.<lambda>  s
    ad r?   key)r,   r	  r   r   r   r   rh   r{   r   r
  sortr+   r   )rM   r   r   perm_image_formr   cumulr`   perm_image_form_in_componentscomppsperm_args_image_formargs_sortedperm_image_form_sorted_argsrj   new_permutations                  r=   r  z5PermuteDims._PermuteDims_denestarg_ArrayTensorProduct  sB    %[%;%;<DIIZdmm 345 X]]`ae]fWg(hRSq%!*)M(h%(h/89V/WXGAtq&,XX 	N#.01!11(<=1tAw==Qe&fA'DQ'G&f#&f%j=X1dbc1d]^!1d!1d&ef$k2OCC )iX  2=&f1ds$   #D D%9D+D0D5:D:c                   t        |t              s||fS t        |j                  t              s||fS |j                  j                  }|j                  j                  D cg c]  }t        |       }}|j                  }|D cg c]  }|D ]  }|  }	}}t        t        dg|z               }
g }t        |j                        }d}t        t        |            D ]M  }g }t        |
|   |
|dz            D ]   }||	v r|j                  ||          |dz  }" |j                  |       O t        |j                        D cg c]#  \  }}t        t        |
|   |
|dz                  % }}}|j!                  |j                  |      }|dz  }|D cg c]  }|D cg c]  }| ||       c} }}}t        t        |            }|j#                  d        |D cg c]  }|d   	 }}|D cg c]  }||   	 }}t        |D cg c]  }|D ]  }|  c}}      |D cg c]  }||   	 }}|D cg c]  }t%        fd|D               }}t'        t)        | g| }t+        t        |D cg c]  }||   	 c}D cg c]  }|D ]  }|  c}}            }||fS c c}w c c}}w c c}}w c c}w c c}}w c c}w c c}w c c}}w c c}w c c}w c c}w c c}}w )Nr   rY   r   c                    | d   S rX   rF   r  s    r=   r  zEPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<lambda>6  s
    ! r?   r  c              3  (   K   | ]	  }|     y wr2   rF   )r_   rj   new_index_perm_array_forms     r=   ra   zFPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<genexpr>>  s     (Q!)B1)E(Q   )r3   r   r   r   r   r   r   r   r   r,   r	  rh   r{   r   r   r   _push_indices_upr  rs   r   r   r+   )rM   r   r   r   r   r   r   r`   rj   contraction_indices_flatr  permutation_array_blocks_up
image_formcountercurrenteindex_blocksindex_blocks_upr   index_blocks_up_permutedsorting_keysnew_perm_image_formnew_index_blocksr   new_contraction_indicesnew_exprr   r"  r&  s                               @r=   r  z3PermuteDims._PermuteDims_denestarg_ArrayContraction  s   $ 01$$$))%78$$yy~~-1YY^^<cHSM<<"66/B#N!A#NqA#NA#N #NZh/0 ')# 6 67
s8}% 	8AG58U1Q3Z0 00z'231	
 (..w7	8 GPPTP]P]F^_daU58U1Q3Z89__//0H0H,W)B/bq#r]^Q$X!-%8%;$X#r #r I&>?@n- .::qt::5HILOII$.;K/WaUV/WPQ/W/W$X!%89DG99[n"oVW5(Qq(Q#Q"o"o%&;X&FaI`a%jfy=zab>YZ[>\=z  2G  EF  2G  @A!  2G!  2G  'H  I((Q = $O$ ` %Y#r ;I/W9"o=z  2GsZ   "J-J2(J8	K!J>)
J>3K&K	8KK
,K>K;K#K(>Kc                (   |j                   }t        |j                        D cg c]$  \  }}t        |j                   |         D ]  }| & }}}}t        |j	                               D cg c]
  } ||       }}t        |j                        }	||d      }
g }g }t               }t        |      D ]  \  }}||   |
k7  r|j                  |       g }||   }
|j                  |       ||
   }t        |      |k(  sK|j                  t        |             |D cg c]  }|t        |      z
   }}||   }t        |	|   t        |            |	|<   |j                  |
       g } |j                  |       t        t        t        |	                  }i }dgt        t        |            z   }t        t        |            D ]X  }t        ||   ||dz            D ch c]
  }|||       }}t        |      dk7  r:t!        t#        |            }||k7  sT|||<   Z g }g }|r|t        |      dk(  r%|j%                         \  }}|j                  |       n|d   }||vrg }A|j'                  |      }||v r|j                  |       g }j|j                  |       |r||D ],  }t        |      D ]  \  }}||||dz   t        |      z     <    . t        |      D cg c]'  \  }}t        |      D cg c]  }|||   |z       c}) }}}}|D cg c]  }|	|   	 }	}|D cg c]  }||   	 }}|D cg c]  }|D ]  }|  }}}t)        |	 t        |      fS c c}}}w c c}w c c}w c c}w c c}w c c}}}w c c}w c c}w c c}}w Nr   rY   r   )r   r   r   rh   r   r   r   r   r   r{   r
  minr   r+   r   r   nextiterpopitemr   r   ) rM   r   r   r   r`   r   rj   	index2argpermuted_indicesr   arg_candidate_indexcurrent_indicesr"  inserted_arg_cand_indicesidxarg_candidate_ranklocal_current_indicesr   args_positionsmapscumulative_subranksrw   elemlinescurrent_liner   vliner.  permutation_blocksnew_permutation_blocksnew_permutation2s                                    r=   _check_permutation_mappingz&PermuteDims._check_permutation_mappingC  s   ==%.tyy%9[[61c5WXIYCZ[aQ[Q[	[49$,,.4IJqKNJJ		?'(8(;<$'E! 01 	%FAs~!44&&7"$&/n#""3'!)*=!>?#'99&&vo'>?KZ([aS-A)A([%([q\,Xb\;G\;]^)--.AB"$	% 	/ eCM23 cDH)=$>>s8}% 	A8=>QRS>TVijklmjmVn8op1?1-.pAp1v{Q=DDyQ	 < A%||~1##A& $D=#%LHHQKL \*!"   	>D!$ >1<=tQUc$i$789>	>
 ktt|j}~~bfbcefTYZ[T\]q/B1/E/IJ]~~)78AHQK88AO!PA"4Q"7!P!P'=I!qI!AIAII$h/=M1NNNA \J )\ q< ^~8!PIsA   )M".M)M. M3#M=8M8
M=N)N	<N8M=c                r   t        |j                        }|j                  }|j                  }dgt        t	        |            z   }|D cg c]  }t        |       }}|D cg c]  }t        |       }	}g }
t        |      D ]  \  }}d}t        t        |      dz
        D ]P  }||   ||   k\  s|	|   ||dz      k  st        ||   t        |D cg c]
  }|||   z
   c}g            ||<   d} n |su|
j                  |        t        | t        |
|j                        fS c c}w c c}w c c}w )Nr   TrY   F)r  )r   r   r   r   r   r9  maxr   rh   r{   r   r+   r   r   r  )rM   r   r   r   r   r   rG  r`   
cyclic_min
cyclic_maxcyclic_keepcycleflagrj   r   s                  r=   !_check_if_there_are_closed_cyclesz-PermuteDims._check_if_there_are_closed_cycles  sQ   DII==!-- cDH)=$>>&12c!f2
2&12c!f2
2!+. 		*HAuD323a78 a=$7$::z!}ObcdefcfOg?g+DG[glBmbc1GZ[\G]C]BmAn5opDG D ""5)		* %d+[;K[K[-\\\ 32 Cns   
D*"D/D4c                Z    | j                  | j                  | j                        }|| S |S )z
        DEPRECATED.
        )_nest_permutationr   r   )r;   rets     r=   nest_permutationzPermuteDims.nest_permutation  s/     $$TYY0@0@A;K
r?   c           	        t        |t              rt        | j                  ||       S t        |t              rx|j
                  }t	        j                  |g| }t        |      |j                  D cg c]  }t        fd|D               }}t        t        |j                        g| S t        |t              r*t        |j                  D cg c]  }t        ||       c} S y c c}w c c}w )Nc              3  .   K   | ]  } |        y wr2   rF   )r_   rj   newpermutations     r=   ra   z0PermuteDims._nest_permutation.<locals>.<genexpr>  s     &DQ~a'8&Dr   )r3   r   r   rX  r   r   '_convert_outer_indices_to_inner_indicesr+   r   rs   r   r   r   r   
_array_addr   )	rM   r   r   cycles	newcyclesr`   new_contr_indicesr   r_  s	           @r=   rZ  zPermuteDims._nest_permutation  s    d./ #"G"Gk"Z[[./ ,,F(PPQU_X^_I(3NNRNfNf g&D!&D!D g g%k$))^&LaO`aah'S#C =STT	 !h  Ts   5C-C2c                ~    | j                   }t        |d      r|j                         }t        || j                        S r   )r   ry   rl   r   r   r;   r   s     r=   rl   zPermuteDims.as_explicit  s6    yy4'##%D4!1!122r?   c                    |&||t        d      t        j                  |||      S |t        d      |t        d      |S )NzPermutation not definedz2index_order_new cannot be defined with permutationz2index_order_old cannot be defined with permutation)re   r   "_get_permutation_from_index_orders)rM   r   r  r  dims        r=   r   z+PermuteDims._get_permutation_from_arguments  s`    &/*A !:;;AA/Sbdghh* !UVV* !UVVr?   c                R   t        t        |            |k7  rt        d      t        t        |            |k7  rt        d      t        t        j                  t        |      t        |                  dkD  rt        d      |D cg c]  }|j	                  |       }}|S c c}w )Nz*wrong number of indices in index_order_newz*wrong number of indices in index_order_oldr   z>index_order_new and index_order_old must have the same indices)r{   r   re   symmetric_differenceindex)rM   r  r  ri  r`   r   s         r=   rh  z.PermuteDims._get_permutation_from_index_orders  s    s?#$+IJJs?#$+IJJs''O(<c/>RSTWXX]^^9HIA,,Q/II Js   B$)NNN)rB   rC   rD   rn   rL   r   rp   r   r   r   r  r  rP  rX  r\  rZ  rl   r   rh  rF   r?   r=   r   r   }  s    GR.@&     D D0 .) .)` BO BOH ] ](  3 
 
  r?   r   c                      e Zd ZdZd Zd Zed        Zed        Ze	d        Z
e	d        Zed        Zed	        Zed
        Zedd       Zd Zd Zed        Zed        Zed        Zd Zy)r   a  
    Class to represent the diagonal operator.

    Explanation
    ===========

    In a 2-dimensional array it returns the diagonal, this looks like the
    operation:

    `A_{ij} \rightarrow A_{ii}`

    The diagonal over axes 1 and 2 (the second and third) of the tensor product
    of two 2-dimensional arrays `A \otimes B` is

    `\Big[ A_{ab} B_{cd} \Big]_{abcd} \rightarrow \Big[ A_{ai} B_{id} \Big]_{adi}`

    In this last example the array expression has been reduced from
    4-dimensional to 3-dimensional. Notice that no contraction has occurred,
    rather there is a new index `i` for the diagonal, contraction would have
    reduced the array to 2 dimensions.

    Notice that the diagonalized out dimensions are added as new dimensions at
    the end of the indices.
    c                   t        |      }|D cg c]  }t        t        |        }}|j                  dd      }t	        |      }|, | j
                  |g|i | | j                  ||      \  }}nd }t        |      dk(  r|S t        j                  | |g| }||_
        t        |      |_        ||_        |r|j                         S |S c c}w )Nr   Fr   )r-   r   r
  r   r   	_validate_get_positions_shaper{   r   rL   
_positions_get_subranksr   r   r   )	rM   r   r   r   r`   r   r0   	positionsrO   s	            r=   rL   zArrayDiagonal.__new__  s    ~7GH!E6!9-HHzz.%8$CMM$<!1<V<"77?OPIuI A%KmmC9(89"%d+
$$&&
% Is   Cc                   | j                   }| j                  }|D cg c]  }t        |      dk(  s| }}t        |      dkD  rnt        |      D ci c]  \  }}t        |      dk(  s|d   | }}}t        |      D ci c]  \  }}t        |      dkD  s|| }}}|D cg c]  }t        |      dkD  s| }}t	        |       }	t        |      }
|	|
z
  }g }d}t
        j                  |t        t        |	            t	        |            }|D ]b  }||v r|j                  |||   z          t        |t        t        f      r|j                  |       |dz  }L|j                  |||   z          d t        |      }t        |      dkD  rt        t        |g| |      S t        ||      S t        |t               r | j"                  |g| S t        |t
              r | j$                  |g| S t        |t&              r | j(                  |g| S t        |t*        t,        f      r'| j/                  |j0                  |      \  }}t+        | S  | j2                  |g|ddiS c c}w c c}}w c c}}w c c}w )NrY   r   r   F)r   r   r{   r   r   r   _push_indices_downr   rh   r   r3   r   intr,   r   r   r   _ArrayDiagonal_denest_ArrayAdd#_ArrayDiagonal_denest_ArrayDiagonalr   !_ArrayDiagonal_denest_PermuteDimsr   r   rp  r0   r   )r;   r   r   r`   trivial_diagsr.  trivial_posdiag_posdiagonal_indices_shortrank1rank2rank3inv_permutationcounter1indices_downr   rs  r0   s                     r=   r   zArrayDiagonal._canonicalize  s   yy00$4DqA!DD}!/89I/JZtq!cRSfXYk1Q47ZKZ)23C)DSAAQR
1SHS1A%PASVaZa%P"%PTNE()EEME OH(;;<RTXY^_dYeTfhpquhvwL! @##**5;q>+ABGS>2#**84MH#**58A;+>?@ %_5K)*Q.$_T%S<R%SU`aa$T;77dH%6466tO>NOOdM*;4;;DTCSTTdK(9499$RAQRRdY
34#88EUVIue$$tyyE 0EuEEC EZS%Ps.   I0I0I5+I5I;I;'J;Jc                r   t        |       |D ]  }t        fd|D              rt        d      t        |D ch c]  }|   	 c}      dk7  rt        d      |j	                  dd      st        |      dk  rt        d      t        t        |            t        |      k7  st        d       y c c}w )	Nc              3  :   K   | ]  }|t              k\    y wr2   r{   )r_   rj   r0   s     r=   ra   z*ArrayDiagonal._validate.<locals>.<genexpr>0  s     .q1E
?.s   z%index is larger than expression shaperY   z-diagonalizing indices of different dimensionsallow_trivial_diagsFz%need at least two axes to diagonalizezaxis index cannot be repeated)r   r|   re   r{   r   r   )r   r   r   r`   rj   r0   s        @r=   ro  zArrayDiagonal._validate*  s     $! 	BA.A.. !HIIa(E!H()Q. !PQQ::3U;A! !HII3q6{c!f$ !@AA	B )s   B4
c                d    |D cg c]   }| |d      dk7  st        d |D              " c}S c c}w )Nr   rY   c              3      K   | ]  }|  y wr2   rF   )r_   rj   s     r=   ra   z;ArrayDiagonal._remove_trivial_dimensions.<locals>.<genexpr>;  s     ^Aa^s   rs   )r0   r   r`   s      r=   _remove_trivial_dimensionsz(ArrayDiagonal._remove_trivial_dimensions9  s/    -=RqtPQAQ^^#RRRs   --c                     | j                   d   S rQ   r  rT   s    r=   r   zArrayDiagonal.expr=  r  r?   c                     | j                   dd  S rX   r  rT   s    r=   r   zArrayDiagonal.diagonal_indicesA      yy}r?   c                   | j                   }|D cg c]  }|D ]  }|  }}}|j                          t        |       }t        |      }||z
  }t	        |      D cg c]  }d c}d}	d}
t	        |      D ]9  }|
|k  r |	||
   k\  r|	dz  }	|
dz  }
|
|k  r	|	||
   k\  r|xx   |
z  cc<   |	dz  }	; t        fd|D              }||z   }t        | j                  g| S c c}}w c c}w )Nr   rY   c              3  F   K   | ]  }t        fd |D                yw)c              3  .   K   | ]  }|   |z     y wr2   rF   r_   rj   shiftss     r=   ra   z3ArrayDiagonal._flatten.<locals>.<genexpr>.<genexpr>W  s     ,FqVAY],Fr   Nr  r_   r`   r  s     r=   ra   z)ArrayDiagonal._flatten.<locals>.<genexpr>W  s     &g1u,FA,F'F&g   !)r   r  r   r{   rh   rs   r   r   )r   outer_diagonal_indicesinner_diagonal_indicesr`   rj   	all_inner
total_rank
inner_rank
outer_rankr,  pointerr   r  s               @r=   r   zArrayDiagonal._flattenE  s   !%!6!6 6B1B1QBQB	B!$'
^
*,
":./!/z" 	AJ&7i6H+H11 J&7i6H+H 1I IqLG	 "'&gPf&g!g14JJtyy<+;<<# C 0s   C$	C*c           	     `    t        |j                  D cg c]  }t        |g|  c} S c c}w r2   )ra  r   r   )rM   r   r   r   s       r=   rw  z,ArrayDiagonal._ArrayDiagonal_denest_ArrayAdd[  s*    tyyYOCC2BCYZZY   +c                (     | j                   |g| S r2   r   )rM   r   r   s      r=   rx  z1ArrayDiagonal._ArrayDiagonal_denest_ArrayDiagonal_  s    s||D4#344r?   c           
     n   |D cg c]!  }|D cg c]  }|j                  |       c}# }}}t        t        |            D cg c]  t        fd|D              r }}|D cg c]  }|j                  |       }}t	        t        |            D ci c]  \  }}||
 }	}}|D cg c]  }|	|   	 }
}t        |
      }t        t        |            D cg c]  }||z   	 }}|
|z   }t        t        |j                  g| |      S c c}w c c}}w c c}w c c}w c c}}w c c}w c c}w )Nc              3  &   K   | ]  }|v  
 y wr2   rF   r_   rj   r`   s     r=   ra   zBArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<genexpr>f  s     >`!qAv>`   )
r   rh   r   r|   r   r
  r{   r   r   r   )rM   r   r   r`   rj   back_diagonal_indicesnondiagback_nondiagr.  remapnew_permutation1shiftdiag_block_permr"  s      `          r=   ry  z/ArrayDiagonal._ArrayDiagonal_denest_PermuteDimsc  s*   K[ \aq!A!$"2"21"5!A \ \#HTN3a3>`O_>`;`1aa5<=((+=="+F<,@"AB$!QABB.:;E!H;;$%.3C8M4N.OP1u9PP*_<		& 
 	
 "B \a=B;Ps9   	DDDD!D+D"D'0D-D2Dc                &      fd}t        ||      S )Nc                V    | t        j                        k  rj                  |    S d S r2   )r{   rq  )r  r;   s    r=   r  z<ArrayDiagonal._push_indices_down_nonstatic.<locals>.<lambda>v  s%    ADOO8L4Ldooa0 RV r?   r$   r;   rt   	transforms   `  r=   _push_indices_down_nonstaticz*ArrayDiagonal._push_indices_down_nonstaticu  s    V	3IwGGr?   c                &      fd}t        ||      S )Nc                    t        j                        D ]3  \  }}t        |t              r| |k(  st        |t              s,| |v s1|c S  y r2   )r   rq  r3   rv  rs   )r  r`   r.  r;   s      r=   r  z;ArrayDiagonal._push_indices_up_nonstatic.<locals>.transform{  sF    !$//2 1q#&16z!U7KPQUVPVHr?   r  r  s   `  r=   _push_indices_up_nonstaticz(ArrayDiagonal._push_indices_up_nonstaticy  s    	
 4IwGGr?   c                b    | j                  t        |      |      \  }fd}t        ||      S )Nc                .    | t              k  r|    S d S r2   r  )r  rs  s    r=   r  z2ArrayDiagonal._push_indices_down.<locals>.<lambda>  s    a#i..@il d r?   rp  rh   r$   rM   r   rt   rankr0   r  rs  s         @r=   ru  z ArrayDiagonal._push_indices_down  s1    33E$KAQR	5J	3IwGGr?   c                b    | j                  t        |      |      \  }fd}t        ||      S )Nc                    t              D ]9  \  }}t        |t              r| |k(  st        |t        t        f      s2| |v s7|c S  y r2   )r   r3   rv  rs   r   )r  r`   r.  rs  s      r=   r  z1ArrayDiagonal._push_indices_up.<locals>.transform  sF    !), 1q#&16z!eU^7TZ[_`Z`Hr?   r  r  s         @r=   r(  zArrayDiagonal._push_indices_up  s3    33E$KAQR	5	
 4IwGGr?   c                    t        fdt              D              }|rt        | nd\  }}t        fdD              }|rt        | nd\  }}||z   }	||z   |	fS )Nc              3  X   K   | ]   \  }t        fd D              r|f " yw)c              3  &   K   | ]  }|v  
 y wr2   rF   r  s     r=   ra   z?ArrayDiagonal._get_positions_shape.<locals>.<genexpr>.<genexpr>  s     HjTUaHjr  Nr|   )r_   shpr`   r   s     @r=   ra   z5ArrayDiagonal._get_positions_shape.<locals>.<genexpr>  s'     k61cSHjYiHjEjq#hks   *	*)rF   rF   c              3  2   K   | ]  }||d       f  yw)r   NrF   )r_   r`   r0   s     r=   ra   z5ArrayDiagonal._get_positions_shape.<locals>.<genexpr>  s     A1q%!+&As   )rs   r   r}   )
rM   r0   r   data1pos1shp1data2pos2shp2rs  s
    ``       r=   rp  z"ArrayDiagonal._get_positions_shape  sh    kYu-=kk$)S%[x
dA0@AA$)S%[x
d4K	t%r?   c                ~    | j                   }t        |d      r|j                         }t        |g| j                   S r   )r   ry   rl   r   r   rf  s     r=   rl   zArrayDiagonal.as_explicit  s9    yy4'##%Dd;T%:%:;;r?   N)r   r   )rB   rC   rD   rn   rL   r   staticmethodro  r  rp   r   r   r   r   rw  rx  ry  r  r  ru  r(  rp  rl   rF   r?   r=   r   r     s
   2,$FL B B S S     = =* [ [ 5 5 
 
"HH H H
 H H    <r?   r   c                  N    e Zd Zd Zed        Zed        Zed        Zd Zd Z	y)ArrayElementwiseApplyFuncc                    t        |t              st        d      }t        | ||            }t        j	                  | ||      }t        |      |_        |S Nd)r3   r   r   r   rL   rr  r   )rM   functionelementr  rO   s        r=   rL   z!ArrayElementwiseApplyFunc.__new__  sJ    (F+c
Aa!-H#++C7C%g.
r?   c                     | j                   d   S rQ   r  rT   s    r=   r  z"ArrayElementwiseApplyFunc.function  r  r?   c                     | j                   d   S rX   r  rT   s    r=   r   zArrayElementwiseApplyFunc.expr  r  r?   c                .    | j                   j                  S r2   r   r0   rT   s    r=   r0   zArrayElementwiseApplyFunc.shape  s    yyr?   c                    t        d      }| j                  |      }|j                  |      }t        |t              rt        |      }|S t        ||      }|S r  )r   r  diffr3   r   typer   )r;   r  r  fdiffs       r=   _get_function_fdiffz-ArrayElementwiseApplyFunc._get_function_fdiff  sT    #J==#a eX&KE  1e$Er?   c                    | j                   }t        |d      r|j                         }|j                  | j                        S r   )r   ry   rl   	applyfuncr  rf  s     r=   rl   z%ArrayElementwiseApplyFunc.as_explicit  s6    yy4'##%D~~dmm,,r?   N)
rB   rC   rD   rL   rp   r  r   r0   r  rl   rF   r?   r=   r  r    sM          -r?   r  c                     e Zd ZdZd Zd Zd Zd Zed        Z	e
d        Ze
d        Ze
d	        Zd
 Zd Zed        Zed        Zed        Zed        Ze
d        Ze
d        Ze
d        Ze
d        Ze
d!d       Ze
d        Zd Zed        Zed        Zed        Zed        Zed        Z d Z!d Z"d Z#d Z$y )"r   zx
    This class is meant to represent contractions of arrays in a form easily
    processable by the code printers.
    c                $   t              t        |      }|j                  dd      }t        j                  | |g }t        |      |_        t        |j                        |_        t        t        |j                              D ci c]  t        fdD              s }}||_        t        |      } | j                  |g  |rt        fdt!        |      D              }||_        |r|j%                         S |S c c}w )Nr   Fc              3  &   K   | ]  }|v 
 y wr2   rF   )r_   cindr`   s     r=   ra   z+ArrayContraction.__new__.<locals>.<genexpr>  s!       SBeiST\`S`  SBr  c              3  T   K   | ]  \  }t        fd D              r|   yw)c              3  &   K   | ]  }|v  
 y wr2   rF   r  s     r=   ra   z5ArrayContraction.__new__.<locals>.<genexpr>.<genexpr>  s     GlSTQGlr  Nr  )r_   r  r`   r   s     @r=   ra   z+ArrayContraction.__new__.<locals>.<genexpr>  s#     m&!SCGlXkGlDl#ms   (()r%   r-   r   r   rL   rr  r   r&   _mappingrh   r   rd   _free_indices_to_positionr   ro  rs   r   r   r   )	rM   r   r   r   r   rO   r`   free_indices_to_positionr0   s	     `   `  r=   rL   zArrayContraction.__new__  s   78KL~zz.%8mmC<(;<%d+1#--@27CMM8J2K  $CQs  SB  nA  SB  PBAqD  $C   $C(@%$d101mIe,<mmE
$$&&
 $Cs   D'Dc                
   | j                   }| j                  }t        |      dk(  r|S t        |t              r | j
                  |g| S t        |t        t        f      r | j                  |g| S t        |t              r | j                  |g| S t        |t              r:| j                  ||      \  }}| j                  ||      \  }}t        |      dk(  r|S t        |t              r | j                  |g| S t        |t               r | j"                  |g| S |D cg c]'  }t        |      dkD  st%        |      |d      dk7  s&|) }}t        |      dk(  r|S  | j&                  |g|ddiS c c}w )Nr   rY   r   F)r   r   r{   r3   r   )_ArrayContraction_denest_ArrayContractionr   r   "_ArrayContraction_denest_ZeroArrayr   $_ArrayContraction_denest_PermuteDimsr   _sort_fully_contracted_args_lower_contraction_to_addendsr   &_ArrayContraction_denest_ArrayDiagonalr   !_ArrayContraction_denest_ArrayAddr   r   )r;   r   r   r`   s       r=   r   zArrayContraction._canonicalize  s   yy"66"#q(Kd,-A4AA$]I\]]dY
34:4::4VBUVVdK(<4<<TXDWXXd./(,(H(HOb(c%D%(,(J(J4Qd(e%D%&'1,dM*>4>>tZFYZZdH%9499$UATUU +>jQQ!yY]_`ab_cOdhiOiqjj"#q(KtyyH 3H%HH	 ks   ,'F F c                &    |dk(  r| S t        d      NrY   zDProduct of N-dim arrays is not uniquely defined. Use another method.r   r;   others     r=   __mul__zArrayContraction.__mul__      A:K%&lmmr?   c                &    |dk(  r| S t        d      r  r  r  s     r=   __rmul__zArrayContraction.__rmul__  r  r?   c                    t        |       }|y |D ]5  }t        |D ch c]  }||   dk7  s||    c}      dk7  s,t        d       y c c}w )Nr   rY   z+contracting indices of different dimensions)r   r{   re   )r   r   r0   r`   rj   s        r=   ro  zArrayContraction._validate  s[    $= % 	PAa:58r>E!H:;q@ !NOO	P:s
   A

A

c                    |D cg c]  }|D ]  }|  }}}|j                          t        |      }t        ||      S c c}}w r2   )r  r)   r$   rM   r   rt   r`   rj   flattened_contraction_indicesr  s          r=   ru  z#ArrayContraction._push_indices_down#  sM    4G(SqQR(SA(S(S%(S%**,@A^_	3IwGG )T   A c                    |D cg c]  }|D ]  }|  }}}|j                          t        |      }t        ||      S c c}}w r2   )r  r'   r$   r  s          r=   r(  z!ArrayContraction._push_indices_up*  sM    4G(SqQR(SA(S(S%(S%**,>?\]	3IwGG )Tr  c           
        t        |t              r
t               t        |t              s||fS |j                  }t        t        dg|z               g }|j                  D cg c]  }g  }}t               }|D ]  }t        t        |j                              D ]p  t        |j                     t              s!t        fd|D              s7|   j                  |D 	cg c]
  }	|	   z
   c}	       |j                  |         |j                  |        t        |      t        |      k(  r||fS t        |      }
t        t        t        |
      D cg c]
  }||v rdnd c}            |D cg c]   }t        j                   fd|D              " }}t#        t%        |j                  |      D cg c]  \  }}t'        |g|  c}} }||fS c c}w c c}	w c c}w c c}w c c}}w )Nr   c              3  P   K   | ]  }   |cxk  xr d z      k  nc   yw)rY   NrF   )r_   r   cumranksrj   s     r=   ra   zAArrayContraction._lower_contraction_to_addends.<locals>.<genexpr>@  s*     SAx{a7(1Q3-77Ss   #&rY   c              3  .   K   | ]  }||   z
    y wr2   rF   r  s     r=   ra   zAArrayContraction._lower_contraction_to_addends.<locals>.<genexpr>J  s     7Q!F1I7Qr   )r3   r   r   r   r   r   r   r   r   rh   r{   rd   r   updater   r   r   r   r}   r   )rM   r   r   r   contraction_indices_remainingr`   contraction_indices_args	backshiftcontraction_groupr   r  r   contrr[  r  rj   r  s                 @@@r=   r  z.ArrayContraction._lower_contraction_to_addends1  s   dH%%''$ 23,,,==
A3>23(*%04		#:1B#: #:E	!4 		H3tyy>* H!$))A,9SARSS,Q/66Qb7cAHQK7cd$$%67H .445FG		H ,-5H1II,,,d^
jeJFW!XqI~!1"<!XYZ[x(yVW7Qq7Q)Q(y%(y#>A$))Me>f&
0:Us+U+&
  111) $; 8d "Y(y&
s   &	G#'G(!G-?%G2G7
c           	        t        |       }| j                  }g }t        |      D ]  \  }t        |      dk  r|j	                        }| j
                  j                  |d      }g }g }|D ]  \  }	}
|j                  |	   }|j                  }|j                  |      \  }}d|
z
  }||z   d|j                  vs4|dk(  du r|j                  dk7  st        fdt        |      D              r|j                  ||
f       |j                  ||
f        t        |      dkD  r|D ]  \  }}
t        |j                        |_        ! |dd |z   |dd z   }|d   \  }}
|j                  |
   }|dd D ]  \  }}
||j                  |
<   |j                         }|j                  j                  d      d|
z
  k(  sJ ||j                  |j                  j                  d      <   |j                  |        |d   \  }}
||j                  |
<    |D ](  }|j!                  |t#        t%        d      dg             * |j'                         S )	a`  
        Recognize multiple contractions and attempt at rewriting them as paired-contractions.

        This allows some contractions involving more than two indices to be
        rewritten as multiple contractions involving two indices, thus allowing
        the expression to be rewritten as a matrix multiplication line.

        Examples:

        * `A_ij b_j0 C_jk` ===> `A*DiagMatrix(b)*C`

        Care for:
        - matrix being diagonalized (i.e. `A_ii`)
        - vectors being diagonalized (i.e. `a_i0`)

        Multiple contractions can be split into matrix multiplications if
        not more than two arguments are non-diagonals or non-vectors.
        Vectors get diagonalized while diagonal matrices remain diagonal.
        The non-diagonal matrices can be at the beginning or at the end
        of the final matrix multiplication line.
           r   rY   T)rY   rY   c              3  8   K   | ]  \  }}|k7  s|v   y wr2   rF   )r_   lilindlother_arg_abss      r=   ra   z?ArrayContraction.split_multiple_contractions.<locals>.<genexpr>  s#     eur1Z\`dZd*es   	Nr   )_EditArrayContractionr   r   r{   get_mapping_for_indexr   r0   args_with_indr  get_absolute_ranger|   r   r   rt   get_new_contraction_indexrl  insert_after_ArgEr   to_array_contraction)r;   editorr   onearray_insertlinksrs  current_dimensionnot_vectorsvectorsarg_indrel_indr   matabs_arg_startabs_arg_endother_arg_posrK  vectors_to_loopfirst_not_vector	new_indexlast_vecr  r  s                        @@r=   split_multiple_contractionsz,ArrayContraction.split_multiple_contractionsP  s   . 't,"66$%89 @	2KD%5zQ& 44T:I !%		a 9KG$- 3 **73kk-3-F-Fs-K*{ !'	 - =cii''1,5#))v:Me	BU8Vee&&W~6NNC>23 ;!# 
 & :
7.qyy9	:)"1o7+ab/IO(7(:%g(009I-a3 *
7%.		'""<<>	yyt,G;;;3<		!))//$/0&&q)* !0 3Hg(1HW%A@	2D ! 	?A5!tf#=>	? **,,r?   c           
        t        | j                  t              s| S | j                  j                  | j                  j                  | j
                        }g }| j                  j                  d d  }|D ]  }t        |      }|D ]R  }|D cg c]	  }||v s| }}|j                  |D 	cg c]  }|D ]  }	|	  c}	}       |D cg c]	  }||vs| }}T |j                  t        t        |                    t        j                  ||      }t        t        | j                  j                  g| g| S c c}w c c}	}w c c}w r2   )r3   r   r   ru  r   r   r   r   r   r
  r   r(  r   r   )
r;   contraction_downr5  r   r`   r  rj   r   diagonal_withr
  s
             r=   flatten_contraction_of_diagonalz0ArrayContraction.flatten_contraction_of_diagonal  sM   $))]3K9977		8R8RTXTlTlm"$9955a8! 	KA $Q [,< GqQ G G!((])NA)Nq!)N!)NO/?#Z!1MCYA#Z #Z[ $**6#6G2H+IJ	K #0"@"@AQSj"k!		!

 %
 	
 !H)N#Zs   	D>D>+E	E	E	c                    i }|D cg c]  }|D ]  }|  }}}d}| D ]  }||v r
|dz  }||v r
|||<   |dz  } |S c c}}w Nr   rY   rF   )free_indicesr   r  r`   rj   r  r,  inds           r=   !_get_free_indices_to_position_mapz2ArrayContraction._get_free_indices_to_position_map  s|    #% 4G(SqQR(SA(S(S%(S 	C::1 ::,3$S)qLG		
 (' )Ts   >c                   | j                   }|D cg c]  }|D ]  }|  }}}|j                          t        |       }t        |      }||z
  }t	        |      D cg c]  }d }}d}	d}
t	        |      D ]9  }|
|k  r |	||
   k\  r|	dz  }	|
dz  }
|
|k  r	|	||
   k\  r||xx   |
z  cc<   |	dz  }	; |S c c}}w c c}w )a  
        Get the mapping of indices at the positions before the contraction
        occurs.

        Examples
        ========

        >>> from sympy.tensor.array import tensorproduct, tensorcontraction
        >>> from sympy import MatrixSymbol
        >>> M = MatrixSymbol("M", 3, 3)
        >>> N = MatrixSymbol("N", 3, 3)
        >>> cg = tensorcontraction(tensorproduct(M, N), [1, 2])
        >>> cg._get_index_shifts(cg)
        [0, 2]

        Indeed, ``cg`` after the contraction has two dimensions, 0 and 1. They
        need to be shifted by 0 and 2 to get the corresponding positions before
        the contraction (that is, 0 and 3).
        r   rY   )r   r  r   r{   rh   )r   inner_contraction_indicesr`   rj   r  r  r  r  r  r,  r  s              r=   _get_index_shiftsz"ArrayContraction._get_index_shifts  s    * %)$<$<! 9E11EaQEQE	E!$'
^
*,
":./!//z" 	AJ&7i6H+H11 J&7i6H+H 1I IqLG	  F 0s   B5	B;c                Z    t         j                  |       t        fd|D              }|S )Nc              3  F   K   | ]  }t        fd |D                yw)c              3  .   K   | ]  }|   |z     y wr2   rF   r  s     r=   ra   zUArrayContraction._convert_outer_indices_to_inner_indices.<locals>.<genexpr>.<genexpr>  s     /I!q	A/Ir   Nr  r  s     r=   ra   zKArrayContraction._convert_outer_indices_to_inner_indices.<locals>.<genexpr>  s     )ma%/Iq/I*I)mr  )r   r1  rs   )r   outer_contraction_indicesr  s     @r=   r`  z8ArrayContraction._convert_outer_indices_to_inner_indices  s+    !33D9$))mSl)m$m!((r?   c                |    | j                   }t        j                  | g| }||z   }t        | j                  g| S r2   )r   r   r`  r   r   )r   r5  r0  r   s       r=   r   zArrayContraction._flatten  sG    $($<$<!$4$\$\]a$~d}$~!7:SS!$))B.ABBr?   c                (     | j                   |g| S r2   r  )rM   r   r   s      r=   r  z:ArrayContraction._ArrayContraction_denest_ArrayContraction  s    s||D7#677r?   c                    |D cg c]  }|D ]  }|  }}}t        |j                        D cg c]  \  }}||vs| }}}t        | S c c}}w c c}}w r2   )r   r0   r   )rM   r   r   r`   rj   r)  r.  r0   s           r=   r  z3ArrayContraction._ArrayContraction_denest_ZeroArray  s^    /B#N!A#NqA#NA#N #N(4Ztq!AY8YZZ%   $OZs   AAAc           	     `    t        |j                  D cg c]  }t        |g|  c} S c c}w r2   )ra  r   r   )rM   r   r   r`   s       r=   r  z2ArrayContraction._ArrayContraction_denest_ArrayAdd  s.    QUQZQZ[A.qG3FG[\\[r  c                L   |j                   j                  }|D cg c]  }t        fd|D               }}|D cg c]  t        fd|D              r }}| j	                  ||      }t        t        |j                  g| t        |            S c c}w c c}w )Nc              3  .   K   | ]  } |        y wr2   rF   )r_   rj   r   s     r=   ra   zHArrayContraction._ArrayContraction_denest_PermuteDims.<locals>.<genexpr>  s     (CAQ(Cr   c              3  &   K   | ]  }|v  
 y wr2   rF   r  s     r=   ra   zHArrayContraction._ArrayContraction_denest_PermuteDims.<locals>.<genexpr>  s     0YAa0Yr  )	r   r	  rs   r|   r(  r   r   r   r+   )rM   r   r   r  r`   r5  	new_plistr   s       `  @r=   r  z5ArrayContraction._ArrayContraction_denest_PermuteDims  s    &&&&M`"a5(C(C#C"a"a %Z1S0YAX0Y-YQZ	Z(()@)L	tyyC+BC	"
 	
 #bZs   BB!B!c                   t        |j                        }|j                  |j                  |t        |j                              }|D cg c]4  }|D cg c]$  }t        |t        t        f      r|n|gD ]  }| & c}}6 }}}}g }|D ]k  }	|	d d  }
t        |      D ]3  \  }	t        fd|	D              s|
j                         d ||<   5 |j                  t        t        |
                   m |D cg c]  }||	 }}t        j                  ||      }t!        t#        |j                  g| g| S c c}}w c c}}}w c c}w )Nc              3  &   K   | ]  }|v  
 y wr2   rF   )r_   r`   diag_indgrps     r=   ra   zJArrayContraction._ArrayContraction_denest_ArrayDiagonal.<locals>.<genexpr>1  s     >AqK'>r  )r   r   ru  r   r   r3   rs   r   r   r|   r   r   r
  r   r   r(  r   r   )rM   r   r   r   down_contraction_indicesr`   rj   r   r5  contr_indgrpr-  new_diagonal_indices_downnew_diagonal_indicesr@  s                @r=   r  z7ArrayContraction._ArrayContraction_denest_ArrayDiagonal%  sx    5 56#'#:#:4;P;PRegoptpypygz#{  tL  $M  $Mno$i1APUW\~A^Aefdg$iaQ$iQ$i  $M   $M"$4 	=Lq/C"+,<"= /;&>>>JJ{+*.$Q'/ $**6#c(+;<	= 1A$R1AMQ$R!$R/@@AXZsttyyC+BC
!
 	
 %j  $M %Ss$   
E
)E E
 EEE
c                T   j                   |fS t        t        dgj                  z               }t	        t        j                              D cg c]   }t        t	        ||   ||dz                  " }}|D ch c]  }|D ]  }|  c}}t        j                        D cg c],  \  }}t        fdt	        ||   ||dz            D              . c}}t        t	        t        j                              fd      }|D cg c]  }j                  |    }	}|D cg c]  }||   D ]  }|  }
}}t        |
      |D cg c]  }t        fd|D               }}t        |      }t        |	 |fS c c}w c c}}w c c}}w c c}w c c}}w c c}w )Nr   rY   c              3  &   K   | ]  }|v  
 y wr2   rF   )r_   rj   r)  s     r=   ra   z?ArrayContraction._sort_fully_contracted_args.<locals>.<genexpr>D  s     c!%= =cr  c                F    |    rdt        j                  |          fS dS )Nr   )rY   )r   r   )r  r   fully_contracteds    r=   r  z>ArrayContraction._sort_fully_contracted_args.<locals>.<lambda>E  s1    euvwexqBRSWS\S\]^S_B`>a   C r?   r  c              3  (   K   | ]	  }|     y wr2   rF   )r_   rj   index_permutation_array_forms     r=   ra   z?ArrayContraction._sort_fully_contracted_args.<locals>.<genexpr>I  s     (TQ)Ea)H(Tr'  )r0   r   r   r   rh   r{   r   r   rd   r
  r,   rs   r%   r   )rM   r   r   r  r`   r/  rj   r   new_posr   new_index_blocks_flatr5  r)  rH  rJ  s    `          @@@r=   r  z,ArrayContraction._sort_fully_contracted_args=  s   ::,,,Zdmm 345CHTYYCXYaU58U1Q3Z89YY/B#N!A#NqA#NA#N r{  }A  }F  }F  sG  HhnhiknCcuUSTXW\]^_`]`WaGbcc  Hs499~.  5C  D*12QDIIaL22,3 Mq\!_ M M M M'12G'H$^q"rYZ5(TRS(T#T"r"r";<S"T$h/1HHH Z#N H2 M"rs$   %F	F/1FF2FF%c           	         | j                   }| j                  D cg c]  }|D cg c]  }||   	 c} c}}S c c}w c c}}w )a  
        Return tuples containing the argument index and position within the
        argument of the index position.

        Examples
        ========

        >>> from sympy import MatrixSymbol
        >>> from sympy.abc import N
        >>> from sympy.tensor.array import tensorproduct, tensorcontraction
        >>> A = MatrixSymbol("A", N, N)
        >>> B = MatrixSymbol("B", N, N)

        >>> cg = tensorcontraction(tensorproduct(A, B), (1, 2))
        >>> cg._get_contraction_tuples()
        [[(0, 1), (1, 0)]]

        Notes
        =====

        Here the contraction pair `(1, 2)` meaning that the 2nd and 3rd indices
        of the tensor product `A\otimes B` are contracted, has been transformed
        into `(0, 1)` and `(1, 0)`, identifying the same indices in a different
        notation. `(0, 1)` is the second index (1) of the first argument (i.e.
                0 or `A`). `(1, 0)` is the first index (i.e. 0) of the second
        argument (i.e. 1 or `B`).
        )r  r   )r;   mappingr`   rj   s       r=   _get_contraction_tuplesz(ArrayContraction._get_contraction_tuplesM  s9    8 --151I1IJAQ''JJ'Js   	?:??c                    | j                   }dgt        t        |            z   |D cg c]  }t        fd|D               c}S c c}w )Nr   c              3  4   K   | ]  \  }}|   |z     y wr2   rF   )r_   rj   r   r   s      r=   ra   zNArrayContraction._contraction_tuples_to_contraction_indices.<locals>.<genexpr>q  s      :1&q)!+:r   )r   r   r   rs   )r   contraction_tuplesr   r`   r   s       @r=   *_contraction_tuples_to_contraction_indicesz;ArrayContraction._contraction_tuples_to_contraction_indicesl  sD     3j&7!88DVWq:::WWWs   Ac                     | j                   d d  S r2   )_free_indicesrT   s    r=   r,  zArrayContraction.free_indicess  s    !!!$$r?   c                ,    t        | j                        S r2   )dictr  rT   s    r=   r  z)ArrayContraction.free_indices_to_positionw  s    D2233r?   c                     | j                   d   S rQ   r  rT   s    r=   r   zArrayContraction.expr{  r  r?   c                     | j                   dd  S rX   r  rT   s    r=   r   z$ArrayContraction.contraction_indices  r  r?   c                    | j                   }t        |t              st        d      |j                  }i }d}t        |      D ]!  \  }}t        |      D ]  }||f||<   |dz  } # |S )Nz(only for contractions of tensor productsr   rY   )r   r3   r   r   r   r   rh   )r;   r   r   rN  r,  r`   r  rj   s           r=   "_contraction_indices_to_componentsz3ArrayContraction._contraction_indices_to_components  s~    yy$ 23%&PQQ ' 	GAt4[ $%q6 1	 r?   c                   | j                   }t        |t              s| S |j                  }t	        t        |      d       }t        | \  }}t        |      D ci c]  \  }}||j                  |       }}}| j                         }	|	D 
cg c]  }|D 
cg c]  \  }
}||
   |f c}}
 }	}
}}t        | }| j                  ||	      }t        |g| S c c}}w c c}}
w c c}}
}w )a  
        Sort arguments in the tensor product so that their order is lexicographical.

        Examples
        ========

        >>> from sympy.tensor.array.expressions.from_matrix_to_array import convert_matrix_to_array
        >>> from sympy import MatrixSymbol
        >>> from sympy.abc import N
        >>> A = MatrixSymbol("A", N, N)
        >>> B = MatrixSymbol("B", N, N)
        >>> C = MatrixSymbol("C", N, N)
        >>> D = MatrixSymbol("D", N, N)

        >>> cg = convert_matrix_to_array(C*D*A*B)
        >>> cg
        ArrayContraction(ArrayTensorProduct(A, D, C, B), (0, 3), (1, 6), (2, 5))
        >>> cg.sort_args_by_name()
        ArrayContraction(ArrayTensorProduct(A, D, B, C), (0, 3), (1, 4), (2, 7))
        c                    t        | d         S rX   r   r  s    r=   r  z4ArrayContraction.sort_args_by_name.<locals>.<lambda>  s    <LQqT<R r?   r  )r   r3   r   r   r
  r   r}   rl  rO  r   rS  r   )r;   r   r   sorted_data
pos_sortedr   r`   r   reordering_maprR  rj   r   c_tprd  s                 r=   sort_args_by_namez"ArrayContraction.sort_args_by_name  s    * yy$ 23KyyYt_2RS"%{"3
K?HOVQ!Z--a00OO!99;N`aa!D$!Qq 115Daa$k2 KK"
 "$;):;; PDas   C
C'C!+C'!C'c                P    t        | g| j                  g| j                   \  }}|S )ao  
        Returns a dictionary of links between arguments in the tensor product
        being contracted.

        See the example for an explanation of the values.

        Examples
        ========

        >>> from sympy import MatrixSymbol
        >>> from sympy.abc import N
        >>> from sympy.tensor.array.expressions.from_matrix_to_array import convert_matrix_to_array
        >>> A = MatrixSymbol("A", N, N)
        >>> B = MatrixSymbol("B", N, N)
        >>> C = MatrixSymbol("C", N, N)
        >>> D = MatrixSymbol("D", N, N)

        Matrix multiplications are pairwise contractions between neighboring
        matrices:

        `A_{ij} B_{jk} C_{kl} D_{lm}`

        >>> cg = convert_matrix_to_array(A*B*C*D)
        >>> cg
        ArrayContraction(ArrayTensorProduct(B, C, A, D), (0, 5), (1, 2), (3, 6))

        >>> cg._get_contraction_links()
        {0: {0: (2, 1), 1: (1, 0)}, 1: {0: (0, 1), 1: (3, 0)}, 2: {1: (0, 0)}, 3: {0: (1, 1)}}

        This dictionary is interpreted as follows: argument in position 0 (i.e.
        matrix `A`) has its second index (i.e. 1) contracted to `(1, 0)`, that
        is argument in position 1 (matrix `B`) on the first index slot of `B`,
        this is the contraction provided by the index `j` from `A`.

        The argument in position 1 (that is, matrix `B`) has two contractions,
        the ones provided by the indices `j` and `k`, respectively the first
        and second indices (0 and 1 in the sub-dict).  The link `(0, 1)` and
        `(2, 0)` respectively. `(0, 1)` is the index slot 1 (the 2nd) of
        argument in position 0 (that is, `A_{\ldot j}`), and so on.
        )r(   r   r   )r;   r   dlinkss      r=   r(   z'ArrayContraction._get_contraction_links  s+    R .tfdmm_dF^F^_fr?   c                ~    | j                   }t        |d      r|j                         }t        |g| j                   S r   )r   ry   rl   r   r   rf  s     r=   rl   zArrayContraction.as_explicit  s9    yy4'##%D A(@(@AAr?   N)r   z'ArrayDiagonal')%rB   rC   rD   rn   rL   r   r  r  r  ro  r   ru  r(  r  r%  r)  r.  r1  r`  r   r  r  r  r  r  r  rO  rS  rp   r,  r  r   r   r[  rb  r(   rl   rF   r?   r=   r   r     s   
,!IFnn P P H H H H 2 2<b-H
. 	( 	( $ $L ) )
 C C 8 8 ! !
 ] ] 	
 	
 
 
. I IK> X X % % 4 4    #<J*XBr?   r   c                  B    e Zd ZdZd Zed        Zed        Zd Zd Z	y)Reshapea  
    Reshape the dimensions of an array expression.

    Examples
    ========

    >>> from sympy.tensor.array.expressions import ArraySymbol, Reshape
    >>> A = ArraySymbol("A", (6,))
    >>> A.shape
    (6,)
    >>> Reshape(A, (3, 2)).shape
    (3, 2)

    Check the component-explicit forms:

    >>> A.as_explicit()
    [A[0], A[1], A[2], A[3], A[4], A[5]]
    >>> Reshape(A, (3, 2)).as_explicit()
    [[A[0], A[1]], [A[2], A[3]], [A[4], A[5]]]

    c                <   t        |      }t        |t              st        | }t        t	        j
                  |j                        t	        j
                  |            dk(  rt        d      t        j                  | ||      }t        |      |_        ||_        |S )NFzshape mismatch)r-   r3   r   r	   r   r   r0   re   r   rL   rs   r   _expr)rM   r   r0   rO   s       r=   rL   zReshape.__new__  sx    ~%'5MECLL,cll5.ABeK-..ll3e,5\
	
r?   c                    | j                   S r2   r   rT   s    r=   r0   zReshape.shape
  r   r?   c                    | j                   S r2   )ri  rT   s    r=   r   zReshape.expr  r   r?   c                   |j                  dd      r | j                  j                  |i |}n| j                  }t        |t        t
        f      r |j                  | j                   S t        || j                        S )Nr   T)	r   r   r   r3   r   r    ri   r0   rg  )r;   r   r   r   s       r=   r   zReshape.doit  sg    ::fd#!499>>4262D99DdZ344<<,,tTZZ((r?   c                    | j                   }t        |d      r|j                         }t        |t              rddlm}  ||      }nt        |t              r| S  |j                  | j                   S )Nrl   r   )Array)
r   ry   rl   r3   r   sympyrn  r   ri   r0   )r;   eern  s      r=   rl   zReshape.as_explicit  s[    YY2}%!Bb*%#rBJ'Krzz4::&&r?   N)
rB   rC   rD   rn   rL   rp   r0   r   r   rl   rF   r?   r=   rg  rg    s>    ,	    )	'r?   rg  c                  0    e Zd ZU dZded<   dddZd ZeZy)	r  al  
    The ``_ArgE`` object contains references to the array expression
    (``.element``) and a list containing the information about index
    contractions (``.indices``).

    Index contractions are numbered and contracted indices show the number of
    the contraction. Uncontracted indices have ``None`` value.

    For example:
    ``_ArgE(M, [None, 3])``
    This object means that expression ``M`` is part of an array contraction
    and has two indices, the first is not contracted (value ``None``),
    the second index is contracted to the 4th (i.e. number ``3``) group of the
    array contraction object.
    zlist[int | None]rt   Nc                ~    || _         |(t        t        |            D cg c]  }d  c}| _        y || _        y c c}w r2   )r  rh   r   rt   )r;   r  rt   r`   s       r=   __init__z_ArgE.__init__9  s7    ?*/0A*BCQDCDL"DL Ds   	:c                <    d| j                   d| j                  dS )Nz_ArgE(z, ))r  rt   rT   s    r=   __str__z_ArgE.__str__@  s    "&,,==r?   r2   )rt   zlist[int | None] | None)rB   rC   rD   rn   rE   rs  rv  __repr__rF   r?   r=   r  r  '  s      #> Hr?   r  c                  (    e Zd ZdZddZd ZeZd Zy)_IndPosz
    Index position, requiring two integers in the constructor:

    - arg: the position of the argument in the tensor product,
    - rel: the relative position of the index inside the argument.
    c                     || _         || _        y r2   r   rel)r;   r   r|  s      r=   rs  z_IndPos.__init__M  s    r?   c                8    d| j                   | j                  fz  S )Nz_IndPos(%i, %i)r{  rT   s    r=   rv  z_IndPos.__str__Q  s     DHHdhh#777r?   c              #  P   K   | j                   | j                  gE d {    y 7 wr2   r{  rT   s    r=   __iter__z_IndPos.__iter__V  s     HHdhh'''s   &$&N)r   rv  r|  rv  )rB   rC   rD   rn   rs  rv  rw  r  rF   r?   r=   ry  ry  F  s    8 H(r?   ry  c                      e Zd ZdZddZddZd Zd Zd Zd Z	ddZ
dd	Zdd
ZddZddZed        Zd ZddZddZddZy)r  a  
    Utility class to help manipulate array contraction objects.

    This class takes as input an ``ArrayContraction`` object and turns it into
    an editable object.

    The field ``args_with_ind`` of this class is a list of ``_ArgE`` objects
    which can be used to easily edit the contraction structure of the
    expression.

    Once editing is finished, the ``ArrayContraction`` object may be recreated
    by calling the ``.to_array_contraction()`` method.
    c                   t        |t              r1t        |j                        }|j                  }|j
                  }d}nt        |t              rt        |j                  t              rt        |j                  j                        }|j                  j                  }t        j                  |j                  j
                  |j                        }|j                  j
                  }nut        |j                  t              ri }|j                  }|j                  }g }n>i }|j                  }|j                  }g }n!t        |t              r|}g }d}n
t               t        |t              rt        |j                        }n|g}|D cg c]  }t        |       }}t        |      D ]&  \  }	}
|
D ]  }|   \  }}|	||   j                  |<    ( || _        t#        |      | _        d | _        t        |j                        }t        |      D ]3  \  }	}|D ])  }||   \  }}d|	z
  | j                   |   j                  |<   + 5 y c c}w )NrF   r   )r3   r   r&   r   r   r   r   ru  r   r   r   r   r   r  r   rt   r  r{   number_of_contraction_indices_track_permutation)r;   
base_arrayrN  r   r   diagonalizedr   r   r  r`   contraction_tuplerj   arg_posrel_posr.  s                  r=   rs  z_EditArrayContraction.__init__i  s7   
 j"2301D1DEG??D","@"@L
M2*//+;<4Z__5M5MN!++/BB:??CfCfhr  iD  iD   E&0oo&I&I#JOO-?@!)::&(#!)::&(#
$67D"$L%''d./		?D6D<@%ASeCj%A%A$-.A$B 	< A & <#*1: :;g&..w7<	< +8256I2J*:>,Z-@-@A l+ 	FDAq F#*1: ?AAv""7+33G<F	F &Bs   Ic                x    | j                   j                  |      }| j                   j                  |dz   |       y rX   )r  rl  insert)r;   r   new_argposs       r=   r  z"_EditArrayContraction.insert_after  s2      &&s+!!#'73r?   c                J    | xj                   dz  c_         | j                   dz
  S rX   )r  rT   s    r=   r  z/_EditArrayContraction.get_new_contraction_index  s$    **a/*11A55r?   c                z   i }| j                   D ]/  }|j                  |j                  D ci c]  }||d
 c}       1 t        t	        |            D ]
  \  }}|||<    t        |      | _        | j                   D ]1  }|j                  D cg c]  }|j                  |d        c}|_        3 y c c}w c c}w )Nr   )r  r   rt   r   r
  r{   r  r   )r;   updatesarg_with_indr`   r.  s        r=   refresh_indicesz%_EditArrayContraction.refresh_indices  s     .. 	SLNN<+?+?Qa1=ArEQR	SfWo. 	DAqGAJ	-0\* .. 	XLBNBVBV#WQGKK4$8#WL 	X	 R
 $Xs   B3
B3
B8c                   g }| j                   D ],  }t        |j                        dk(  s|j                  |       . |D ]  }| j                   j	                  |        t        j                  |D cg c]  }|j                   c}      }t        | j                         dk(  r%| j                   j                  t        |             y ddl	m
}  ||| j                   d   j                        | j                   d   _        y c c}w )Nr   )_a2m_tensor_product)r  r{   rt   r   remover   r   r  r  3sympy.tensor.array.expressions.from_array_to_matrixr  )r;   scalarsr  r`   scalarr  s         r=   merge_scalarsz#_EditArrayContraction.merge_scalars  s     .. 	-L<''(A-|,	-  	)A%%a(	)':Qqyy:;t!!"a'%%eFm4_,?HZHZ[\H]HeHe,fDq!) ;s   3Dc           	     P   d}t        t              }t               }| j                  D ]&  }|j	                  t        |j
                               ( |d    }g }g }t               }d}	| j                  D ]  }d}
|j
                  D ]  }||j                  |	       |
dz  }
|	dz  }	!|dk\  r'|d|z
     j                  ||
z          ||   dk(  r-||vr)|j                  |dz
  |z
         |j                  |       n,||vr(|j                  |dz
  |z
         |j                  |       |
dz  }
 |j
                  D cg c]  }||dk\  r|nd  c}|_        |t        |j
                  D cg c]  }||dk  s| c}      z  } ||z   }t        |      }|j                         D cg c]  }t        |      dkD  st        |       }}| j                          | j                          | j                  D cg c]  }|j                   }}| j!                         }t#        t%        | g| }t'        |g| }| j(                  8t        | j(                  D cg c]  }|D ]  }|  c}}      }t+        ||      }t+        ||      }|S c c}w c c}w c c}w c c}w c c}}w r8  )r   r   r   r  r   rt   r   r   r   r{   r,   valuesrs   r  r  r  get_contraction_indicesr   r   r   r  r   )r;   r,  diag_indicescount_index_freqr  free_index_count	inv_perm1	inv_perm2donecounter4counter2r`   r   r   rK  diag_indices_filteredr   r   r   r   expr2rj   permutation2expr3s                           r=   r  z*_EditArrayContraction.to_array_contraction  s    "4("9 .. 	CL##GL,@,@$AB	C ,D1 		u  .. 	TL H!)) 9$$X.MHMH6R!V$++Gh,>?#A&!+$$%5%9A%=>HHQKd]$$%5%9A%=>HHQKA!$ VbUiUi#jPQ16At$K#jL s|';';R!qyAPQEARSSG1	T4 ()3 !45 4@3F3F3H WaCPQFUVJq W W'+'9'9:::"::<!"7">UATU='<="".%$2I2I&UQST&Uaq&Uq&UVL!%6Ee[1) $kR !X ;
 'Vs*   ;J)J6J(J<J9JJ"
c                    t        | j                        D cg c]  }g  }}d}| j                  D ].  }|j                  D ]  }|||   j	                  |       |dz  } 0 |S c c}w r+  )rh   r  r  rt   r   )r;   r`   r   current_positionr  rj   s         r=   r  z-_EditArrayContraction.get_contraction_indices  s    <A$BdBd<e/fq/f/f ! .. 	&L!)) &='*112BC A% &	&
 #" 0gs   	A$c                    || j                   k\  rt        d      g }t        | j                        D ]C  \  }}t        |j                        D ]&  \  }}||k(  s|j                  t        ||             ( E |S )Nz%index value exceeding the index range)r  re   r   r  rt   r   ry  )r;   r-  rs  r`   r  rj   r  s          r=   r  z+_EditArrayContraction.get_mapping_for_index  s    $444DEE#%	(););< 	4OA|'(<(<= 4
7'>$$WQ]34	4 r?   c                
   t        | j                        D cg c]  }g  }}t        | j                        D ]C  \  }}t        |j                        D ]&  \  }}|	||   j                  t        ||             ( E |S c c}w r2   )rh   r  r   r  rt   r   ry  )r;   r`   r   r  rj   r-  s         r=   &get_contraction_indices_to_ind_rel_posz<_EditArrayContraction.get_contraction_indices_to_ind_rel_pos  s    @EdFhFh@i3j1B3j3j(););< 	COA|#L$8$89 C3?',33GAqMBC	C #" 4ks   	B c                T    d}| j                   D ]  }||j                  v s|dz  } |S )zJ
        Count the number of arguments that have the given index.
        r   rY   r  rt   )r;   rl  r,  r  s       r=   count_args_with_indexz+_EditArrayContraction.count_args_with_index!  s<      .. 	L,,,1	 r?   c                `    | j                   D cg c]  }||j                  v s| }}|S c c}w )zA
        Get a list of arguments having the given index.
        r  )r;   rl  r`   r[  s       r=   get_args_with_indexz)_EditArrayContraction.get_args_with_index+  s3     (,'9'9P!Uaii=OAPP
 Qs   ++c                    t               }| j                  D ]4  }|j                  |j                  D ch c]  }||dk  s| c}       6 t	        |      S c c}w rQ   )r   r  r   rt   r{   )r;   rk   r   r`   s       r=   number_of_diagonal_indicesz0_EditArrayContraction.number_of_diagonal_indices2  sU    u%% 	MCKKCKKKq1=QUKL	M4y Ls   A
A
A
c                V   g }g }d}d}| j                   D ]Z  }g }|j                  D ]6  }||dk  r|j                  |       |dz  }!|j                  |       |dz  }8 |j                  |       \ |rt        d |D              nd}|D cg c]  }||z
  	 }}||gz   | _        y c c}w )Nr   r   rY   c              3  :   K   | ]  }|rt        |      nd   yw)r   N)rR  r^   s     r=   ra   z@_EditArrayContraction.track_permutation_start.<locals>.<genexpr>I  s     ?ac!fr)?r   )r  rt   r   rR  r  )	r;   r   	perm_diagr,  r  r  permr`   max_inds	            r=   track_permutation_startz-_EditArrayContraction.track_permutation_start9  s    	 .. 
	%LD!)) =1u!((2 AG$1 t$
	% DO#?;??TV*34QWq[4	4"-"; 5s   B&c                    | j                   j                  |      }| j                   j                  |      }| j                  |   j                  | j                  |          | j                  j	                  |       y r2   )r  rl  r  r   r   )r;   destinationfrom_elementindex_destinationindex_elements        r=   track_permutation_mergez-_EditArrayContraction.track_permutation_mergeM  si     ..44[A**00> 1299$:Q:QR_:`a##M2r?   c                    d}| j                   D ];  }t        |j                  D cg c]  }||	 c}      }||k(  r	|||z   fc S ||z  }= t        d      c c}w )zw
        Return the range of the free indices of the arg as absolute positions
        among all free indices.
        r   argument not foundr  r{   rt   rz   )r;   r   r,  r  r`   number_free_indicess         r=   get_absolute_free_rangez-_EditArrayContraction.get_absolute_free_rangeS  sv    
  .. 	+L"%,2F2F&TQ!)q&T"Us"*= ===**G		+
 -..	 'Us
   A
A
c                    d}| j                   D ]*  }t        |j                        }||k(  r	|||z   fc S ||z  }, t        d      )zc
        Return the absolute range of indices for arg, disregarding dummy
        indices.
        r   r  r  )r;   r   r,  r  number_indicess        r=   r  z(_EditArrayContraction.get_absolute_range`  s^    
  .. 	&L !5!56Ns". 888~%G		&
 -..r?   N)r  zAtyping.Union[ArrayContraction, ArrayDiagonal, ArrayTensorProduct])r   r  r  r  )rm   zlist[list[int]])rm   zlist[_IndPos])rm   zlist[list[_IndPos]])rl  rv  rm   rv  )rl  rv  rm   zlist[_ArgE])r  r  r  r  )r   r  rm   ztyping.Tuple[int, int])rB   rC   rD   rn   rs  r  r  r  r  r  r  r  r  r  r  rp   r  r  r  r  r  rF   r?   r=   r  r  Z  sl    7Fr46XgAF##  <(3//r?   r  c                   t        | t        t        f      ryt        | t              rt	        | j
                        S t        | t              r| j                         S t        | t              r| j                  S t        | t              r| j
                  }|yt	        |      S t        | d      rt	        | j
                        S y)Nr  r   r0   r   )r3   r   r#   r   r{   r0   r    r  r!   r"   ry   r  s     r=   r   r   n  s    $]34$-.4::$	"yy{$ yy$$

=u:tW4::r?   c                X    t        | t              r| j                         S t        |       S r2   )r3   r   r   r   r   s    r=   r   r     s#    $-.||~D>r?   c                R    t        | t              r| j                  S t        |       gS r2   )r3   r   r   r   r  s    r=   rr  rr    s$    $-.}}r?   c                4    t        | d      r| j                  S y)Nr0   rF   )ry   r0   r  s    r=   r   r     s    tWzzr?   c                F    t        | t              r| j                         S | S r2   )r3   r   r\  r  s    r=   r\  r\    s     $$$$&&r?   c                     t        | ddi|S Nr   T)r   r   r   s     r=   r   r     s    tA$A&AAr?   c                $    t        | g|ddi|S r  )r   )r   r   r   s      r=   r   r     s    DT#6TTTVTTr?   c                $    t        | g|ddi|S r  )r   )r   r   r   s      r=   r   r     s    N 0NtNvNNr?   c                     t        | |fddi|S r  )r   )r   r   r   s      r=   r   r     s    t[FtFvFFr?   c                     t        | ddi|S r  )r   r  s     r=   ra  ra    s    T7777r?   c                    t        | |      S r2   )r7   )r   rt   s     r=   rA   rA     s    g&&r?   )a
__future__r   collections.abcr4   r   r   r   	functoolsr   rf   r   typingsympy.core.numbersr   sympy.core.relationalr	   (sympy.functions.special.tensor_functionsr   sympy.core.basicr   sympy.core.containersr   sympy.core.exprr   sympy.core.functionr   r   sympy.core.mulr   sympy.core.singletonr   sympy.core.sortingr   sympy.core.symbolr   r   sympy.matrices.matrixbaser   #sympy.matrices.expressions.diagonalr   "sympy.matrices.expressions.matexprr   "sympy.matrices.expressions.specialr   sympy.tensor.array.arrayopr   r   r   r   #sympy.tensor.array.dense_ndim_arrayr   sympy.tensor.array.ndim_arrayr    sympy.tensor.indexedr!   r"   r#   $sympy.tensor.array.expressions.utilsr$   r%   r&   r'   r(   r)   r   r+    sympy.combinatorics.permutationsr,   sympy.core.sympifyr-   r/   rH   r7   r   r   r   r   r   r   r   r  r   rg  r  ry  r  r   r   rr  r   r\  r   r   r   r   ra  rA   rF   r?   r=   <module>r     s   "   ,      & * C " '   2  " / - 0 B 9 9 f f G 3 7 <1 1 , 7 '
7 
7B* B<2[4 2[j
 2z 2-(E -(^Wp. Wpt8^$ 8^vT' Tn
M<) M<`&- 5 &-RXB, XBv<'# <'~ >( ((Q/ Q/h( BUOG8'r?   