
    sg,                    H   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	m
Z
mZmZ d dl	Z	d dlmZ d dlmZ d dlmZ d d	lmZ 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/m0Z0m1Z1 d dl2m3Z3 d dl4m5Z5 d dl6m7Z7m8Z8 d dl)m9Z9 d dl:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@ d dlAmBZB d dlCmDZD d dlEmFZF  G d de      ZG G d  d!eG      ZH G d" d#e      ZI G d$ d%eG      ZJ G d& d'eG      ZK G d( d)e      ZL G d* d+eL      ZM G d, d-eL      ZN G d. d/eL      ZO G d0 d1eL      ZP G d2 d3eL      ZQ G d4 d5eL      ZR G d6 d7eL      ZS G d8 d9      ZT G d: d;      ZU G d< d=      ZVd> ZWd? ZXd@ ZYdA ZZdB Z[dC Z\dD Z]dE Z^dF Z_dG Z`dH Zay)I    N)defaultdictCounter)reduce)
accumulate)OptionalListTuple)Integer)EqualityKroneckerDelta)Basic)r	   )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 eedf   ed<   d Zd Zy)
_ArrayExpr.shapec                     t        |t        j                  j                        s|f}t        j                  | |       | j                  |      S N)
isinstancecollectionsabcIterableArrayElement_check_shape_getselfitems     c/var/www/html/venv/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 r3   )_get_array_element_or_slicer;   s     r>   r:   z_ArrayExpr._get0   s    *466r@   N)__name__
__module____qualname__tTupler   __annotations__r?   r:    r@   r>   r0   r0   '   s    $)7r@   r0   c                   Z    e Zd ZdZdej
                  dd fdZed        Zed        Z	d Z
y)	ArraySymbolz1
    Symbol representing an array expression
    r1   returnc                     t        |t              rt        |      }t        t	        t
        |       }t        j                  | ||      }|S r3   )r4   strr   r	   mapr.   r   __new__)clssymbolr1   objs       r>   rO   zArraySymbol.__new__9   s=    fc"F^Fs8U+,ll3.
r@   c                      | j                   d   S Nr   _argsr<   s    r>   namezArraySymbol.nameA       zz!}r@   c                      | j                   d   S N   rU   rW   s    r>   r1   zArraySymbol.shapeE   rY   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r3   
is_Integer.0is     r>   	<genexpr>z*ArraySymbol.as_explicit.<locals>.<genexpr>J        4A1<<4   z1cannot express explicit array with symbolic shape)allr1   
ValueError	itertoolsproductranger    reshape)r<   jrc   datas       r>   as_explicitzArraySymbol.as_explicitI   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)rC   rD   rE   __doc__typingr7   rO   propertyrX   r1   ro   rH   r@   r>   rJ   rJ   4   sL    FOO      Br@   rJ   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)	r8   z!
    An element of an array.
    Tc                    t        |t              rt        |      }t        |      }t        |t        j
                  j                        s|f}t        t        |            }| j                  ||       t        j                  | ||      }|S r3   )r4   rM   r   r.   r5   r6   r7   tupler9   r   rO   )rP   rX   indicesrR   s       r>   rO   zArrayElement.__new__Y   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 )Nr1   z3number of indices does not match shape of the arrayc              3   2   K   | ]  \  }}||k\  d k(    yw)TNrH   )rb   rc   ss      r>   rd   z,ArrayElement._check_shape.<locals>.<genexpr>k   s     I1AFt#Is   zshape is out of boundsc              3   ,   K   | ]  }|d k  dk(    yw)r   TNrH   ra   s     r>   rd   z,ArrayElement._check_shape.<locals>.<genexpr>m   s     01A$0s   zshape contains negative values)ru   hasattr
IndexErrorlenr1   anyziprh   )rP   rX   rv   index_errors       r>   r9   zArrayElement._check_shaped   s~    .4!$%Z[K7|s4::.!!IGTZZ0HII !9::000=>> 1r@   c                      | j                   d   S rT   rU   rW   s    r>   rX   zArrayElement.namep   rY   r@   c                      | j                   d   S r[   rU   rW   s    r>   rv   zArrayElement.indicest   rY   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r3   r   rb   rc   rm   s      r>   rd   z0ArrayElement._eval_derivative.<locals>.<genexpr>   s     ZTQN1a0Z   )
r4   r8   r   ZeroOnerX   r   fromiterr   rv   )r<   ry   s     r>   _eval_derivativezArrayElement._eval_derivativex   sb    !\*66M955L66TYY66M||ZSqyy=YZZZr@   N)rC   rD   rE   rp   	_diff_wrt	is_symbolis_commutativerO   classmethodr9   rr   rX   rv   r   rH   r@   r>   r8   r8   P   s_     IIN	 	? 	?    
[r@   r8   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 rT   )r}   r   r   rN   r.   r   rO   rP   r1   rR   s      r>   rO   zZeroArray.__new__   s:    u:?66MHe$ll3''
r@   c                     | j                   S r3   rU   rW   s    r>   r1   zZeroArray.shape       zzr@   c                     t        d | j                  D              st        d      t        j                  | j                   S )Nc              3   4   K   | ]  }|j                     y wr3   r_   ra   s     r>   rd   z(ZeroArray.as_explicit.<locals>.<genexpr>   re   rf   /Cannot return explicit form for symbolic shape.)rg   r1   rh   r    zerosrW   s    r>   ro   zZeroArray.as_explicit   s5    444NOO&,,djj99r@   c                 "    t         j                  S r3   )r   r   r;   s     r>   r:   zZeroArray._get   s    vvr@   N	rC   rD   rE   rp   rO   rr   r1   ro   r:   rH   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 rT   )r}   r   r   rN   r.   r   rO   r   s      r>   rO   zOneArray.__new__   s:    u:?55LHe$ll3''
r@   c                     | j                   S r3   rU   rW   s    r>   r1   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r3   r_   ra   s     r>   rd   z'OneArray.as_explicit.<locals>.<genexpr>   re   rf   r   )rg   r1   rh   r    rk   r   operatormulr   r   rl   )r<   rc   s     r>   ro   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 r3   )r   r   r;   s     r>   r:   zOneArray._get   s    uur@   Nr   rH   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)	_subranksrW   s    r>   subranksz_CodegenArrayAbstract.subranks   s    4 ~~a  r@   c                 ,    t        | j                        S )z*
        The sum of ``subranks``.
        )sumr   rW   s    r>   subrankz_CodegenArrayAbstract.subrank   s     4==!!r@   c                     | j                   S r3   _shaperW   s    r>   r1   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deepTrH   )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)rC   rD   rE   rr   r   r   r1   r   rH   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r3   rH   ra   s     r>   rd   z-ArrayTensorProduct.__new__.<locals>.<genexpr>        )QqDy)   c              3   .   K   | ]  }|D ]  }|   y wr3   rH   r   s      r>   rd   z-ArrayTensorProduct.__new__.<locals>.<genexpr>   s     <Q!<Qq<q<s   )r.   popget_rankr   rO   r   	get_shaper~   r   ru   r   )	rP   r   kwargsr   r   ranksrR   rc   shapess	            r>   rO   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 )
Nr\   r   c              3   H   K   | ]  }t        |t        t        f        y wr3   )r4   r   r   )rb   r   s     r>   rd   z3ArrayTensorProduct._canonicalize.<locals>.<genexpr>  s     HCz#	:67Hs    "rH   c              3   .   K   | ]  }   |z     y wr3   rH   )rb   kcumulative_ranksrc   s     r>   rd   z3ArrayTensorProduct._canonicalize.<locals>.<genexpr>  s     (LQ)9!)<q)@(L   c              3   .   K   | ]  }   |z     y wr3   rH   )rb   r   cumulative_ranks2rc   s     r>   rd   z3ArrayTensorProduct._canonicalize.<locals>.<genexpr>2  s     %J1&7&:Q&>%Jr   r   F)#r   _flattenr   	enumerater4   PermuteDimsextendpermutationcyclic_formr   expr_permute_dims_array_tensor_productr,   r}   r~   r   r   addr   r   ArrayContraction_get_subranklistr   itemscontraction_indicesru   _array_contractionArrayDiagonaldiagonal_indicesrk   _array_diagonalr-   r   )r<   r   r   r   permutation_cyclesrm   r   rc   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 r3   )r4   r   )rP   r   r   rc   s       r>   r   zArrayTensorProduct._flatten7  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 Nro   )r   r   r{   ro   r<   r   s     r>   ro   zArrayTensorProduct.as_explicit<  s9    dhdmdmn]`GC4Os0UXXnoons   %=N)	rC   rD   rE   rp   rO   r   r   r   ro   rH   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 )Nr\   z!summing arrays of different rankszmismatching shapes in additionr   Fc              3   $   K   | ]  }|d u  
 y wr3   rH   ra   s     r>   rd   z#ArrayAdd.__new__.<locals>.<genexpr>S  r   r   r   )r.   r   r   setr}   rh   r1   r   r   rO   r   r~   r   r   )	rP   r   r   r   r   r   rc   r   rR   s	            r>   rO   zArrayAdd.__new__E  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r3   rH   ra   s     r>   rd   z)ArrayAdd._canonicalize.<locals>.<genexpr>d  s     2	12s   zIcannot handle addition of ZeroMatrix/ZeroArray and undefined shape objectr\   r   F)
r   _flatten_argsr   r4   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 r3   )r4   r   r   r   append)rP   r   new_argsr   s       r>   r   zArrayAdd._flatten_argsk  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   r{   ro   r   s     r>   ro   zArrayAdd.as_explicitu  sD    LLRVR[R[\3'#}"=S__3F\^ 	^\s   %A
N)	rC   rD   rE   rp   rO   r   r   r   ro   rH   r@   r>   r   r   @  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r3   rH   )rb   rc   r   r1   s     r>   rd   z&PermuteDims.__new__.<locals>.<genexpr>  s     Pu[^4P   )sympy.combinatoricsr,   r.   r   _get_permutation_from_argumentssizerh   r   r   rO   r   r   r   ru   rk   r}   r   )rP   r   r   index_order_oldindex_order_newr   r,   	expr_rankpermutation_sizer   rR   r1   s     `        @r>   rO   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   r4   r   r   '_PermuteDims_denestarg_ArrayContractionr   )_PermuteDims_denestarg_ArrayTensorProductr   r   
array_formr1   sortedr   )r<   r   r   subexprsubpermrc   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 rT   r   rW   s    r>   r   zPermuteDims.expr      yy|r@   c                      | j                   d   S r[   r  rW   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   r\   c                     | d   S r[   rH   xs    r>   <lambda>zGPermuteDims._PermuteDims_denestarg_ArrayTensorProduct.<locals>.<lambda>  s
    ad r@   key)r-   r  r   r   r   r   rk   r}   r   r  sortr,   r   )rP   r   r   perm_image_formr   cumulrc   perm_image_form_in_componentscomppsperm_args_image_formargs_sortedperm_image_form_sorted_argsrm   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        |      D ]P  \  }}g }t        |
|   |
|dz            D ]   }||	v r|j                  ||          |dz  }" |j                  |       R 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   r\   r   c                     | d   S r[   rH   r  s    r>   r  zEPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<lambda>4  s
    ! r@   r  c              3   (   K   | ]	  }|     y wr3   rH   )rb   rm   new_index_perm_array_forms     r>   rd   zFPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<genexpr><  s     (Q!)B1)E(Q   )r4   r   r   r   r   r   r   r   r   r-   r  r   rk   r   r   _push_indices_upr  ru   r   r   r,   )rP   r   r   r   r   r   r   rc   rm   contraction_indices_flatr  permutation_array_blocks_up
image_formcounterecurrent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
h' 	8DAq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'J,(J2	J=J8#
J8-J= K2K
K
&K8K5KK"8J=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   r\   r   )r   r   r   rk   r   r   r   r   r   r}   r  minr   r,   r   r   nextiterpopitemr   r   ) rP   r   r   r   rc   r   rm   	index2argpermuted_indicesr   arg_candidate_indexcurrent_indicesr$  inserted_arg_cand_indicesidxarg_candidate_ranklocal_current_indicesr   args_positionsmapscumulative_subranksry   elemlinescurrent_liner   vliner/  permutation_blocksnew_permutation_blocksnew_permutation2s                                    r>   _check_permutation_mappingz&PermuteDims._check_permutation_mappingA  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                 ~   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 ]S  }||   ||   k\  s|	|   ||dz      k  st        ||   t        ||   D cg c]
  }|||   z
   c}g            ||<   d} n |sx|
j                  ||           t        | t        |
|j                        fS c c}w c c}w c c}w )Nr   Tr\   F)r  )r   r   r   r   r   r;  maxr   rk   r}   r   r,   r   r   r  )rP   r   r   r   r   r   rI  rc   
cyclic_min
cyclic_maxcyclic_keepcycleflagrm   r   s                  r>   !_check_if_there_are_closed_cyclesz-PermuteDims._check_if_there_are_closed_cycles  s[   DII==!-- cDH)=$>>&12c!f2
2&12c!f2
2!+. 		3HAuD323a78 a=$7$::z!}ObcdefcfOg?g+DG[grstguBvbc1GZ[\G]C]BvAw5xyDG D "";q>2		3 %d+[;K[K[-\\\ 32 Cws   
D0"D5D: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r3   rH   )rb   rm   newpermutations     r>   rd   z0PermuteDims._nest_permutation.<locals>.<genexpr>  s     &DQ~a'8&Dr   )r4   r   r   rZ  r   r   '_convert_outer_indices_to_inner_indicesr,   r   ru   r   r   r   r   
_array_addr   )	rP   r   r   cycles	newcyclesrc   new_contr_indicesr   ra  s	           @r>   r\  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   r{   ro   r   r   r<   r   s     r>   ro   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)rh   r   "_get_permutation_from_index_orders)rP   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   rh   symmetric_differenceindex)rP   r  r  rk  rc   r   s         r>   rj  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)rC   rD   rE   rp   rO   r   rr   r   r   r   r
  r	  rR  rZ  r^  r\  ro   r  rj  rH   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ef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   rO   
_positions_get_subranksr   r   r   )	rP   r   r   r   rc   r   r1   	positionsrR   s	            r>   rO   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 )Nr\   r   r   F)r   r   r}   r   r   r   _push_indices_downr   rk   r   r4   r
   intr-   r   r   r   _ArrayDiagonal_denest_ArrayAdd#_ArrayDiagonal_denest_ArrayDiagonalr   !_ArrayDiagonal_denest_PermuteDimsr   r   rr  r1   r   )r<   r   r   rc   trivial_diagsr/  trivial_posdiag_posdiagonal_indices_shortrank1rank2rank3inv_permutationcounter1indices_downr   ru  r1   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r3   r}   )rb   rm   r1   s     r>   rd   z*ArrayDiagonal._validate.<locals>.<genexpr>.  s     .q1E
?.s   z%index is larger than expression shaper\   z-diagonalizing indices of different dimensionsallow_trivial_diagsFz%need at least two axes to diagonalizezaxis index cannot be repeated)r   r~   rh   r}   r   r   )r   r   r   rc   rm   r1   s        @r>   rq  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   r\   c              3       K   | ]  }|  y wr3   rH   )rb   rm   s     r>   rd   z;ArrayDiagonal._remove_trivial_dimensions.<locals>.<genexpr>9  s     ^Aa^s   ru   )r1   r   rc   s      r>   _remove_trivial_dimensionsz(ArrayDiagonal._remove_trivial_dimensions7  s/    -=RqtPQAQ^^#RRRs   --c                      | j                   d   S rT   r  rW   s    r>   r   zArrayDiagonal.expr;  r  r@   c                      | j                   dd  S r[   r  rW   s    r>   r   zArrayDiagonal.diagonal_indices?      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   r\   c              3   F   K   | ]  }t        fd |D                yw)c              3   .   K   | ]  }|   |z     y wr3   rH   rb   rm   shiftss     r>   rd   z3ArrayDiagonal._flatten.<locals>.<genexpr>.<genexpr>U  s     ,FqVAY],Fr   Nr  rb   rc   r  s     r>   rd   z)ArrayDiagonal._flatten.<locals>.<genexpr>U  s     &g1u,FA,F'F&g   !)r   r  r   r}   rk   ru   r   r   )r   outer_diagonal_indicesinner_diagonal_indicesrc   rm   	all_inner
total_rank
inner_rank
outer_rankr.  pointerr   r  s               @r>   r   zArrayDiagonal._flattenC  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 r3   )rc  r   r   )rP   r   r   r   s       r>   ry  z,ArrayDiagonal._ArrayDiagonal_denest_ArrayAddY  s*    tyyYOCC2BCYZZY   +c                 (     | j                   |g| S r3   r   )rP   r   r   s      r>   rz  z1ArrayDiagonal._ArrayDiagonal_denest_ArrayDiagonal]  s    s||D4#344r@   r   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r3   rH   rb   rm   rc   s     r>   rd   zBArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<genexpr>d  s     >`!qAv>`   )
r   rk   r   r~   r   r  r}   r   r   r   )rP   r   r   rc   rm   back_diagonal_indicesnondiagback_nondiagr/  remapnew_permutation1shiftdiag_block_permr$  s      `          r>   r{  z/ArrayDiagonal._ArrayDiagonal_denest_PermuteDimsa  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 r3   )r}   rs  )r  r<   s    r>   r  z<ArrayDiagonal._push_indices_down_nonstatic.<locals>.<lambda>t  s%    ADOO8L4Ldooa0 RV r@   r%   r<   rv   	transforms   `  r>   _push_indices_down_nonstaticz*ArrayDiagonal._push_indices_down_nonstatics  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 r3   )r   rs  r4   rx  ru   )r  rc   r/  r<   s      r>   r  z;ArrayDiagonal._push_indices_up_nonstatic.<locals>.transformy  sF    !$//2 1q#&16z!U7KPQUVPVHr@   r  r  s   `  r>   _push_indices_up_nonstaticz(ArrayDiagonal._push_indices_up_nonstaticw  s    	
 4IwGGr@   c                 b    | j                  t        |      |      \  }fd}t        ||      S )Nc                 .    | t              k  r|    S d S r3   r  )r  ru  s    r>   r  z2ArrayDiagonal._push_indices_down.<locals>.<lambda>  s    a#i..@il d r@   rr  rk   r%   rP   r   rv   rankr1   r  ru  s         @r>   rw  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 r3   )r   r4   rx  ru   r	   )r  rc   r/  ru  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r3   rH   r  s     r>   rd   z?ArrayDiagonal._get_positions_shape.<locals>.<genexpr>.<genexpr>  s     HjTUaHjr  Nr~   )rb   shprc   r   s     @r>   rd   z5ArrayDiagonal._get_positions_shape.<locals>.<genexpr>  s'     k61cSHjYiHjEjq#hks   *	*)rH   rH   c              3   2   K   | ]  }||d       f  yw)r   NrH   )rb   rc   r1   s     r>   rd   z5ArrayDiagonal._get_positions_shape.<locals>.<genexpr>  s     A1q%!+&As   )ru   r   r   )
rP   r1   r   data1pos1shp1data2pos2shp2ru  s
    ``       r>   rr  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   r{   ro   r   r   rh  s     r>   ro   zArrayDiagonal.as_explicit  s9    yy4'##%Dd;T%:%:;;r@   N)rC   rD   rE   rp   rO   r   staticmethodrq  r  rr   r   r   r   r   ry  rz  r   r{  r  r  rw  r*  rr  ro   rH   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)r4   r   r   r   rO   rt  r   )rP   functionelementr  rR   s        r>   rO   z!ArrayElementwiseApplyFunc.__new__  sJ    (F+c
Aa!-H#++C7C%g.
r@   c                      | j                   d   S rT   r  rW   s    r>   r  z"ArrayElementwiseApplyFunc.function  r  r@   c                      | j                   d   S r[   r  rW   s    r>   r   zArrayElementwiseApplyFunc.expr  r  r@   c                 .    | j                   j                  S r3   r   r1   rW   s    r>   r1   zArrayElementwiseApplyFunc.shape  s    yyr@   c                     t        d      }| j                  |      }|j                  |      }t        |t              rt        |      }|S t        ||      }|S r  )r   r  diffr4   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   r{   ro   	applyfuncr  rh  s     r>   ro   z%ArrayElementwiseApplyFunc.as_explicit  s6    yy4'##%D~~dmm,,r@   N)
rC   rD   rE   rO   rr   r  r   r1   r  ro   rH   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r3   rH   )rb   cindrc   s     r>   rd   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r3   rH   r  s     r>   rd   z5ArrayContraction.__new__.<locals>.<genexpr>.<genexpr>  s     GlSTQGlr  Nr  )rb   r  rc   r   s     @r>   rd   z+ArrayContraction.__new__.<locals>.<genexpr>  s#     m&!SCGlXkGlDl#ms   (()r&   r.   r   r   rO   rt  r   r'   _mappingrk   r   rg   _free_indices_to_positionr   rq  ru   r   r   r   )	rP   r   r   r   r   rR   rc   free_indices_to_positionr1   s	     `   `  r>   rO   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   r\   r   F)r   r   r}   r4   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   rc   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      Nr\   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   r\   z+contracting indices of different dimensions)r   r}   rh   )r   r   r1   rc   rm   s        r>   rq  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 r3   )r  r*   r%   rP   r   rv   rc   rm   flattened_contraction_indicesr  s          r>   rw  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 r3   )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)r\   NrH   )rb   r   cumranksrm   s     r>   rd   zAArrayContraction._lower_contraction_to_addends.<locals>.<genexpr>>  s*     SAx{a7(1Q3-77Ss   #&r\   c              3   .   K   | ]  }||   z
    y wr3   rH   r  s     r>   rd   zAArrayContraction._lower_contraction_to_addends.<locals>.<genexpr>H  s     7Q!F1I7Qr   )r4   r   r   r   r   r   r   r   r   rk   r}   rg   r   updater   r	   r   r   r   r   )rP   r   r   r   contraction_indices_remainingrc   contraction_indices_args	backshiftcontraction_groupr   r  r   contrr]  r   rm   r  s                 @@@r>   r  z.ArrayContraction._lower_contraction_to_addends/  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   r\   T)r\   r\   c              3   8   K   | ]  \  }}|k7  s|v   y wr3   rH   )rb   lilindlother_arg_abss      r>   rd   z?ArrayContraction.split_multiple_contractions.<locals>.<genexpr>  s#     eur1Z\`dZd*es   	Nr   )_EditArrayContractionr   r   r}   get_mapping_for_indexr   r1   args_with_indr  get_absolute_ranger~   r   r   rv   get_new_contraction_indexrn  insert_after_ArgEr   to_array_contraction)r<   editorr   onearray_insertlinksru  current_dimensionnot_vectorsvectorsarg_indrel_indr   matabs_arg_startabs_arg_endother_arg_posrM  vectors_to_loopfirst_not_vector	new_indexlast_vecr  r  s                        @@r>   split_multiple_contractionsz,ArrayContraction.split_multiple_contractionsN  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 r3   )r4   r   r   rw  r   r   r   r   r   r  r   r*  r   r   )
r<   contraction_downr7  r   rc   r  rm   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   r\   rH   )free_indicesr   r  rc   rm   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   r\   )r   r  r   r}   rk   )r   inner_contraction_indicesrc   rm   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r3   rH   r  s     r>   rd   zUArrayContraction._convert_outer_indices_to_inner_indices.<locals>.<genexpr>.<genexpr>  s     /I!q	A/Ir   Nr  r  s     r>   rd   zKArrayContraction._convert_outer_indices_to_inner_indices.<locals>.<genexpr>  s     )ma%/Iq/I*I)mr  )r   r3  ru   )r   outer_contraction_indicesr  s     @r>   rb  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 r3   )r   r   rb  r   r   )r   r7  r2  r   s       r>   r   zArrayContraction._flatten  sG    $($<$<!$4$\$\]a$~d}$~!7:SS!$))B.ABBr@   c                 (     | j                   |g| S r3   r  )rP   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 r3   )r   r1   r   )rP   r   r   rc   rm   r+  r/  r1   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 r3   )rc  r   r   )rP   r   r   rc   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r3   rH   )rb   rm   r   s     r>   rd   zHArrayContraction._ArrayContraction_denest_PermuteDims.<locals>.<genexpr>  s     (CAQ(Cr   c              3   &   K   | ]  }|v  
 y wr3   rH   r  s     r>   rd   zHArrayContraction._ArrayContraction_denest_PermuteDims.<locals>.<genexpr>  s     0YAa0Yr  )	r   r  ru   r~   r*  r   r   r   r,   )rP   r   r   r  rc   r7  	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r3   rH   )rb   rc   diag_indgrps     r>   rd   zJArrayContraction._ArrayContraction_denest_ArrayDiagonal.<locals>.<genexpr>/  s     >AqK'>r  )r   r   rw  r   r   r4   ru   r	   r   r~   r   r   r  r   r   r*  r   r   )rP   r   r   r   down_contraction_indicesrc   rm   r   r7  contr_indgrpr/  new_diagonal_indices_downnew_diagonal_indicesrB  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   r\   c              3   &   K   | ]  }|v  
 y wr3   rH   )rb   rm   r+  s     r>   rd   z?ArrayContraction._sort_fully_contracted_args.<locals>.<genexpr>B  s     c!%= =cr  c                 F    |    rdt        j                  |          fS dS )Nr   )r\   )r   r   )r  r   fully_contracteds    r>   r  z>ArrayContraction._sort_fully_contracted_args.<locals>.<lambda>C  s1    euvwexqBRSWS\S\]^S_B`>a   C r@   r  c              3   (   K   | ]	  }|     y wr3   rH   )rb   rm   index_permutation_array_forms     r>   rd   z?ArrayContraction._sort_fully_contracted_args.<locals>.<genexpr>G  s     (TQ)Ea)H(Tr)  )r1   r   r   r   rk   r}   r   r   rg   r  r-   ru   r&   r   )rP   r   r   r  rc   r1  rm   r   new_posr   new_index_blocks_flatr7  r+  rJ  rL  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<   mappingrc   rm   s       r>   _get_contraction_tuplesz(ArrayContraction._get_contraction_tuplesK  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r3   rH   )rb   rm   r   r   s      r>   rd   zNArrayContraction._contraction_tuples_to_contraction_indices.<locals>.<genexpr>o  s      :1&q)!+:r   )r   r   r   ru   )r   contraction_tuplesr   rc   r   s       @r>   *_contraction_tuples_to_contraction_indicesz;ArrayContraction._contraction_tuples_to_contraction_indicesj  sD     3j&7!88DVWq:::WWWs   Ac                      | j                   d d  S r3   )_free_indicesrW   s    r>   r.  zArrayContraction.free_indicesq  s    !!!$$r@   c                 ,    t        | j                        S r3   )dictr  rW   s    r>   r  z)ArrayContraction.free_indices_to_positionu  s    D2233r@   c                      | j                   d   S rT   r  rW   s    r>   r   zArrayContraction.expry  r  r@   c                      | j                   dd  S r[   r  rW   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   r\   )r   r4   r   r   r   r   rk   )r<   r   r   rP  r.  rc   r  rm   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 r[   r   r  s    r>   r  z4ArrayContraction.sort_args_by_name.<locals>.<lambda>  s    <LQqT<R r@   r  )r   r4   r   r   r  r   r   rn  rQ  r   rU  r   )r<   r   r   sorted_data
pos_sortedr"  rc   r   reordering_maprT  rm   r   c_tprf  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   r{   ro   r   r   rh  s     r>   ro   zArrayContraction.as_explicit  s9    yy4'##%D A(@(@AAr@   N)r   r   )%rC   rD   rE   rp   rO   r   r  r  r  rq  r   rw  r*  r  r'  r+  r0  r3  rb  r   r  r  r  r  r  r  rQ  rU  rr   r.  r  r   r   r]  rd  r)   ro   rH   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.   r4   r	   r   r   r   r1   rh   r   rO   ru   r   _expr)rP   r   r1   rR   s       r>   rO   zReshape.__new__  sx    ~%'5MECLL,cll5.ABeK-..ll3e,5\
	
r@   c                     | j                   S r3   r   rW   s    r>   r1   zReshape.shape  r   r@   c                     | j                   S r3   )rk  rW   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   r4   r   r!   rl   r1   ri  )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 )Nro   r   )Array)
r   r{   ro   r4   r   sympyrp  r   rl   r1   )r<   eerp  s      r>   ro   zReshape.as_explicit  s[    YY2}%!Bb*%#rBJ'Krzz4::&&r@   N)
rC   rD   rE   rp   rO   rr   r1   r   r   ro   rH   r@   r>   ri  ri    s>    ,	    )	'r@   ri  c                   R    e Zd ZU dZeee      ed<   ddeeee         f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.
    rv   Nc                 ~    || _         |(t        t        |            D cg c]  }d  c}| _        y || _        y c c}w r3   )r  rk   r   rv   )r<   r  rv   rc   s       r>   __init__z_ArgE.__init__7  s7    ?*/0A*BCQDCDL"DL Ds   	:c                 <    d| j                   d| j                  dS )Nz_ArgE(z, ))r  rv   rW   s    r>   __str__z_ArgE.__str__>  s    "&,,==r@   r3   )rC   rD   rE   rp   r   r   rx  rG   ru  rx  __repr__rH   r@   r>   r  r  %  s>     (3-  #$x}2E)F #> Hr@   r  c                   0    e Zd ZdZdedef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.
    r   relc                      || _         || _        y r3   r   r|  )r<   r   r|  s      r>   ru  z_IndPos.__init__K  s    r@   c                 8    d| j                   | j                  fz  S )Nz_IndPos(%i, %i)r~  rW   s    r>   rx  z_IndPos.__str__O  s     DHHdhh#777r@   c              #   P   K   | j                   | j                  gE d {    y 7 wr3   r~  rW   s    r>   __iter__z_IndPos.__iter__T  s     HHdhh'''s   &$&N)	rC   rD   rE   rp   rx  ru  rx  ry  r  rH   r@   r>   r{  r{  D  s+    C c 8 H(r@   r{  c                   N   e Zd ZdZdej
                  eeef   fdZ	de
de
fdZd Zd Zd	 Zd
 Zdeee      fdZdee   fdZdeee      fdZdedefdZdedee
   fdZed        Zd Zde
de
fdZde
dej8                  eef   fdZde
dej8                  eef   f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.
    
base_arrayc                    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 )NrH   r   )r4   r   r'   r   r   r   r   rw  r   r   r   r   r   r  r   rv   r  r}   number_of_contraction_indices_track_permutation)r<   r  rP  r   r   diagonalizedr   r   r  rc   contraction_tuplerm   arg_posrel_posr/  s                  r>   ru  z_EditArrayContraction.__init__g  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*=A,Z-@-@A l+ 	FDAq F#*1: ?AAv""7+33G<F	F &Bs   Ir   new_argc                 x    | j                   j                  |      }| j                   j                  |dz   |       y r[   )r  rn  insert)r<   r   r  poss       r>   r  z"_EditArrayContraction.insert_after  s2      &&s+!!#'73r@   c                 J    | xj                   dz  c_         | j                   dz
  S r[   )r  rW   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  rv   r   r  r}   r  r   )r<   updatesarg_with_indrc   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}   rv   r   remover   r   r  r  3sympy.tensor.array.expressions.from_array_to_matrixr  )r<   scalarsr  rc   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 r:  )r   r   r   r  r  rv   r   r   r   r}   r-   valuesru   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counter2rc   r   r   rM  diag_indices_filteredr   r   r   r   expr2rm   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"
rK   c                     t        | j                        D cg c]  }g  }}d}| j                  D ].  }|j                  D ]  }|||   j	                  |       |dz  } 0 |S c c}w r-  )rk   r  r  rv   r   )r<   rc   r   current_positionr  rm   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  rh   r   r  rv   r   r{  )r<   r/  ru  rc   r  rm   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 r3   )rk   r  r   r  rv   r   r{  )r<   rc   r   r  rm   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 rn  c                 T    d}| j                   D ]  }||j                  v s|dz  } |S )zJ
        Count the number of arguments that have the given index.
        r   r\   r  rv   )r<   rn  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<   rn  rc   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 rT   )r   r  r  rv   r}   )r<   rn   r   rc   s       r>   number_of_diagonal_indicesz0_EditArrayContraction.number_of_diagonal_indices0  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   r\   c              3   :   K   | ]  }|rt        |      nd   yw)r   N)rT  ra   s     r>   rd   z@_EditArrayContraction.track_permutation_start.<locals>.<genexpr>G  s     ?ac!fr)?r   )r  rv   r   rT  r  )	r<   r   	perm_diagr.  r  r  permrc   max_inds	            r>   track_permutation_startz-_EditArrayContraction.track_permutation_start7  s    	 .. 
	%LD!)) =1u!((2 AG$1 t$
	% DO#?;??TV*34QWq[4	4"-"; 5s   B&destinationfrom_elementc                     | j                   j                  |      }| j                   j                  |      }| j                  |   j                  | j                  |          | j                  j	                  |       y r3   )r  rn  r  r   r   )r<   r  r  index_destinationindex_elements        r>   track_permutation_mergez-_EditArrayContraction.track_permutation_mergeK  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}   rv   r|   )r<   r   r.  r  rc   number_free_indicess         r>   get_absolute_free_rangez-_EditArrayContraction.get_absolute_free_rangeQ  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)rC   rD   rE   rp   rq   Unionr   r   r   ru  r  r  r  r  r  r  r   rx  r  r{  r  r  r  r  rr   r  r  r  r	   r  r  rH   r@   r>   r  r  X  s"   7F6<<0@-Qc0c#d 7Fr4 4 46XgAF#d3i #DM #T']8K #3 3  e   <(35 3 3/5 /V\\#s(5K //e /S#X0F /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   r1   r   )r4   r   r$   r   r}   r1   r!   r  r"   r#   r{   r  s     r>   r   r   l  s    $]34$-.4::$	"yy{$ yy$$

=u:tW4::r@   c                 X    t        | t              r| j                         S t        |       S r3   )r4   r   r   r   r   s    r>   r   r     s#    $-.||~D>r@   c                 R    t        | t              r| j                  S t        |       gS r3   )r4   r   r   r   r  s    r>   rt  rt    s$    $-.}}r@   c                 4    t        | d      r| j                  S y)Nr1   rH   )r{   r1   r  s    r>   r   r     s    tWzzr@   c                 F    t        | t              r| j                         S | S r3   )r4   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>   rc  rc    s    T7777r@   c                     t        | |      S r3   )r8   )r   rv   s     r>   rB   rB     s    g&&r@   )bcollections.abcr5   r   r   r   	functoolsr   ri   r   rq   r   r   r	   rF   sympy.core.numbersr
   sympy.core.relationalr   (sympy.functions.special.tensor_functionsr   sympy.core.basicr   sympy.core.containers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.   r0   rJ   r8   r   r   r   r   r   r   r   r  r   ri  r  r{  r  r   r   rt  r   r^  r   r   r   r   rc  rB   rH   r@   r>   <module>r     s     ,     2 2  & * C " '   2  " / - 0 B 9 9 f f G 3 7 <1 1 , 7 '
7 
7B* B82[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@   