o
    GZh,                    @  s  d dl mZ d dlZd dlZd dlmZmZ d dlmZ d dl	Z	d dl	m
Z
 d dlZd dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZmZ d dlmZ d dlmZ d dlm Z  d dl!m"Z"m#Z# d dl$m%Z% d dl&m'Z' d dl(m)Z) d dl*m+Z+ d dl,m-Z-m.Z.m/Z/m0Z0 d dl1m2Z2 d dl3m4Z4 d dl5m6Z6m7Z7 d dl(m8Z8 d dl9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z? d dl@mAZA d dlBmCZC d dlDmEZE G dd deZFG d d! d!eFZGG d"d# d#eZHG d$d% d%eFZIG d&d' d'eFZJG d(d) d)eZKG d*d+ d+eKZLG d,d- d-eKZMG d.d/ d/eKZNG d0d1 d1eKZOG d2d3 d3eKZPG d4d5 d5eKZQG d6d7 d7eKZRG d8d9 d9ZSG d:d; d;ZTG d<d= d=ZUd>d? ZVd@dA ZWdBdC ZXdDdE ZYdFdG ZZdHdI Z[dJdK Z\dLdM Z]dNdO Z^dPdQ Z_dRdS Z`dS )T    )annotationsN)defaultdictCounter)reduce)
accumulate)Integer)EqualityKroneckerDelta)Basic)Tuple)Expr)FunctionLambda)Mul)Sdefault_sort_key)DummySymbol)
MatrixBase)diagonalize_vector)
MatrixExpr)
ZeroMatrix)permutedimstensorcontractiontensordiagonaltensorproduct)ImmutableDenseNDimArray)	NDimArray)IndexedIndexedBase)MatrixElement)$_apply_recursively_over_nested_lists_sort_contraction_indices_get_mapping_from_subranks*_build_push_indices_up_func_transformation_get_contraction_links,_build_push_indices_down_func_transformationPermutation)
_af_invert_sympifyc                   @  s&   e Zd ZU ded< dd Zdd ZdS )
_ArrayExprztuple[Expr, ...]shapec                 C  s*   t |tjjs
|f}t| | | |S N)
isinstancecollectionsabcIterableArrayElement_check_shape_getselfitem r;   _/var/www/auris/lib/python3.10/site-packages/sympy/tensor/array/expressions/array_expressions.py__getitem__*   s   
z_ArrayExpr.__getitem__c                 C  
   t | |S r0   )_get_array_element_or_slicer8   r;   r;   r<   r7   0      
z_ArrayExpr._getN)__name__
__module____qualname____annotations__r=   r7   r;   r;   r;   r<   r.   '   s   
 r.   c                   @  s>   e Zd ZdZdZdddZed	d
 Zedd Zdd Z	dS )ArraySymbolz1
    Symbol representing an array expression
    Fr/   typing.Iterablereturn'ArraySymbol'c                 C  s2   t |tr	t|}ttt| }t| ||}|S r0   )r1   strr   r   mapr-   r   __new__)clssymbolr/   objr;   r;   r<   rK   ;   s
   
zArraySymbol.__new__c                 C  
   | j d S Nr   _argsr9   r;   r;   r<   nameC      
zArraySymbol.namec                 C  rO   N   rQ   rS   r;   r;   r<   r/   G   rU   zArraySymbol.shapec                   sP   t dd  jD std fddtjdd  jD  D }t|j j S )Nc                 s      | ]}|j V  qd S r0   Z
is_Integer.0ir;   r;   r<   	<genexpr>L       z*ArraySymbol.as_explicit.<locals>.<genexpr>z1cannot express explicit array with symbolic shapec                      g | ]} | qS r;   r;   rZ   rS   r;   r<   
<listcomp>N       z+ArraySymbol.as_explicit.<locals>.<listcomp>c                 S     g | ]}t |qS r;   ranger[   jr;   r;   r<   r`   N   ra   )allr/   
ValueError	itertoolsproductr   reshape)r9   datar;   rS   r<   as_explicitK   s   $zArraySymbol.as_explicitN)r/   rF   rG   rH   )
rA   rB   rC   __doc__Z	_iterablerK   propertyrT   r/   rm   r;   r;   r;   r<   rE   4   s    


rE   c                   @  sP   e Zd ZdZdZdZdZdd Zedd Z	e
dd Ze
d	d
 Zdd ZdS )r5   z!
    An element of an array.
    Tc                 C  sX   t |tr	t|}t|}t |tjjs|f}tt|}| || t	
| ||}|S r0   )r1   rI   r   r-   r2   r3   r4   tupler6   r   rK   )rL   rT   indicesrN   r;   r;   r<   rK   [   s   
zArrayElement.__new__c                 C  sp   t |}t|dr)td}t|t|jkr|tdd t||jD r)tdtdd |D r6tdd S )Nr/   z3number of indices does not match shape of the arrayc                 s  s     | ]\}}||kd kV  qdS )TNr;   )r[   r\   sr;   r;   r<   r]   m       z,ArrayElement._check_shape.<locals>.<genexpr>zshape is out of boundsc                 s  s    | ]	}|d k dkV  qdS )r   TNr;   rZ   r;   r;   r<   r]   o       zshape contains negative values)rp   hasattr
IndexErrorlenr/   anyziprh   )rL   rT   rq   Zindex_errorr;   r;   r<   r6   f   s   
zArrayElement._check_shapec                 C  rO   rP   rQ   rS   r;   r;   r<   rT   r   rU   zArrayElement.namec                 C  rO   rV   rQ   rS   r;   r;   r<   rq   v   rU   zArrayElement.indicesc                 C  sN   t |tstjS || krtjS |j| jkrtjS tdd t| j	|j	D S )Nc                 s  s    | ]
\}}t ||V  qd S r0   r	   r[   r\   rf   r;   r;   r<   r]          z0ArrayElement._eval_derivative.<locals>.<genexpr>)
r1   r5   r   ZeroOnerT   r   fromiterry   rq   )r9   rr   r;   r;   r<   _eval_derivativez   s   
zArrayElement._eval_derivativeN)rA   rB   rC   rn   Z	_diff_wrtZ	is_symbolZis_commutativerK   classmethodr6   ro   rT   rq   r   r;   r;   r;   r<   r5   R   s    


r5   c                   @  4   e Zd ZdZdd Zedd Zdd Zdd	 Zd
S )	ZeroArrayzM
    Symbolic array of zeros. Equivalent to ``ZeroMatrix`` for matrices.
    c                 G  2   t |dkr	tjS tt|}tj| g|R  }|S rP   )rw   r   r|   rJ   r-   r   rK   rL   r/   rN   r;   r;   r<   rK      
   
zZeroArray.__new__c                 C     | j S r0   rQ   rS   r;   r;   r<   r/         zZeroArray.shapec                 C  s(   t dd | jD stdtj| j S )Nc                 s  rX   r0   rY   rZ   r;   r;   r<   r]      r^   z(ZeroArray.as_explicit.<locals>.<genexpr>/Cannot return explicit form for symbolic shape.)rg   r/   rh   r   ZzerosrS   r;   r;   r<   rm      s   zZeroArray.as_explicitc                 C     t jS r0   )r   r|   r8   r;   r;   r<   r7         zZeroArray._getN	rA   rB   rC   rn   rK   ro   r/   rm   r7   r;   r;   r;   r<   r          
r   c                   @  r   )OneArrayz!
    Symbolic array of ones.
    c                 G  r   rP   )rw   r   r}   rJ   r-   r   rK   r   r;   r;   r<   rK      r   zOneArray.__new__c                 C  r   r0   rQ   rS   r;   r;   r<   r/      r   zOneArray.shapec                 C  sD   t dd | jD stdtdd tttj| jD j| j S )Nc                 s  rX   r0   rY   rZ   r;   r;   r<   r]      r^   z'OneArray.as_explicit.<locals>.<genexpr>r   c                 S  s   g | ]}t jqS r;   r   r}   rZ   r;   r;   r<   r`          z(OneArray.as_explicit.<locals>.<listcomp>)	rg   r/   rh   r   rd   r   operatormulrk   rS   r;   r;   r<   rm      s   (zOneArray.as_explicitc                 C  r   r0   r   r8   r;   r;   r<   r7      r   zOneArray._getNr   r;   r;   r;   r<   r      r   r   c                   @  s4   e Zd Zedd Zdd Zedd Zdd Zd	S )
_CodegenArrayAbstractc                 C  s   | 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)	_subranksrS   r;   r;   r<   subranks   s   z_CodegenArrayAbstract.subranksc                 C  
   t | jS )z*
        The sum of ``subranks``.
        )sumr   rS   r;   r;   r<   subrank   s   
z_CodegenArrayAbstract.subrankc                 C  r   r0   _shaperS   r;   r;   r<   r/      r   z_CodegenArrayAbstract.shapec                   s6     dd}|r| j fdd| jD   S |  S )NdeepTc                   s   g | ]
}|j d i  qS )r;   )doitr[   arghintsr;   r<   r`          z._CodegenArrayAbstract.doit.<locals>.<listcomp>)getfuncargs_canonicalize)r9   r   r   r;   r   r<   r      s   z_CodegenArrayAbstract.doitN)rA   rB   rC   ro   r   r   r/   r   r;   r;   r;   r<   r      s    

r   c                   @  4   e Zd ZdZdd Zdd Zedd Zdd	 Zd
S )ArrayTensorProductzF
    Class to represent the tensor product of array-like objects.
    c                 O  s   dd |D }| dd}dd |D }tj| g|R  }||_dd |D }tdd |D r4d |_n
td	d |D |_|rD| S |S )
Nc                 S  rb   r;   r,   r   r;   r;   r<   r`      ra   z.ArrayTensorProduct.__new__.<locals>.<listcomp>canonicalizeFc                 S  rb   r;   get_rankr   r;   r;   r<   r`      ra   c                 S  rb   r;   	get_shaperZ   r;   r;   r<   r`      ra   c                 s      | ]}|d u V  qd S r0   r;   rZ   r;   r;   r<   r]          z-ArrayTensorProduct.__new__.<locals>.<genexpr>c                 s  s    | ]
}|D ]}|V  qqd S r0   r;   rz   r;   r;   r<   r]      r{   )popr   rK   r   rx   r   rp   r   )rL   r   kwargsr   ranksrN   shapesr;   r;   r<   rK      s   zArrayTensorProduct.__new__c                   s  | j }| |}dd |D g }t|D ]\}t|tsq|fdd|jjD  |j|< q|rGt	t
| ttd t| S t|dkrQ|d S tdd |D rjttjdd |D d	}t| S d
d t|D }|rdd |D ttdg d d  t
dd |D  } fdd| D }t|g|R  S dd t|D }|rSg }	g }
dd |D ttdg d d  t|D ]K\}t|trt|t|j }t|j}|	 fddt|D  |
 fddt||| D  q|	 fddtt|D  q|	|
 t
dd |D  }dd |D }ttdg| d d fdd| D }t	t|g|R  t|	S | j|ddiS )Nc                 S  rb   r;   r   r   r;   r;   r<   r`     ra   z4ArrayTensorProduct._canonicalize.<locals>.<listcomp>c                   s    g | ]} fd d|D qS )c                   s    g | ]}|t d    qS r0   )r   r[   kr\   r   r;   r<   r`          z?ArrayTensorProduct._canonicalize.<locals>.<listcomp>.<listcomp>r;   re   r   r;   r<   r`     r   rW   r   c                 s  s    | ]
}t |ttfV  qd S r0   r1   r   r   r   r;   r;   r<   r]     r{   z3ArrayTensorProduct._canonicalize.<locals>.<genexpr>c                 S  rb   r;   r   rZ   r;   r;   r<   r`     ra   r;   c                 S      i | ]\}}t |tr||qS r;   )r1   ArrayContractionr[   r\   r   r;   r;   r<   
<dictcomp>  r   z4ArrayTensorProduct._canonicalize.<locals>.<dictcomp>c                 S  &   g | ]}t |trt|nt|qS r;   )r1   r   _get_subrankr   r   r;   r;   r<   r`        & c                 S      g | ]}t |tr|jn|qS r;   )r1   r   exprr   r;   r;   r<   r`     r   c                   4   g | ]\ }|j D ]}t fd d|D q	qS )c                 3      | ]	}  | V  qd S r0   r;   r   cumulative_ranksr\   r;   r<   r]     rt   >ArrayTensorProduct._canonicalize.<locals>.<listcomp>.<genexpr>)contraction_indicesrp   r[   r   rf   r   r\   r<   r`        4 c                 S  r   r;   )r1   ArrayDiagonalr   r;   r;   r<   r   "  r   c                 S  rb   r;   r   r   r;   r;   r<   r`   &  ra   c                      g | ]}  | qS r;   r;   re   r   r;   r<   r`   ,      c                   r   r;   r;   re   r   r;   r<   r`   -  r   c                   r   r;   r;   re   r   r;   r<   r`   /  r   c                 S  r   r;   )r1   r   r   r   r;   r;   r<   r`   1  r   c                 S  r   r;   )r1   r   r   r   r   r;   r;   r<   r`   2  r   c                   r   )c                 3  r   r0   r;   r   )cumulative_ranks2r\   r;   r<   r]   4  rt   r   )diagonal_indicesrp   r   )r   r   r<   r`   4  r   r   F)r   _flatten	enumerater1   PermuteDimsextendpermutationcyclic_formr   _permute_dims_array_tensor_productr*   r   rw   rx   r   r   addr   listr   items_array_contractionr   r   r   rd   _array_diagonalr+   r   )r9   r   Zpermutation_cyclesr   r   Zcontractionstpr   Z	diagonalsinverse_permutationZ	last_permi1i2Zranks2r   r;   )r   r   r\   r   r<   r      sV   

"
&$
z ArrayTensorProduct._canonicalizec                   s    fdd|D }|S )Nc                   s,   g | ]}t | r|jn|gD ]}|qqS r;   )r1   r   )r[   r   r\   rL   r;   r<   r`   ;  s   , z/ArrayTensorProduct._flatten.<locals>.<listcomp>r;   )rL   r   r;   r   r<   r   9  s   zArrayTensorProduct._flattenc                 C  s   t dd | jD  S )Nc                 S  "   g | ]}t |d r| n|qS rm   ru   rm   r   r;   r;   r<   r`   ?     " z2ArrayTensorProduct.as_explicit.<locals>.<listcomp>)r   r   rS   r;   r;   r<   rm   >  s   zArrayTensorProduct.as_explicitN)	rA   rB   rC   rn   rK   r   r   r   rm   r;   r;   r;   r<   r      s    9
r   c                   @  r   )ArrayAddz0
    Class for elementwise array additions.
    c                 O  s   dd |D }dd |D }t t|}t|dkrtddd |D }tdd |D dkr4td	|d
d}tj| g|R  }||_tdd |D rSd |_	n|d |_	|r^|
 S |S )Nc                 S  rb   r;   r,   r   r;   r;   r<   r`   H  ra   z$ArrayAdd.__new__.<locals>.<listcomp>c                 S  rb   r;   r   r   r;   r;   r<   r`   I  ra   rW   z!summing arrays of different ranksc                 S     g | ]}|j qS r;   r/   r   r;   r;   r<   r`   M  r   c                 S  s   h | ]}|d ur|qS r0   r;   rZ   r;   r;   r<   	<setcomp>N  r   z#ArrayAdd.__new__.<locals>.<setcomp>zmismatching shapes in additionr   Fc                 s  r   r0   r;   rZ   r;   r;   r<   r]   U  r   z#ArrayAdd.__new__.<locals>.<genexpr>r   )r   setrw   rh   r   r   rK   r   rx   r   r   )rL   r   r   r   r   r   rN   r;   r;   r<   rK   G  s"   
zArrayAdd.__new__c                 C  s   | j }| |}dd |D }dd |D }t|dkr/tdd |D r)tdt|d  S t|dkr9|d S | j|d	d
iS )Nc                 S  rb   r;   r   r   r;   r;   r<   r`   c  ra   z*ArrayAdd._canonicalize.<locals>.<listcomp>c                 S  s   g | ]}t |ttfs|qS r;   r   r   r;   r;   r<   r`   d      r   c                 s  s    | ]	}|d u r|V  qd S r0   r;   rZ   r;   r;   r<   r]   f  rt   z)ArrayAdd._canonicalize.<locals>.<genexpr>zIcannot handle addition of ZeroMatrix/ZeroArray and undefined shape objectrW   r   F)r   _flatten_argsrw   rx   NotImplementedErrorr   r   )r9   r   r   r;   r;   r<   r   ]  s   
zArrayAdd._canonicalizec                 C  s4   g }|D ]}t |tr||j q|| q|S r0   )r1   r   r   r   append)rL   r   new_argsr   r;   r;   r<   r   m  s   
zArrayAdd._flatten_argsc                 C  s   t tjdd | jD S )Nc                 S  r   r   r   r   r;   r;   r<   r`   z  r   z(ArrayAdd.as_explicit.<locals>.<listcomp>)r   r   r   r   rS   r;   r;   r<   rm   w  s   zArrayAdd.as_explicitN)	rA   rB   rC   rn   rK   r   r   r   rm   r;   r;   r;   r<   r   B  s    
	r   c                   @  s   e Zd ZdZdddZdd Zedd Zed	d
 Ze	dd Z
e	dd Ze	dd Ze	dd Zdd Ze	dd Zdd Ze	dd Ze	dd ZdS )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                   s   ddl m} t|}t|}|  ||| |   j}||kr%td|dd}	t	| | }
t|g|
_
t|d u rDd |
_nt fddttD |
_|	r[|
 S |
S )Nr   r)   z8Permutation size must be the length of the shape of exprr   Fc                 3  s    | ]	} | V  qd S r0   r;   rZ   r   r/   r;   r<   r]     rt   z&PermuteDims.__new__.<locals>.<genexpr>)sympy.combinatoricsr*   r-   r   _get_permutation_from_argumentssizerh   r   r   rK   r   r   r   rp   rd   rw   r   )rL   r   r   index_order_oldindex_order_newr   r*   Z	expr_rankZpermutation_sizer   rN   r;   r   r<   rK     s$   "zPermuteDims.__new__c                   s   | j  | j}t tr j } j}|| }| t tr$|  |\ }t tr1|  |\ }t tt	frDt fdd|j
D  S |j
}|t|krO S | j |ddS )Nc                      g | ]} j | qS r;   r   rZ   r   r;   r<   r`         z-PermuteDims._canonicalize.<locals>.<listcomp>F)r   )r   r   r1   r   r   '_PermuteDims_denestarg_ArrayContractionr   )_PermuteDims_denestarg_ArrayTensorProductr   r   
array_formsortedr   )r9   r   ZsubexprZsubpermplistr;   r   r<   r     s"   


zPermuteDims._canonicalizec                 C  rO   rP   r   rS   r;   r;   r<   r     rU   zPermuteDims.exprc                 C  rO   rV   r   rS   r;   r;   r<   r     rU   zPermuteDims.permutationc                   s   t |jt|j ttdg|j fddtt D dd tD }|j	dd d dd |D } fd	d|D }fd
d|D }t
t dd |D }t| |fS )Nr   c                   s$   g | ]} |  |d    qS rW   r;   rZ   )cumulperm_image_formr;   r<   r`        $ zIPermuteDims._PermuteDims_denestarg_ArrayTensorProduct.<locals>.<listcomp>c                 S  s   g | ]
\}}|t |fqS r;   )r   )r[   r\   compr;   r;   r<   r`     r   c                 S     | d S rV   r;   xr;   r;   r<   <lambda>      zGPermuteDims._PermuteDims_denestarg_ArrayTensorProduct.<locals>.<lambda>keyc                 S     g | ]}|d  qS r   r;   rZ   r;   r;   r<   r`   
  ra   c                   r_   r;   r;   rZ   r   r;   r<   r`     ra   c                   r_   r;   r;   rZ   )perm_image_form_in_componentsr;   r<   r`     ra   c                 S     g | ]	}|D ]}|qqS r;   r;   rz   r;   r;   r<   r`         )r+   r   r   r   r   r   rd   rw   r   sortr*   r   )rL   r   r   ZpsZperm_args_image_formargs_sortedZperm_image_form_sorted_argsnew_permutationr;   )r   r   r  r  r<   r     s   

z5PermuteDims._PermuteDims_denestarg_ArrayTensorProductc                   s  t |ts	||fS t |jts||fS |jj dd |jjD }|j}dd |D }ttdg| g t|j	}d}t
t|D ]'}g }	t
| |d  D ]}
|
|v rXqQ|	||  |d7 }qQ|	 qBfddt|jD ||j}|d fdd|D }tt|}|jd	d
 d dd |D }fdd|D }tdd |D  fdd|D }fdd|D }tt| g|R  }ttdd fdd|D D }||fS )Nc                 S  rb   r;   r   r   r;   r;   r<   r`     ra   zGPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<listcomp>c                 S  r  r;   r;   rz   r;   r;   r<   r`     r  r   rW   c                   s*   g | ]\}}t t |  |d   qS r   r   rd   r[   r\   er   r;   r<   r`   .     * r   c                      g | ]} fd d|D qS )c                   s   g | ]
}|d ur |qS r0   r;   re   r   r;   r<   r`   1  r   zRPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<listcomp>.<listcomp>r;   rZ   r  r;   r<   r`   1  r   c                 S  r  rV   r;   r  r;   r;   r<   r  6  r  zEPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<lambda>r	  c                 S  r  r  r;   rZ   r;   r;   r<   r`   9  ra   c                   r_   r;   r;   rZ   index_blocksr;   r<   r`   ;  ra   c                 S  r  r;   r;   rz   r;   r;   r<   r`   <  r  c                   r_   r;   r;   rZ   r   r;   r<   r`   =  ra   c                   "   g | ]}t  fd d|D qS )c                 3      | ]} | V  qd S r0   r;   re   new_index_perm_array_formr;   r<   r]   >  r   zQPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<listcomp>.<genexpr>rp   rZ   r  r;   r<   r`   >  r   c                 S  r  r;   r;   rz   r;   r;   r<   r`   @  r  c                   r_   r;   r;   r   )permutation_array_blocks_upr;   r<   r`   @  ra   )r1   r   r   r   r   r   r   r   r+   r   rd   rw   r   r   r   _push_indices_upr  r   r   r*   )rL   r   r   r   r   contraction_indices_flatZ
image_formcounterr\   currentrf   Zindex_blocks_upZindex_blocks_up_permutedZsorting_keysZnew_perm_image_formZnew_index_blocksr   new_contraction_indicesZnew_exprr  r;   )r   r   r  r   r  r!  r<   r     sD   


$z3PermuteDims._PermuteDims_denestarg_ArrayContractionc                   s  j }fddtjD fddt D }tj|d  }g g t }t|D ]J\}}| |krG g | }| || }	t	|	kr|t
 fddD }
| }t| t|
|< || g q2 ttt	}i }dgtt|  tt	|D ]*}fddt |  |d  D }t	|dkrqtt|}||kr|||< qg }g }|rt	|dkr| \}}|| n|d	 }||vrg }q||}||v r|| g }q|| |s|D ]}t|D ]\}}||||d t	|  < q
q fd
dt|D fdd|D fdd|D }dd |D }t t|fS )Nc                   s(   g | ]\}}t  j| D ]}|qqS r;   )rd   r   )r[   r\   r   rf   r   r;   r<   r`   F     ( z:PermuteDims._check_permutation_mapping.<locals>.<listcomp>c                   s   g | ]} |qS r;   r;   rZ   r   r;   r<   r`   G  ra   r   c                   s   g | ]}|t   qS r;   minre   )current_indicesr;   r<   r`   V  r   c                   s   h | ]} |  qS r;   r;   re   )	index2argr  r;   r<   r   d  r   z9PermuteDims._check_permutation_mapping.<locals>.<setcomp>rW   r   c                   s*   g | ]\ } fd dt |D qS )c                   s   g | ]
}  |  qS r;   r;   re   )cumulative_subranksr\   r  r;   r<   r`     r   zEPermuteDims._check_permutation_mapping.<locals>.<listcomp>.<listcomp>rc   )r[   r  )r-  r  r   r<   r`     r  c                   r_   r;   r;   rZ   )r   r;   r<   r`     ra   c                   r_   r;   r;   rZ   )permutation_blocksr;   r<   r`     ra   c                 S  r  r;   r;   rz   r;   r;   r<   r`     r  )r   r   r   rd   r   r   r   r   r   rw   r   r   r*   r   r   nextiterpopitemr   r   )rL   r   r   r   Zpermuted_indicesZarg_candidate_indexZinserted_arg_cand_indicesr\   idxZarg_candidate_rankZlocal_current_indicesr   Zargs_positionsmapsrr   elemlinescurrent_liner   vliner  Znew_permutation_blocksZnew_permutation2r;   )r-  r+  r   r,  r   r  r   r.  r<   _check_permutation_mappingC  sz   




&


z&PermuteDims._check_permutation_mappingc                   s   t |j}|j}|j}dgt t|  dd |D }dd |D }g }t|D ]B\}	}
d}tt d D ],||	   krb||	  d  k rbt| t	 fdd|
D g|< d} nq6|rj|
|
 q(t| t	||jd	fS )
Nr   c                 S  rb   r;   r)  rZ   r;   r;   r<   r`     ra   zAPermuteDims._check_if_there_are_closed_cycles.<locals>.<listcomp>c                 S  rb   r;   maxrZ   r;   r;   r<   r`     ra   TrW   c                      g | ]}|   qS r;   r;   r   r-  rf   r;   r<   r`     r   F)r   )r   r   r   r   r   r   rd   rw   r   r*   r   r   r   )rL   r   r   r   r   r   Z
cyclic_minZ
cyclic_maxZcyclic_keepr\   cycleflagr;   r=  r<   !_check_if_there_are_closed_cycles  s&   
$(
z-PermuteDims._check_if_there_are_closed_cyclesc                 C  s    |  | j| j}|du r| S |S )z
        DEPRECATED.
        N)_nest_permutationr   r   )r9   retr;   r;   r<   nest_permutation  s   zPermuteDims.nest_permutationc                   s   t |trt| | S t |tr8j}tj|g|R  }t|  fdd|jD }t	t
|j g|R  S t |trItfdd|jD  S d S )Nc                   r  )c                 3      | ]} |V  qd S r0   r;   re   newpermutationr;   r<   r]     r   z;PermuteDims._nest_permutation.<locals>.<listcomp>.<genexpr>r   rZ   rE  r;   r<   r`     r   z1PermuteDims._nest_permutation.<locals>.<listcomp>c                   s   g | ]}t | qS r;   r   r   r(  r;   r<   r`     r   )r1   r   r   r@  r   r   '_convert_outer_indices_to_inner_indicesr*   r   r   r   r   r   
_array_addr   )rL   r   r   ZcyclesZ	newcyclesnew_contr_indicesr;   )rF  r   r<   rA    s   


zPermuteDims._nest_permutationc                 C  s$   | j }t|dr| }t|| jS Nrm   )r   ru   rm   r   r   r9   r   r;   r;   r<   rm        
zPermuteDims.as_explicitc                 C  sR   |d u r|d u s|d u rt dt|||S |d urt d|d ur'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)rL   r   r   r   dimr;   r;   r<   r     s   z+PermuteDims._get_permutation_from_argumentsc                   sj   t t||krtdt t |krtdt tt|t dkr*td fdd|D }|S )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 indicesc                      g | ]}  |qS r;   indexrZ   r   r;   r<   r`     r   zBPermuteDims._get_permutation_from_index_orders.<locals>.<listcomp>)rw   r   rh   symmetric_difference)rL   r   r   rO  r   r;   rS  r<   rN    s   z.PermuteDims._get_permutation_from_index_orders)NNN)rA   rB   rC   rn   rK   r   ro   r   r   r   r   r   r9  r@  rC  rA  rm   r   rN  r;   r;   r;   r<   r   }  s0    
I



0
D
	

r   c                   @  s   e Zd ZdZdd Zdd Zedd Zedd	 Ze	d
d Z
e	dd Zedd Zedd Zedd Zed%ddZdd Zdd Zedd Zedd Zed d! Zd"d# Zd$S )&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                 O  s   t |}dd |D }|dd}t|}|d ur.| j|g|R i | | ||\}}nd }t|dkr8|S tj| |g|R  }||_t	||_
||_|rS| S |S )Nc                 S  s   g | ]}t t| qS r;   )r   r   rZ   r;   r;   r<   r`     r   z)ArrayDiagonal.__new__.<locals>.<listcomp>r   Fr   )r-   r   r   	_validate_get_positions_shaperw   r   rK   
_positions_get_subranksr   r   r   )rL   r   r   r   r   r/   	positionsrN   r;   r;   r<   rK     s"   
zArrayDiagonal.__new__c                 C  s  | j }| j}dd |D }t|dkrdd t|D }dd t|D }dd |D }t| }t|}|| }	g }
d}t|tt|t|}|D ]*}||v r[|
	|	||   qKt
|ttfrl|
	| |d7 }qK|
	|	||   qKt|
}t|dkrtt|g|R  |S t||S t
|tr| j|g|R  S t
|tr| j|g|R  S t
|tr| j|g|R  S t
|ttfr| |j|\}}t| S | j|g|R d	d
iS )Nc                 S  s   g | ]
}t |d kr|qS r   rw   rZ   r;   r;   r<   r`     r   z/ArrayDiagonal._canonicalize.<locals>.<listcomp>r   c                 S  s&   i | ]\}}t |d kr|d |qS rW   r   rZ  r  r;   r;   r<   r   	  r   z/ArrayDiagonal._canonicalize.<locals>.<dictcomp>c                 S  s"   i | ]\}}t |d kr||qS r   rZ  r  r;   r;   r<   r   
  r   c                 S  s   g | ]
}t |d kr|qS r   rZ  rZ   r;   r;   r<   r`     r   rW   r   F)r   r   rw   r   r   r   _push_indices_downr   rd   r   r1   r   intr+   r   r   r   _ArrayDiagonal_denest_ArrayAdd#_ArrayDiagonal_denest_ArrayDiagonalr   !_ArrayDiagonal_denest_PermuteDimsr   r   rV  r/   r   )r9   r   r   Ztrivial_diagsZtrivial_posZdiag_posZdiagonal_indices_shortZrank1Zrank2Zrank3Zinv_permutationZcounter1Zindices_downr\   r   rY  r/   r;   r;   r<   r     sD   





zArrayDiagonal._canonicalizec                   s   t |  |D ]@}t fdd|D rtdt fdd|D dkr(td|dd	s8t|dkr8td
tt|t|krFtdqd S )Nc                 3  s    | ]	}|t  kV  qd S r0   rZ  re   r   r;   r<   r]   0  rt   z*ArrayDiagonal._validate.<locals>.<genexpr>z%index is larger than expression shapec                   s   h | ]} | qS r;   r;   re   r   r;   r<   r   2  ra   z*ArrayDiagonal._validate.<locals>.<setcomp>rW   z-diagonalizing indices of different dimensionsZallow_trivial_diagsFz%need at least two axes to diagonalizezaxis index cannot be repeated)r   rx   rh   rw   r   r   )r   r   r   r\   r;   r   r<   rU  *  s   zArrayDiagonal._validatec                   s    fdd|D S )Nc                   s.   g | ]} |d   dkrt dd |D qS )r   rW   c                 s  s    | ]}|V  qd S r0   r;   re   r;   r;   r<   r]   ;  s    zFArrayDiagonal._remove_trivial_dimensions.<locals>.<listcomp>.<genexpr>r   rZ   r   r;   r<   r`   ;     . z<ArrayDiagonal._remove_trivial_dimensions.<locals>.<listcomp>r;   )r/   r   r;   r   r<   _remove_trivial_dimensions9     z(ArrayDiagonal._remove_trivial_dimensionsc                 C  rO   rP   r   rS   r;   r;   r<   r   =  rU   zArrayDiagonal.exprc                 C     | j dd  S rV   r   rS   r;   r;   r<   r   A     zArrayDiagonal.diagonal_indicesc                   s   | j }dd |D }|  t| }t|}|| }dd t|D  d}d}t|D ]*}	||k rI||| krI|d7 }|d7 }||k rI||| ks7 |	  |7  < |d7 }q+t fdd|D }|| }
t| jg|
R  S )Nc                 S  r  r;   r;   rz   r;   r;   r<   r`   H  r  z*ArrayDiagonal._flatten.<locals>.<listcomp>c                 S     g | ]}d qS r  r;   rZ   r;   r;   r<   r`   N      r   rW   c                 3  &    | ]}t  fd d|D V  qdS )c                 3      | ]	} | | V  qd S r0   r;   re   shiftsr;   r<   r]   W  rt   z3ArrayDiagonal._flatten.<locals>.<genexpr>.<genexpr>Nr   rZ   rj  r;   r<   r]   W     $ z)ArrayDiagonal._flatten.<locals>.<genexpr>)r   r  r   rw   rd   rp   r   r   )r   Zouter_diagonal_indicesZinner_diagonal_indices	all_inner
total_rank
inner_rank
outer_rankr$  pointerr\   r   r;   rj  r<   r   E  s&   
zArrayDiagonal._flattenc                      t  fdd|jD  S )Nc                      g | ]
}t |g R  qS r;   )r   r   r   r;   r<   r`   ]  r   z@ArrayDiagonal._ArrayDiagonal_denest_ArrayAdd.<locals>.<listcomp>rI  r   rL   r   r   r;   rt  r<   r^  [     z,ArrayDiagonal._ArrayDiagonal_denest_ArrayAddc                 G     | j |g|R  S r0   r   rv  r;   r;   r<   r_  _  rc  z1ArrayDiagonal._ArrayDiagonal_denest_ArrayDiagonalr   r   c           	        s   fdd D } fddt tD }fdd|D }dd tt|D fdd|D }t|fddt t|D }|| }ttjg|R  |S )	Nc                   r  )c                   rP  r;   r(  re   r   r;   r<   r`   e  r   zNArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<listcomp>.<listcomp>r;   rZ   r   r;   r<   r`   e  r   zCArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<listcomp>c                   &   g | ] t  fd dD s qS )c                 3      | ]} |v V  qd S r0   r;   re   r   r;   r<   r]   f  r   zMArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<listcomp>.<genexpr>rx   r[   rt  r   r<   r`   f  r   c                   rP  r;   r(  rZ   r   r;   r<   r`   g  r   c                 S  s   i | ]\}}||qS r;   r;   r  r;   r;   r<   r   h  r   zCArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<dictcomp>c                   r_   r;   r;   rZ   )remapr;   r<   r`   i  ra   c                   s   g | ]}|  qS r;   r;   rZ   )shiftr;   r<   r`   k  ra   )rd   r   r   r   rw   r   r   r   )	rL   r   r   Zback_diagonal_indicesZnondiagZback_nondiagZnew_permutation1Zdiag_block_permr  r;   )r   r   r~  r  r<   r`  c  s    z/ArrayDiagonal._ArrayDiagonal_denest_PermuteDimsc                       fdd}t ||S )Nc                   s   | t  jk r j|  S d S r0   )rw   rW  r  rS   r;   r<   r  v  r   z<ArrayDiagonal._push_indices_down_nonstatic.<locals>.<lambda>r#   r9   rq   	transformr;   rS   r<   _push_indices_down_nonstaticu  s   
z*ArrayDiagonal._push_indices_down_nonstaticc                   r  )Nc                   sD   t  jD ]\}}t|tr| |kst|tr| |v r|  S qd S r0   )r   rW  r1   r]  rp   r  r\   r  rS   r;   r<   r  {  s
   $z;ArrayDiagonal._push_indices_up_nonstatic.<locals>.transformr  r  r;   rS   r<   _push_indices_up_nonstaticy  s   
z(ArrayDiagonal._push_indices_up_nonstaticc                   *   |  t||\ } fdd}t||S )Nc                   s   | t  k r
 |  S d S r0   rZ  r  rY  r;   r<   r    r   z2ArrayDiagonal._push_indices_down.<locals>.<lambda>rV  rd   r#   rL   r   rq   rankr/   r  r;   r  r<   r\    s   
z ArrayDiagonal._push_indices_downc                   r  )Nc                   sF   t  D ]\}}t|tr| |kst|ttfr | |v r |  S qd S r0   )r   r1   r]  rp   r   r  r  r;   r<   r    s
   (z1ArrayDiagonal._push_indices_up.<locals>.transformr  r  r;   r  r<   r"    s   
zArrayDiagonal._push_indices_upc           
        sp   t  fddtD }|rt| nd\}}t fdd D }|r(t| nd\}}|| }	|| |	fS )Nc                 3  s2    | ]\ }t  fd dD s |fV  qdS )c                 3  r{  r0   r;   re   r   r;   r<   r]     r   z?ArrayDiagonal._get_positions_shape.<locals>.<genexpr>.<genexpr>Nr|  r[   Zshprt  r   r<   r]     s   0 z5ArrayDiagonal._get_positions_shape.<locals>.<genexpr>)r;   r;   c                 3  s     | ]}| |d   fV  qdS )r   Nr;   rZ   r   r;   r<   r]     rs   )rp   r   ry   )
rL   r/   r   Zdata1Zpos1Zshp1Zdata2pos2Zshp2rY  r;   )r   r/   r<   rV    s   z"ArrayDiagonal._get_positions_shapec                 C  *   | j }t|dr| }t|g| jR  S rK  )r   ru   rm   r   r   rL  r;   r;   r<   rm        
zArrayDiagonal.as_explicitN)r   r   )rA   rB   rC   rn   rK   r   staticmethodrU  rb  ro   r   r   r   r   r^  r_  r`  r  r  r\  r"  rV  rm   r;   r;   r;   r<   r     s:    &






	



	r   c                   @  sH   e Zd Zdd Zedd Zedd Zedd Zd	d
 Zdd Z	dS )ArrayElementwiseApplyFuncc                 C  s<   t |tstd}t|||}t| ||}t||_|S Nd)r1   r   r   r   rK   rX  r   )rL   functionelementr  rN   r;   r;   r<   rK     s   

z!ArrayElementwiseApplyFunc.__new__c                 C  rO   rP   r   rS   r;   r;   r<   r    rU   z"ArrayElementwiseApplyFunc.functionc                 C  rO   rV   r   rS   r;   r;   r<   r     rU   zArrayElementwiseApplyFunc.exprc                 C  s   | j jS r0   r   r/   rS   r;   r;   r<   r/     s   zArrayElementwiseApplyFunc.shapec                 C  s@   t d}| |}||}t|trt|}|S t||}|S r  )r   r  diffr1   r   typer   )r9   r  r  Zfdiffr;   r;   r<   _get_function_fdiff  s   



z-ArrayElementwiseApplyFunc._get_function_fdiffc                 C  s$   | j }t|dr| }|| jS rK  )r   ru   rm   Z	applyfuncr  rL  r;   r;   r<   rm     rM  z%ArrayElementwiseApplyFunc.as_explicitN)
rA   rB   rC   rK   ro   r  r   r/   r  rm   r;   r;   r;   r<   r    s    




r  c                   @  sN  e Zd ZdZdd Zdd Zdd Zdd	 Zed
d Z	e
dd Ze
dd Ze
dd Zdd Zdd Zedd Zedd Zedd Zedd Ze
dd Ze
d d! Ze
d"d# Ze
d$d% Ze
dAd(d)Ze
d*d+ Zd,d- Zed.d/ Zed0d1 Zed2d3 Zed4d5 Zed6d7 Z d8d9 Z!d:d; Z"d<d= Z#d>d? Z$d@S )Br   zx
    This class is meant to represent contractions of arrays in a form easily
    processable by the code printers.
    c                   s   t   t|}|dd}tj| |g R  }t||_t|j|_ fddt	t
|jD }||_t|}| j|g R   |rPt fddt|D }||_|rY| S |S )Nr   Fc                   s(   i | ] t  fd dD r  qS )c                 3  s    | ]} |vV  qd S r0   r;   )r[   Zcindr   r;   r<   r]     r   z6ArrayContraction.__new__.<locals>.<dictcomp>.<genexpr>)rg   r}  r   r   r<   r     r'  z,ArrayContraction.__new__.<locals>.<dictcomp>c                 3  s.    | ]\ }t  fd dD s|V  qdS )c                 3  r{  r0   r;   re   r   r;   r<   r]     r   z5ArrayContraction.__new__.<locals>.<genexpr>.<genexpr>Nr|  r  r  r   r<   r]     s   , z+ArrayContraction.__new__.<locals>.<genexpr>)r$   r-   r   r   rK   rX  r   r%   _mappingrd   r   _free_indices_to_positionr   rU  rp   r   r   r   )rL   r   r   r   r   rN   free_indices_to_positionr/   r;   r  r<   rK     s    
zArrayContraction.__new__c                   s   | j  | j}t|dkr S t tr| j g|R  S t ttfr,| j g|R  S t t	r:| j
 g|R  S t trW|  |\ }|  |\ }t|dkrW S t tre| j g|R  S t trs| j g|R  S  fdd|D }t|dkr S | j g|R ddiS )Nr   c                   s0   g | ]}t |d kst |d  d kr|qS r[  )rw   r   rZ   r   r;   r<   r`     s   0 z2ArrayContraction._canonicalize.<locals>.<listcomp>r   F)r   r   rw   r1   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   )r9   r   r;   r   r<   r     s.   




zArrayContraction._canonicalizec                 C     |dkr| S t dNrW   zDProduct of N-dim arrays is not uniquely defined. Use another method.r   r9   otherr;   r;   r<   __mul__     zArrayContraction.__mul__c                 C  r  r  r  r  r;   r;   r<   __rmul__  r  zArrayContraction.__rmul__c                   sD   t |   d u r
d S |D ]}t fdd|D dkrtdqd S )Nc                   s    h | ]} | d kr | qS )r   r;   re   r   r;   r<   r      r   z-ArrayContraction._validate.<locals>.<setcomp>rW   z+contracting indices of different dimensions)r   rw   rh   )r   r   r\   r;   r   r<   rU    s   zArrayContraction._validatec                 C  (   dd |D }|   t|}t||S )Nc                 S  r  r;   r;   rz   r;   r;   r<   r`   %  r  z7ArrayContraction._push_indices_down.<locals>.<listcomp>)r  r(   r#   rL   r   rq   flattened_contraction_indicesr  r;   r;   r<   r\  #     
z#ArrayContraction._push_indices_downc                 C  r  )Nc                 S  r  r;   r;   rz   r;   r;   r<   r`   ,  r  z5ArrayContraction._push_indices_up.<locals>.<listcomp>)r  r&   r#   r  r;   r;   r<   r"  *  r  z!ArrayContraction._push_indices_upc           	        sD  t |trt t |ts||fS |j}ttdg| g }dd |jD }t  |D ]<}t	t
|jD ]-t |j ts@q5tfdd|D rb| fdd|D   |  nq5|| q,t
|t
|kru||fS t|}tt fddt	|D fdd|D }td	d t|j|D  }||fS )
Nr   c                 S     g | ]}g qS r;   r;   rZ   r;   r;   r<   r`   :  rg  zBArrayContraction._lower_contraction_to_addends.<locals>.<listcomp>c                 3  s4    | ]}  |  ko d   k n  V  qdS )rW   Nr;   r   cumranksrf   r;   r<   r]   @  s   2 zAArrayContraction._lower_contraction_to_addends.<locals>.<genexpr>c                   r<  r;   r;   r   r  r;   r<   r`   A  r   c                   s   g | ]
}| v r
d ndqS r[  r;   rZ   )	backshiftr;   r<   r`   I  r   c                   s$   g | ]}t  fd d|D qS )c                 3  s    | ]	}| |  V  qd S r0   r;   re   rj  r;   r<   r]   J  rt   zLArrayContraction._lower_contraction_to_addends.<locals>.<listcomp>.<genexpr>)r   r~   rZ   rj  r;   r<   r`   J  r  c                 S  s    g | ]\}}t |g|R  qS r;   r   )r[   r   Zcontrr;   r;   r<   r`   K  s    )r1   r   r   r   r   r   r   r   r   rd   rw   rg   r   updater   r   ry   )	rL   r   r   r   Zcontraction_indices_remainingZcontraction_indices_argscontraction_grouprn  rB  r;   )r  r  rf   rk  r<   r  1  s:   




z.ArrayContraction._lower_contraction_to_addendsc                   s  t | }| j}g }t|D ]\ }t|dkrq| }| jj|d  }g }g }|D ]H\}	}
|j|	 }|j}|	|\}}d|
 }|| d|jvsd|dkdu rV|jdksdt
 fddt|D rl|||
f q+|||
f q+t|dkr{q|D ]
\}}
t|j|_q}|dd | |dd  }|d \}}
|j|
 }|dd	 D ]'\}}
||j|
< | }|jdd|
 ksJ ||j|jd< || q|d	 \}}
||j|
< q|D ]}||ttddg q| 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   rW   T)rW   rW   c                 3  s$    | ]\}}| kr|v V  qd S r0   r;   )r[   ZlilZindlZother_arg_absr;   r<   r]     s   " z?ArrayContraction.split_multiple_contractions.<locals>.<genexpr>Nr   )_EditArrayContractionr   r   rw   get_mapping_for_indexr   r/   args_with_indr  get_absolute_rangerx   r   r   rq   get_new_contraction_indexrR  insert_after_ArgEr   to_array_contraction)r9   Zeditorr   Zonearray_insertlinksrY  Zcurrent_dimensionZnot_vectorsZvectorsarg_indZrel_indr   matZabs_arg_startZabs_arg_endZother_arg_posr7  Zvectors_to_loopZfirst_not_vectorZ	new_indexZlast_vecr;   r  r<   split_multiple_contractionsP  sP   




z,ArrayContraction.split_multiple_contractionsc                   s   t | jts| S | j| jj| j}g }| jjd d  }|D ]0}t|}|D ]fdd|D  |dd  D   fdd|D }q&|t	t
| qt||}tt| jjg|R  g|R  S )Nc                   s   g | ]} |v r|qS r;   r;   r   )rf   r;   r<   r`     r   zDArrayContraction.flatten_contraction_of_diagonal.<locals>.<listcomp>c                 S  r  r;   r;   )r[   r   r  r;   r;   r<   r`     r  c                   s   g | ]}| vr|qS r;   r;   r   )diagonal_withr;   r<   r`     r   )r1   r   r   r\  r   r   r   r   r   r   r   r"  r   r   )r9   Zcontraction_downr&  r   r\   r  r;   )r  rf   r<   flatten_contraction_of_diagonal  s,   z0ArrayContraction.flatten_contraction_of_diagonalc                 C  sL   i }dd |D }d}| D ]}||v r|d7 }||v s|||< |d7 }q|S )Nc                 S  r  r;   r;   rz   r;   r;   r<   r`     r  zFArrayContraction._get_free_indices_to_position_map.<locals>.<listcomp>r   rW   r;   )free_indicesr   r  r  r$  indr;   r;   r<   !_get_free_indices_to_position_map  s   
z2ArrayContraction._get_free_indices_to_position_mapc           
      C  s   | j }dd |D }|  t| }t|}|| }dd t|D }d}d}t|D ]*}	||k rI||| krI|d7 }|d7 }||k rI||| ks7||	  |7  < |d7 }q+|S )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).
        c                 S  r  r;   r;   rz   r;   r;   r<   r`     r  z6ArrayContraction._get_index_shifts.<locals>.<listcomp>c                 S  rf  r  r;   rZ   r;   r;   r<   r`     rg  r   rW   )r   r  r   rw   rd   )
r   inner_contraction_indicesrm  rn  ro  rp  rk  r$  rq  r\   r;   r;   r<   _get_index_shifts  s"   
z"ArrayContraction._get_index_shiftsc                   s$   t |  t fdd|D }|S )Nc                 3  rh  )c                 3  ri  r0   r;   re   rj  r;   r<   r]     rt   zUArrayContraction._convert_outer_indices_to_inner_indices.<locals>.<genexpr>.<genexpr>Nr   rZ   rj  r;   r<   r]     rl  zKArrayContraction._convert_outer_indices_to_inner_indices.<locals>.<genexpr>)r   r  rp   )r   outer_contraction_indicesr;   rj  r<   rH    s   
z8ArrayContraction._convert_outer_indices_to_inner_indicesc                 G  s2   | j }tj| g|R  }|| }t| jg|R  S r0   )r   r   rH  r   r   )r   r  r  r   r;   r;   r<   r     s   zArrayContraction._flattenc                 G  rx  r0   ry  rL   r   r   r;   r;   r<   r    rc  z:ArrayContraction._ArrayContraction_denest_ArrayContractionc                   s.   dd |D   fddt |jD }t| S )Nc                 S  r  r;   r;   rz   r;   r;   r<   r`     r  zGArrayContraction._ArrayContraction_denest_ZeroArray.<locals>.<listcomp>c                   s   g | ]
\}}| vr|qS r;   r;   r  r#  r;   r<   r`     r   )r   r/   r   )rL   r   r   r/   r;   r  r<   r    s   z3ArrayContraction._ArrayContraction_denest_ZeroArrayc                   rr  )Nc                   rs  r;   r  rZ   r  r;   r<   r`     r   zFArrayContraction._ArrayContraction_denest_ArrayAdd.<locals>.<listcomp>ru  r  r;   r  r<   r    rw  z2ArrayContraction._ArrayContraction_denest_ArrayAddc                   sX   |j j}fdd|D   fdd|D }|  |}tt|jg R  t|S )Nc                   r  )c                 3  rD  r0   r;   re   r(  r;   r<   r]     r   SArrayContraction._ArrayContraction_denest_PermuteDims.<locals>.<listcomp>.<genexpr>r   rZ   r(  r;   r<   r`     r   zIArrayContraction._ArrayContraction_denest_PermuteDims.<locals>.<listcomp>c                   rz  )c                 3  r{  r0   r;   re   r   r;   r<   r]     r   r  r|  r}  )r&  r   r<   r`     r   )r   r   r"  r   r   r   r*   )rL   r   r   r   Z	new_plistr;   )r&  r   r<   r    s   z5ArrayContraction._ArrayContraction_denest_PermuteDimsr   'ArrayDiagonal'c                   s   t |j}||j|t|j}dd |D }g }|D ]3}|d d  }t|D ]\}  d u r0q't fdd|D rD|  d ||< q'|t	t
| qdd |D }	t||	}
tt|jg|R  g|
R  S )Nc                 S  s   g | ]	}d d |D qS )c                 S  s.   g | ]}t |ttfr|n|gD ]}|qqS r;   )r1   rp   r   r[   rf   r   r;   r;   r<   r`   *  ra  zVArrayContraction._ArrayContraction_denest_ArrayDiagonal.<locals>.<listcomp>.<listcomp>r;   rZ   r;   r;   r<   r`   *  r  zKArrayContraction._ArrayContraction_denest_ArrayDiagonal.<locals>.<listcomp>c                 3      | ]}| v V  qd S r0   r;   rZ   Zdiag_indgrpr;   r<   r]   1  r   zJArrayContraction._ArrayContraction_denest_ArrayDiagonal.<locals>.<genexpr>c                 S  s   g | ]}|d ur|qS r0   r;   rZ   r;   r;   r<   r`   6  r   )r   r   r\  r   r   r   rx   r   r   r   r   r   r"  r   r   )rL   r   r   r   Zdown_contraction_indicesr&  Zcontr_indgrpr  rf   Znew_diagonal_indices_downZnew_diagonal_indicesr;   r  r<   r  %  s*   

z7ArrayContraction._ArrayContraction_denest_ArrayDiagonalc                   s   j d u r	|fS ttdgj fddttjD dd |D   fddtjD tttjfddd	}fd
d|D }fdd|D }t	|fdd|D }t
|}t| |fS )Nr   c                   s&   g | ]}t t |  |d   qS r   r  rZ   r  r;   r<   r`   B  r   z@ArrayContraction._sort_fully_contracted_args.<locals>.<listcomp>c                 S  s   h | ]	}|D ]}|qqS r;   r;   rz   r;   r;   r<   r   C  r  z?ArrayContraction._sort_fully_contracted_args.<locals>.<setcomp>c              	     s8   g | ]\}}t  fd dt| |d  D qS )c                 3  r  r0   r;   re   r  r;   r<   r]   D  r   JArrayContraction._sort_fully_contracted_args.<locals>.<listcomp>.<genexpr>rW   )rg   rd   r   )r#  r   r;   r<   r`   D  s   8 c                   s   |  rdt  j|  fS dS )Nr   r   )r   r   r  )r   fully_contractedr;   r<   r  E  r   z>ArrayContraction._sort_fully_contracted_args.<locals>.<lambda>r	  c                   r   r;   r   rZ   r   r;   r<   r`   F  r   c                   s   g | ]} | D ]}|qqS r;   r;   rz   r  r;   r<   r`   G  r   c                   r  )c                 3  r  r0   r;   re   index_permutation_array_formr;   r<   r]   I  r   r  r   rZ   r  r;   r<   r`   I  r   )r/   r   r   r   rd   rw   r   r   r   r+   r$   r   )rL   r   r   new_posr   Znew_index_blocks_flatr&  r;   )r#  r   r   r  r  r  r<   r  =  s   
 z,ArrayContraction._sort_fully_contracted_argsc                   s   | j   fdd| jD S )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`).
        c                   r  )c                   r_   r;   r;   re   mappingr;   r<   r`   j  ra   zGArrayContraction._get_contraction_tuples.<locals>.<listcomp>.<listcomp>r;   rZ   r  r;   r<   r`   j  r   z<ArrayContraction._get_contraction_tuples.<locals>.<listcomp>)r  r   rS   r;   r  r<   _get_contraction_tuplesM  s   z(ArrayContraction._get_contraction_tuplesc                   s*   | j }dgtt|   fdd|D S )Nr   c                   r  )c                 3  s     | ]\}} | | V  qd S r0   r;   r  r   r;   r<   r]   q  rs   zYArrayContraction._contraction_tuples_to_contraction_indices.<locals>.<listcomp>.<genexpr>r   rZ   r   r;   r<   r`   q  r   zOArrayContraction._contraction_tuples_to_contraction_indices.<locals>.<listcomp>)r   r   r   )r   contraction_tuplesr   r;   r   r<   *_contraction_tuples_to_contraction_indicesl  s   z;ArrayContraction._contraction_tuples_to_contraction_indicesc                 C  s   | j d d  S r0   )Z_free_indicesrS   r;   r;   r<   r  s  re  zArrayContraction.free_indicesc                 C  r   r0   )dictr  rS   r;   r;   r<   r  w  rU   z)ArrayContraction.free_indices_to_positionc                 C  rO   rP   r   rS   r;   r;   r<   r   {  rU   zArrayContraction.exprc                 C  rd  rV   r   rS   r;   r;   r<   r     re  z$ArrayContraction.contraction_indicesc                 C  s^   | j }t|tstd|j}i }d}t|D ]\}}t|D ]}||f||< |d7 }qq|S )Nz(only for contractions of tensor productsr   rW   )r   r1   r   r   r   r   rd   )r9   r   r   r  r$  r\   r  rf   r;   r;   r<   "_contraction_indices_to_components  s   

z3ArrayContraction._contraction_indices_to_componentsc                   s   | j }t|ts
| S |j}tt|dd d}t| \ } fddt|D |  }fdd|D }t| }| 	||}t
|g|R  S )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                 S  s   t | d S rV   r   r  r;   r;   r<   r    s    z4ArrayContraction.sort_args_by_name.<locals>.<lambda>r	  c                   s   i | ]
\}}|  |qS r;   rQ  r   )
pos_sortedr;   r<   r     r   z6ArrayContraction.sort_args_by_name.<locals>.<dictcomp>c                   r  )c                   s   g | ]
\}} | |fqS r;   r;   r  reordering_mapr;   r<   r`     r   zAArrayContraction.sort_args_by_name.<locals>.<listcomp>.<listcomp>r;   rZ   r  r;   r<   r`     r   z6ArrayContraction.sort_args_by_name.<locals>.<listcomp>)r   r1   r   r   r   r   ry   r  r   r  r   )r9   r   r   Zsorted_datar  r  Zc_tprJ  r;   )r  r  r<   sort_args_by_name  s   
z"ArrayContraction.sort_args_by_namec                 C  s    t | g| jg| jR  \}}|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   )r9   r   Zdlinksr;   r;   r<   r'     s   )z'ArrayContraction._get_contraction_linksc                 C  r  rK  )r   ru   rm   r   r   rL  r;   r;   r<   rm     r  zArrayContraction.as_explicitN)r   r  )%rA   rB   rC   rn   rK   r   r  r  r  rU  r   r\  r"  r  r  r  r  r  rH  r   r  r  r  r  r  r  r  r  ro   r  r  r   r   r  r  r'   rm   r;   r;   r;   r<   r     sf    #




d

&











%,r   c                   @  s@   e Zd ZdZdd Zedd Zedd Zdd	 Zd
d Z	dS )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                 C  s`   t |}t|tst| }tt|jt|dkrtdt	| ||}t
||_||_|S )NFzshape mismatch)r-   r1   r   r   r   r~   r/   rh   r   rK   rp   r   _expr)rL   r   r/   rN   r;   r;   r<   rK     s   

zReshape.__new__c                 C  r   r0   r   rS   r;   r;   r<   r/   
  r   zReshape.shapec                 C  r   r0   )r  rS   r;   r;   r<   r     r   zReshape.exprc                 O  sL   | ddr| jj|i |}n| j}t|ttfr |j| j S t|| jS )Nr   T)	r   r   r   r1   r   r   rk   r/   r  )r9   r   r   r   r;   r;   r<   r     s   zReshape.doitc                 C  sR   | j }t|dr| }t|trddlm} ||}nt|tr#| S |j| j	 S )Nrm   r   )Array)
r   ru   rm   r1   r   Zsympyr  r   rk   r/   )r9   eer  r;   r;   r<   rm     s   



zReshape.as_explicitN)
rA   rB   rC   rn   rK   ro   r/   r   r   rm   r;   r;   r;   r<   r    s    

	r  c                   @  s2   e Zd ZU dZded< d
dddZdd	 ZeZdS )r  al  
    The ``_ArgE`` object contains references to the array expression
    (``.element``) and a list containing the information about index
    contractions (``.indices``).

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

    For example:
    ``_ArgE(M, [None, 3])``
    This object means that expression ``M`` is part of an array contraction
    and has two indices, the first is not contracted (value ``None``),
    the second index is contracted to the 4th (i.e. number ``3``) group of the
    array contraction object.
    zlist[int | None]rq   Nlist[int | None] | Nonec                 C  s4   || _ |d u rdd tt|D | _d S || _d S )Nc                 S  rf  r0   r;   rZ   r;   r;   r<   r`   <  rg  z"_ArgE.__init__.<locals>.<listcomp>)r  rd   r   rq   )r9   r  rq   r;   r;   r<   __init__9  s   
z_ArgE.__init__c                 C     d| j | jf S )Nz_ArgE(%s, %s))r  rq   rS   r;   r;   r<   __str__@     z_ArgE.__str__r0   )rq   r  )rA   rB   rC   rn   rD   r  r  __repr__r;   r;   r;   r<   r  '  s   
 r  c                   @  s.   e Zd ZdZdddZdd ZeZd	d
 ZdS )_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   r]  relc                 C  s   || _ || _d S r0   r   r  )r9   r   r  r;   r;   r<   r  M  s   
z_IndPos.__init__c                 C  r  )Nz_IndPos(%i, %i)r  rS   r;   r;   r<   r  Q  r  z_IndPos.__str__c                 c  s    | j | jgE d H  d S r0   r  rS   r;   r;   r<   __iter__V  s   z_IndPos.__iter__N)r   r]  r  r]  )rA   rB   rC   rn   r  r  r  r  r;   r;   r;   r<   r  F  s    
r  c                   @  s   e Zd ZdZd2ddZd3d	d
Zdd Zdd Zdd Zdd Z	d4ddZ
d5ddZd6ddZd7dd Zd8d"d#Zed$d% Zd&d' Zd9d*d+Zd:d-d.Zd:d/d0Zd1S );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_arrayAtyping.Union[ArrayContraction, ArrayDiagonal, ArrayTensorProduct]c                 C  s  t |trt|j}|j}|j}d}nNt |trRt |jtr6t|jj}|jj}t|jj|j}|jj}n+t |jt	rGi }|j}|j}g }ni }|j}|j}g }nt |t	r^|}g }d}nt
 t |t	rlt|j}n|g}dd |D }t|D ]\}}	|	D ]}
||
 \}}||| j|< qqz|| _t|| _d | _t|j}t|D ]\}}|D ]}
||
 \}}d| | j| j|< qqd S )Nr;   c                 S  rb   r;   )r  r   r;   r;   r<   r`     ra   z2_EditArrayContraction.__init__.<locals>.<listcomp>r   )r1   r   r%   r   r   r   r   r\  r   r   r   r   r   r   rq   r  rw   number_of_contraction_indices_track_permutation)r9   r  r  r   r   Zdiagonalizedr   r  r\   Zcontraction_tuplerf   Zarg_posZrel_posr  r;   r;   r<   r  i  sX   







z_EditArrayContraction.__init__r   r  new_argc                 C  s"   | j |}| j |d | d S rV   )r  rR  insert)r9   r   r  posr;   r;   r<   r    s   z"_EditArrayContraction.insert_afterc                 C  s   |  j d7  _ | j d S rV   )r  rS   r;   r;   r<   r    s   
z/_EditArrayContraction.get_new_contraction_indexc                   st   i  | j D ]} dd |jD  qtt D ]\}}| |< qt | _| j D ]} fdd|jD |_q*d S )Nc                 S  s   i | ]	}|d ur|dqS )Nr   r;   rZ   r;   r;   r<   r     r  z9_EditArrayContraction.refresh_indices.<locals>.<dictcomp>c                   s   g | ]}  |d qS r0   )r   rZ   Zupdatesr;   r<   r`     r   z9_EditArrayContraction.refresh_indices.<locals>.<listcomp>)r  r  rq   r   r   rw   r  )r9   arg_with_indr\   r  r;   r  r<   refresh_indices  s   



z%_EditArrayContraction.refresh_indicesc                 C  s   g }| j D ]}t|jdkr|| q|D ]}| j | qtdd |D }t| j dkr:| j t| d S ddlm	} ||| j d j
| j d _
d S )Nr   c                 S  r   r;   r  rZ   r;   r;   r<   r`     r   z7_EditArrayContraction.merge_scalars.<locals>.<listcomp>)_a2m_tensor_product)r  rw   rq   r   remover   r~   r  Z3sympy.tensor.array.expressions.from_array_to_matrixr  r  )r9   Zscalarsr  r\   Zscalarr  r;   r;   r<   merge_scalars  s   

z#_EditArrayContraction.merge_scalarsc                 C  s  d}t t}t }| jD ]
}|t|j q|d  }g }g }t }d}	| jD ]p}d}
|jD ]S}|d u rB||	 |
d7 }
|	d7 }	q.|dkrGq.|d|  ||
  || dkrk||vrk||d |  || n||vr}||d |  || |
d7 }
q.dd |jD |_|t	dd |jD 7 }q'|| }t
|}dd | D }|   |   dd | jD }|  }tt| g|R  }t|g|R  }| jd urt
d	d | jD }t||}t||}|S )
Nr   rW   r   c                 S  s$   g | ]}|d ur|dkr|nd qS rP   r;   rZ   r;   r;   r<   r`     r  z>_EditArrayContraction.to_array_contraction.<locals>.<listcomp>c                 S  s    g | ]}|d u s|dk r|qS rP   r;   rZ   r;   r;   r<   r`     r   c                 S  s    g | ]}t |d krt|qS r   )rw   rp   )r[   r7  r;   r;   r<   r`     r   c                 S  r   r;   r  r   r;   r;   r<   r`     r   c                 S  r  r;   r;   rz   r;   r;   r<   r`     r  )r   r   r   r  r  rq   r   r   r   rw   r+   valuesr  r  get_contraction_indicesr   r   r   r  r   )r9   r$  Zdiag_indicesZcount_index_freqr  Zfree_index_countZ	inv_perm1Z	inv_perm2doneZcounter4counter2r\   r   r   Zdiag_indices_filteredr   r   r   Zexpr2Zpermutation2Zexpr3r;   r;   r<   r    sX   








z*_EditArrayContraction.to_array_contractionrG   list[list[int]]c                 C  sR   dd t | jD }d}| jD ]}|jD ]}|d ur!|| | |d7 }qq|S )Nc                 S  r  r;   r;   rZ   r;   r;   r<   r`     rg  zA_EditArrayContraction.get_contraction_indices.<locals>.<listcomp>r   rW   )rd   r  r  rq   r   )r9   r   current_positionr  rf   r;   r;   r<   r    s   


z-_EditArrayContraction.get_contraction_indiceslist[_IndPos]c                 C  sZ   || j kr	tdg }t| jD ]\}}t|jD ]\}}||kr)|t|| qq|S )Nz%index value exceeding the index range)r  rh   r   r  rq   r   r  )r9   r  rY  r\   r  rf   r  r;   r;   r<   r    s   
z+_EditArrayContraction.get_mapping_for_indexlist[list[_IndPos]]c                 C  s\   dd t | jD }t| jD ]\}}t|jD ]\}}|d ur*|| t|| qq|S )Nc                 S  r  r;   r;   rZ   r;   r;   r<   r`     rg  zP_EditArrayContraction.get_contraction_indices_to_ind_rel_pos.<locals>.<listcomp>)rd   r  r   r  rq   r   r  )r9   r   r\   r  rf   r  r;   r;   r<   &get_contraction_indices_to_ind_rel_pos  s   z<_EditArrayContraction.get_contraction_indices_to_ind_rel_posrR  r]  c                 C  s&   d}| j D ]}||jv r|d7 }q|S )zJ
        Count the number of arguments that have the given index.
        r   rW   )r  rq   )r9   rR  r$  r  r;   r;   r<   count_args_with_index!  s   

z+_EditArrayContraction.count_args_with_indexlist[_ArgE]c                   s    fdd| j D }|S )zA
        Get a list of arguments having the given index.
        c                   s   g | ]	} |j v r|qS r;   )rq   rZ   rQ  r;   r<   r`   /  r  z=_EditArrayContraction.get_args_with_index.<locals>.<listcomp>)r  )r9   rR  rB  r;   rQ  r<   get_args_with_index+  s   z)_EditArrayContraction.get_args_with_indexc                 C  s0   t  }| jD ]}|dd |jD  qt|S )Nc                 S  s    h | ]}|d ur|dk r|qS rP   r;   rZ   r;   r;   r<   r   6  r   zC_EditArrayContraction.number_of_diagonal_indices.<locals>.<setcomp>)r   r  r  rq   rw   )r9   rl   r   r;   r;   r<   number_of_diagonal_indices2  s   
z0_EditArrayContraction.number_of_diagonal_indicesc                   s   g }g }d}d}| j D ]*}g }|jD ]}|d ur&|dk r%|| |d8 }q|| |d7 }q|| q|rAtdd |D nd  fdd|D }||g | _d S )Nr   r   rW   c                 s  s     | ]}|r
t |nd V  qdS )r   Nr:  rZ   r;   r;   r<   r]   I  rs   z@_EditArrayContraction.track_permutation_start.<locals>.<genexpr>c                   s   g | ]} | qS r;   r;   rZ   Zmax_indr;   r<   r`   J  ra   zA_EditArrayContraction.track_permutation_start.<locals>.<listcomp>)r  rq   r   r;  r  )r9   r   Z	perm_diagr$  r  r  permr\   r;   r  r<   track_permutation_start9  s$   




z-_EditArrayContraction.track_permutation_startdestinationfrom_elementc                 C  s>   | j |}| j |}| j| | j|  | j| d S r0   )r  rR  r  r   r   )r9   r  r  Zindex_destinationZindex_elementr;   r;   r<   track_permutation_mergeM  s   z-_EditArrayContraction.track_permutation_mergetyping.Tuple[int, int]c                 C  sL   d}| j D ]}tdd |jD }||kr||| f  S ||7 }qtd)zw
        Return the range of the free indices of the arg as absolute positions
        among all free indices.
        r   c                 S  s   g | ]}|d u r|qS r0   r;   rZ   r;   r;   r<   r`   Z  r   zA_EditArrayContraction.get_absolute_free_range.<locals>.<listcomp>argument not foundr  rw   rq   rv   )r9   r   r$  r  Znumber_free_indicesr;   r;   r<   get_absolute_free_rangeS  s   

z-_EditArrayContraction.get_absolute_free_rangec                 C  sB   d}| j D ]}t|j}||kr||| f  S ||7 }qtd)zc
        Return the absolute range of indices for arg, disregarding dummy
        indices.
        r   r  r  )r9   r   r$  r  Znumber_indicesr;   r;   r<   r  `  s   


z(_EditArrayContraction.get_absolute_rangeN)r  r  )r   r  r  r  )rG   r  )rG   r  )rG   r	  )rR  r]  rG   r]  )rR  r]  rG   r  )r  r  r  r  )r   r  rG   r  )rA   rB   rC   rn   r  r  r  r  r  r  r  r  r
  r  r  ro   r  r  r  r  r  r;   r;   r;   r<   r  Z  s&    

9

C









r  c                 C  s   t | ttfr	dS t | trt| jS t | tr|  S t | tr$| jS t | t	r6| j}|d u r2dS t|S t
| dr@t| jS dS )Nr  r   r/   r   )r1   r   r"   r   rw   r/   r   r  r    r!   ru   r  r;   r;   r<   r   n  s    






r   c                 C  s   t | tr	|  S t| S r0   )r1   r   r   r   r   r;   r;   r<   r     s   
r   c                 C  s   t | tr| jS t| gS r0   )r1   r   r   r   r   r;   r;   r<   rX    s   

rX  c                 C  s   t | dr| jS dS )Nr/   r;   )ru   r/   r   r;   r;   r<   r     s   
r   c                 C  s   t | tr	|  S | S r0   )r1   r   rC  r   r;   r;   r<   rC    s   
rC  c                  O     t | ddi|S Nr   T)r   r   r   r;   r;   r<   r        r   c                 O     t | g|R ddi|S r  )r   )r   r   r   r;   r;   r<   r        r   c                 O  r  r  )r   )r   r   r   r;   r;   r<   r     r  r   c                 K  s   t | |fddi|S r  rG  )r   r   r   r;   r;   r<   r     s   r   c                  O  r  r  )r   r  r;   r;   r<   rI    r  rI  c                 C  r>   r0   )r5   )r   rq   r;   r;   r<   r?     r@   r?   )a
__future__r   collections.abcr2   r   r   r   	functoolsr   ri   r   typingZsympy.core.numbersr   Zsympy.core.relationalr   Z(sympy.functions.special.tensor_functionsr
   Zsympy.core.basicr   Zsympy.core.containersr   Zsympy.core.exprr   Zsympy.core.functionr   r   Zsympy.core.mulr   Zsympy.core.singletonr   Zsympy.core.sortingr   Zsympy.core.symbolr   r   Zsympy.matrices.matrixbaser   Z#sympy.matrices.expressions.diagonalr   Z"sympy.matrices.expressions.matexprr   Z"sympy.matrices.expressions.specialr   Zsympy.tensor.array.arrayopr   r   r   r   Z#sympy.tensor.array.dense_ndim_arrayr   Zsympy.tensor.array.ndim_arrayr   Zsympy.tensor.indexedr    r!   r"   Z$sympy.tensor.array.expressions.utilsr#   r$   r%   r&   r'   r(   r   r*   Z sympy.combinatorics.permutationsr+   Zsympy.core.sympifyr-   r.   rE   r5   r   r   r   r   r   r   r   r  r   r  r  r  r  r   r   rX  r   rC  r   r   r   r   rI  r?   r;   r;   r;   r<   <module>   s     5/Z;  Y Q)    ?  