o
    ٷi,                    @  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;   d/home/ubuntu/.local/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   
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;   r[   rS   r;   r<   
<listcomp>N       z+ArraySymbol.as_explicit.<locals>.<listcomp>c                 S     g | ]}t |qS r;   ranger\   jr;   r;   r<   ra   N   rb   )allr/   
ValueError	itertoolsproductr   reshape)r9   datar;   rS   r<   as_explicitK   s   $zArraySymbol.as_explicitN)r/   rF   rG   rH   )
rA   rB   rC   __doc__	_iterablerK   propertyrT   r/   rn   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;   r[   r;   r;   r<   r^   o       zshape contains negative values)rr   hasattr
IndexErrorlenr/   anyzipri   )rL   rT   rs   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<   rs   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]   rg   r;   r;   r<   r^          z0ArrayElement._eval_derivative.<locals>.<genexpr>)
r1   r5   r   ZeroOnerT   r   fromiterr{   rs   )r9   rt   r;   r;   r<   _eval_derivativez   s   
zArrayElement._eval_derivativeN)rA   rB   rC   ro   	_diff_wrt	is_symbolis_commutativerK   classmethodr6   rq   rT   rs   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   )ry   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   r[   r;   r;   r<   r^      r_   z(ZeroArray.as_explicit.<locals>.<genexpr>/Cannot return explicit form for symbolic shape.)rh   r/   ri   r   zerosrS   r;   r;   r<   rn      s   zZeroArray.as_explicitc                 C     t jS r0   )r   r   r8   r;   r;   r<   r7         zZeroArray._getN	rA   rB   rC   ro   rK   rq   r/   rn   r7   r;   r;   r;   r<   r          
r   c                   @  r   )OneArrayz!
    Symbolic array of ones.
    c                 G  r   rP   )ry   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   r[   r;   r;   r<   r^      r_   z'OneArray.as_explicit.<locals>.<genexpr>r   c                 S  s   g | ]}t jqS r;   r   r   r[   r;   r;   r<   ra          z(OneArray.as_explicit.<locals>.<listcomp>)	rh   r/   ri   r   re   r   operatormulrl   rS   r;   r;   r<   rn      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<   ra          z._CodegenArrayAbstract.doit.<locals>.<listcomp>)getfuncargs_canonicalize)r9   r   r   r;   r   r<   r      s   z_CodegenArrayAbstract.doitN)rA   rB   rC   rq   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  rc   r;   r,   r   r;   r;   r<   ra      rb   z.ArrayTensorProduct.__new__.<locals>.<listcomp>canonicalizeFc                 S  rc   r;   get_rankr   r;   r;   r<   ra      rb   c                 S  rc   r;   	get_shaper[   r;   r;   r<   ra      rb   c                 s      | ]}|d u V  qd S r0   r;   r[   r;   r;   r<   r^          z-ArrayTensorProduct.__new__.<locals>.<genexpr>c                 s  s    | ]
}|D ]}|V  qqd S r0   r;   r}   r;   r;   r<   r^      r~   )popr   rK   r   rz   r   rr   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  rc   r;   r   r   r;   r;   r<   ra     rb   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<   ra          z?ArrayTensorProduct._canonicalize.<locals>.<listcomp>.<listcomp>r;   rf   r   r;   r<   ra     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  rc   r;   r   r[   r;   r;   r<   ra     rb   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<   ra        & c                 S      g | ]}t |tr|jn|qS r;   )r1   r   exprr   r;   r;   r<   ra     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^     rv   >ArrayTensorProduct._canonicalize.<locals>.<listcomp>.<genexpr>)contraction_indicesrr   r\   r   rg   r   r]   r<   ra        4 c                 S  r   r;   )r1   ArrayDiagonalr   r;   r;   r<   r   "  r   c                 S  rc   r;   r   r   r;   r;   r<   ra   &  rb   c                      g | ]}  | qS r;   r;   rf   r   r;   r<   ra   ,      c                   r   r;   r;   rf   r   r;   r<   ra   -  r   c                   r   r;   r;   rf   r   r;   r<   ra   /  r   c                 S  r   r;   )r1   r   r   r   r;   r;   r<   ra   1  r   c                 S  r   r;   )r1   r   r   r   r   r;   r;   r<   ra   2  r   c                   r   )c                 3  r   r0   r;   r   )cumulative_ranks2r]   r;   r<   r^   4  rv   r   )diagonal_indicesrr   r   )r   r   r<   ra   4  r   r   F)r   _flatten	enumerater1   PermuteDimsextendpermutationcyclic_formr   _permute_dims_array_tensor_productr*   r   ry   rz   r   r   addr   listr   items_array_contractionr   r   r   re   _array_diagonalr+   r   )r9   r   permutation_cyclesr   r   contractionstpr   	diagonalsinverse_permutation	last_permi1i2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<   ra   ;  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 rn   rw   rn   r   r;   r;   r<   ra   ?     " z2ArrayTensorProduct.as_explicit.<locals>.<listcomp>)r   r   rS   r;   r;   r<   rn   >  s   zArrayTensorProduct.as_explicitN)	rA   rB   rC   ro   rK   r   r   r   rn   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  rc   r;   r,   r   r;   r;   r<   ra   H  rb   z$ArrayAdd.__new__.<locals>.<listcomp>c                 S  rc   r;   r   r   r;   r;   r<   ra   I  rb   rW   z!summing arrays of different ranksc                 S     g | ]}|j qS r;   r/   r   r;   r;   r<   ra   M  r   c                 S  s   h | ]}|d ur|qS r0   r;   r[   r;   r;   r<   	<setcomp>N  r   z#ArrayAdd.__new__.<locals>.<setcomp>zmismatching shapes in additionr   Fc                 s  r   r0   r;   r[   r;   r;   r<   r^   U  r   z#ArrayAdd.__new__.<locals>.<genexpr>r   )r   setry   ri   r   r   rK   r   rz   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  rc   r;   r   r   r;   r;   r<   ra   c  rb   z*ArrayAdd._canonicalize.<locals>.<listcomp>c                 S  s   g | ]}t |ttfs|qS r;   r   r   r;   r;   r<   ra   d      r   c                 s  s    | ]	}|d u r|V  qd S r0   r;   r[   r;   r;   r<   r^   f  rv   z)ArrayAdd._canonicalize.<locals>.<genexpr>zIcannot handle addition of ZeroMatrix/ZeroArray and undefined shape objectrW   r   F)r   _flatten_argsry   rz   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<   ra   z  r   z(ArrayAdd.as_explicit.<locals>.<listcomp>)r   r   r   r   rS   r;   r;   r<   rn   w  s   zArrayAdd.as_explicitN)	rA   rB   rC   ro   rK   r   r   r   rn   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;   r[   r   r/   r;   r<   r^     rv   z&PermuteDims.__new__.<locals>.<genexpr>)sympy.combinatoricsr*   r-   r   _get_permutation_from_argumentssizeri   r   r   rK   r   r   r   rr   re   ry   r   )rL   r   r   index_order_oldindex_order_newr   r*   	expr_rank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   r[   r   r;   r<   ra         z-PermuteDims._canonicalize.<locals>.<listcomp>F)r   )r   r   r1   r   r   '_PermuteDims_denestarg_ArrayContractionr   )_PermuteDims_denestarg_ArrayTensorProductr   r   
array_formsortedr   )r9   r   subexpr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;   r[   )cumulperm_image_formr;   r<   ra        $ zIPermuteDims._PermuteDims_denestarg_ArrayTensorProduct.<locals>.<listcomp>c                 S  s   g | ]
\}}|t |fqS r;   )r
  )r\   r]   compr;   r;   r<   ra     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;   r[   r;   r;   r<   ra   
  rb   c                   r`   r;   r;   r[   r  r;   r<   ra     rb   c                   r`   r;   r;   r[   )perm_image_form_in_componentsr;   r<   ra     rb   c                 S     g | ]	}|D ]}|qqS r;   r;   r}   r;   r;   r<   ra         )r+   r	  r   r   r   r   re   ry   r   sortr*   r   )rL   r   r   psperm_args_image_formargs_sorted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  rc   r;   r   r   r;   r;   r<   ra     rb   zGPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<listcomp>c                 S  r  r;   r;   r}   r;   r;   r<   ra     r  r   rW   c                   s*   g | ]\}}t t |  |d   qS r  r   re   r\   r]   er  r;   r<   ra   .     * r   c                      g | ]} fd d|D qS )c                   s   g | ]
}|d ur |qS r0   r;   rf   r   r;   r<   ra   1  r   zRPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<listcomp>.<listcomp>r;   r[   r,  r;   r<   ra   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;   r[   r;   r;   r<   ra   9  rb   c                   r`   r;   r;   r[   index_blocksr;   r<   ra   ;  rb   c                 S  r  r;   r;   r}   r;   r;   r<   ra   <  r  c                   r`   r;   r;   r[   r  r;   r<   ra   =  rb   c                   "   g | ]}t  fd d|D qS )c                 3      | ]} | V  qd S r0   r;   rf   new_index_perm_array_formr;   r<   r^   >  r   zQPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<listcomp>.<genexpr>rr   r[   r1  r;   r<   ra   >  r   c                 S  r  r;   r;   r}   r;   r;   r<   ra   @  r  c                   r`   r;   r;   r   )permutation_array_blocks_upr;   r<   ra   @  rb   )r1   r   r   r   r   r   r   r   r+   r	  re   ry   r   r   r   _push_indices_upr   r   r   r*   )rL   r   r   r   r   contraction_indices_flat
image_formcounterr]   currentrg   index_blocks_upindex_blocks_up_permutedsorting_keysnew_perm_image_formnew_index_blocksr   new_contraction_indicesnew_exprr%  r;   )r   r  r.  r   r2  r4  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;   )re   r   )r\   r]   r   rg   r  r;   r<   ra   F     ( z:PermuteDims._check_permutation_mapping.<locals>.<listcomp>c                   s   g | ]} |qS r;   r;   r[   r   r;   r<   ra   G  rb   r   c                   s   g | ]}|t   qS r;   minrf   )current_indicesr;   r<   ra   V  r   c                   s   h | ]} |  qS r;   r;   rf   )	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;   rf   )cumulative_subranksr]   r%  r;   r<   ra     r   zEPermuteDims._check_permutation_mapping.<locals>.<listcomp>.<listcomp>rd   )r\   r(  )rG  r%  r   r<   ra     r*  c                   r`   r;   r;   r[   )r   r;   r<   ra     rb   c                   r`   r;   r;   r[   )permutation_blocksr;   r<   ra     rb   c                 S  r  r;   r;   r}   r;   r;   r<   ra     r  )r   r   r   re   r   r   r   r   r   ry   r
  r   r*   r   r   nextiterpopitemr   r   )rL   r   r   r   permuted_indicesarg_candidate_indexinserted_arg_cand_indicesr]   idxarg_candidate_ranklocal_current_indicesr   args_positionsmapsrt   elemlinescurrent_liner   vliner(  new_permutation_blocksnew_permutation2r;   )rG  rE  r   rF  r   r%  r   rH  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  rc   r;   rC  r[   r;   r;   r<   ra     rb   zAPermuteDims._check_if_there_are_closed_cycles.<locals>.<listcomp>c                 S  rc   r;   maxr[   r;   r;   r<   ra     rb   TrW   c                      g | ]}|   qS r;   r;   r   rG  rg   r;   r<   ra     r   F)r   )r   r   r   r   r   r   re   ry   r   r*   r   r   r   )rL   r   r   r   r   r   
cyclic_min
cyclic_max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;   rf   newpermutationr;   r<   r^     r   z;PermuteDims._nest_permutation.<locals>.<listcomp>.<genexpr>r3  r[   rj  r;   r<   ra     r   z1PermuteDims._nest_permutation.<locals>.<listcomp>c                   s   g | ]}t | qS r;   r   r   rB  r;   r<   ra     r  )r1   r   r   re  r   r   '_convert_outer_indices_to_inner_indicesr*   r   r   r   r   r   
_array_addr   )rL   r   r   cycles	newcyclesnew_contr_indicesr;   )rk  r   r<   rf    s   


zPermuteDims._nest_permutationc                 C  s$   | j }t|dr| }t|| jS Nrn   )r   rw   rn   r   r   r9   r   r;   r;   r<   rn        
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)ri   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;   indexr[   r   r;   r<   ra     r  zBPermuteDims._get_permutation_from_index_orders.<locals>.<listcomp>)ry   r   ri   symmetric_difference)rL   r   r  rv  r   r;   rz  r<   ru    s   z.PermuteDims._get_permutation_from_index_orders)NNN)rA   rB   rC   ro   rK   r   rq   r   r   r   r  r  r[  re  rh  rf  rn   r   ru  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
  r[   r;   r;   r<   ra     r   z)ArrayDiagonal.__new__.<locals>.<listcomp>r   Fr   )r-   r   r   	_validate_get_positions_shapery   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  ry   r[   r;   r;   r<   ra     r   z/ArrayDiagonal._canonicalize.<locals>.<listcomp>r   c                 S  s&   i | ]\}}t |d kr|d |qS rW   r   r  r'  r;   r;   r<   r   	  r   z/ArrayDiagonal._canonicalize.<locals>.<dictcomp>c                 S  s"   i | ]\}}t |d kr||qS r  r  r'  r;   r;   r<   r   
  r   c                 S  s   g | ]
}t |d kr|qS r  r  r[   r;   r;   r<   ra     r   rW   r   F)r   r   ry   r   r   r   _push_indices_downr   re   r   r1   r   intr+   r   r   r   _ArrayDiagonal_denest_ArrayAdd#_ArrayDiagonal_denest_ArrayDiagonalr   !_ArrayDiagonal_denest_PermuteDimsr   r   r}  r/   r   )r9   r   r   trivial_diagstrivial_posdiag_posdiagonal_indices_shortrank1rank2rank3inv_permutationcounter1indices_downr]   r   r  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   r  rf   r   r;   r<   r^   0  rv   z*ArrayDiagonal._validate.<locals>.<genexpr>z%index is larger than expression shapec                   s   h | ]} | qS r;   r;   rf   r   r;   r<   r   2  rb   z*ArrayDiagonal._validate.<locals>.<setcomp>rW   z-diagonalizing indices of different dimensionsallow_trivial_diagsFz%need at least two axes to diagonalizezaxis index cannot be repeated)r   rz   ri   ry   r   r   )r   r   r   r]   r;   r   r<   r|  *  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;   rf   r;   r;   r<   r^   ;  s    zFArrayDiagonal._remove_trivial_dimensions.<locals>.<listcomp>.<genexpr>r3  r[   r   r;   r<   ra   ;     . 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;   r}   r;   r;   r<   ra   H  r  z*ArrayDiagonal._flatten.<locals>.<listcomp>c                 S     g | ]}d qS r  r;   r[   r;   r;   r<   ra   N      r   rW   c                 3  &    | ]}t  fd d|D V  qdS )c                 3      | ]	} | | V  qd S r0   r;   rf   shiftsr;   r<   r^   W  rv   z3ArrayDiagonal._flatten.<locals>.<genexpr>.<genexpr>Nr3  r[   r  r;   r<   r^   W     $ z)ArrayDiagonal._flatten.<locals>.<genexpr>)r   r   r   ry   re   rr   r   r   )r   outer_diagonal_indicesinner_diagonal_indices	all_inner
total_rank
inner_rank
outer_rankr8  pointerr]   r   r;   r  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<   ra   ]  r   z@ArrayDiagonal._ArrayDiagonal_denest_ArrayAdd.<locals>.<listcomp>rn  r   rL   r   r   r;   r  r<   r  [     z,ArrayDiagonal._ArrayDiagonal_denest_ArrayAddc                 G     | j |g|R  S r0   r   r  r;   r;   r<   r  _  r  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                   rw  r;   rB  rf   r  r;   r<   ra   e  r  zNArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<listcomp>.<listcomp>r;   r[   r  r;   r<   ra   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;   rf   r   r;   r<   r^   f  r   zMArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<listcomp>.<genexpr>rz   r\   r  r   r<   ra   f  r   c                   rw  r;   rB  r[   r  r;   r<   ra   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;   r[   )remapr;   r<   ra   i  rb   c                   s   g | ]}|  qS r;   r;   r[   )shiftr;   r<   ra   k  rb   )re   r   r   r
  ry   r   r   r   )	rL   r   r   back_diagonal_indicesnondiagback_nondiagnew_permutation1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   )ry   r~  r  rS   r;   r<   r  v  r   z<ArrayDiagonal._push_indices_down_nonstatic.<locals>.<lambda>r#   r9   rs   	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   r~  r1   r  rr   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   r  r  r  r;   r<   r    r   z2ArrayDiagonal._push_indices_down.<locals>.<lambda>r}  re   r#   rL   r   rs   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  rr   r   r  r  r;   r<   r    s
   (z1ArrayDiagonal._push_indices_up.<locals>.transformr  r  r;   r  r<   r5    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;   rf   r   r;   r<   r^     r   z?ArrayDiagonal._get_positions_shape.<locals>.<genexpr>.<genexpr>Nr  r\   shpr  r   r<   r^     s   0 z5ArrayDiagonal._get_positions_shape.<locals>.<genexpr>)r;   r;   c                 3  s     | ]}| |d   fV  qdS )r   Nr;   r[   r   r;   r<   r^     ru   )rr   r   r{   )
rL   r/   r   data1pos1shp1data2pos2shp2r  r;   )r   r/   r<   r}    s   z"ArrayDiagonal._get_positions_shapec                 C  *   | j }t|dr| }t|g| jR  S rr  )r   rw   rn   r   r   rs  r;   r;   r<   rn        
zArrayDiagonal.as_explicitN)r   r   )rA   rB   rC   ro   rK   r   staticmethodr|  r  rq   r   r   r   r   r  r  r  r  r  r  r5  r}  rn   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   r  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  fdiffr;   r;   r<   _get_function_fdiff  s   



z-ArrayElementwiseApplyFunc._get_function_fdiffc                 C  s$   | j }t|dr| }|| jS rr  )r   rw   rn   	applyfuncr  rs  r;   r;   r<   rn     rt  z%ArrayElementwiseApplyFunc.as_explicitN)
rA   rB   rC   rK   rq   r  r   r/   r  rn   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\   cindr   r;   r<   r^     r   z6ArrayContraction.__new__.<locals>.<dictcomp>.<genexpr>)rh   r  r   r   r<   r     rA  z,ArrayContraction.__new__.<locals>.<dictcomp>c                 3  s.    | ]\ }t  fd dD s|V  qdS )c                 3  r  r0   r;   rf   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   r  r   r%   _mappingre   r   _free_indices_to_positionr   r|  rr   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  )ry   r   r[   r  r;   r<   ra     s   0 z2ArrayContraction._canonicalize.<locals>.<listcomp>r   F)r   r   ry   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;   rf   r   r;   r<   r      r   z-ArrayContraction._validate.<locals>.<setcomp>rW   z+contracting indices of different dimensions)r   ry   ri   )r   r   r]   r;   r   r<   r|    s   zArrayContraction._validatec                 C  (   dd |D }|   t|}t||S )Nc                 S  r  r;   r;   r}   r;   r;   r<   ra   %  r  z7ArrayContraction._push_indices_down.<locals>.<listcomp>)r   r(   r#   rL   r   rs   flattened_contraction_indicesr  r;   r;   r<   r  #     
z#ArrayContraction._push_indices_downc                 C  r  )Nc                 S  r  r;   r;   r}   r;   r;   r<   ra   ,  r  z5ArrayContraction._push_indices_up.<locals>.<listcomp>)r   r&   r#   r  r;   r;   r<   r5  *  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;   r[   r;   r;   r<   ra   :  r  zBArrayContraction._lower_contraction_to_addends.<locals>.<listcomp>c                 3  s4    | ]}  |  ko d   k n  V  qdS )rW   Nr;   r   cumranksrg   r;   r<   r^   @  s   2 zAArrayContraction._lower_contraction_to_addends.<locals>.<genexpr>c                   r^  r;   r;   r   r  r;   r<   ra   A  r   c                   s   g | ]
}| v r
d ndqS r  r;   r[   )	backshiftr;   r<   ra   I  r   c                   s$   g | ]}t  fd d|D qS )c                 3  s    | ]	}| |  V  qd S r0   r;   rf   r  r;   r<   r^   J  rv   zLArrayContraction._lower_contraction_to_addends.<locals>.<listcomp>.<genexpr>)r   r   r[   r  r;   r<   ra   J  r  c                 S  s    g | ]\}}t |g|R  qS r;   r   )r\   r   contrr;   r;   r<   ra   K  s    )r1   r   r   r   r   r   r   r   r   re   ry   rh   r   updater   r   r{   )	rL   r   r   r   contraction_indices_remainingcontraction_indices_argscontraction_groupr  rg  r;   )r  r  rg   r  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\   lilindlother_arg_absr;   r<   r^     s   " z?ArrayContraction.split_multiple_contractions.<locals>.<genexpr>Nr   )_EditArrayContractionr   r   ry   get_mapping_for_indexr   r/   args_with_indr  get_absolute_rangerz   r   r   rs   get_new_contraction_indexry  insert_after_ArgEr   to_array_contraction)r9   editorr   onearray_insertlinksr  current_dimensionnot_vectorsvectorsarg_indrel_indr   matabs_arg_startabs_arg_endother_arg_posrW  vectors_to_loopfirst_not_vector	new_index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   )rg   r;   r<   ra     r   zDArrayContraction.flatten_contraction_of_diagonal.<locals>.<listcomp>c                 S  r  r;   r;   )r\   r   r  r;   r;   r<   ra     r  c                   s   g | ]}| vr|qS r;   r;   r   )diagonal_withr;   r<   ra     r   )r1   r   r   r  r   r   r   r   r   r
  r   r5  r   r   )r9   contraction_downr?  r   r]   r  r;   )r  rg   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;   r}   r;   r;   r<   ra     r  zFArrayContraction._get_free_indices_to_position_map.<locals>.<listcomp>r   rW   r;   )free_indicesr   r  r  r8  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;   r}   r;   r;   r<   ra     r  z6ArrayContraction._get_index_shifts.<locals>.<listcomp>c                 S  r  r  r;   r[   r;   r;   r<   ra     r  r   rW   )r   r   r   ry   re   )
r   inner_contraction_indicesr  r  r  r  r  r8  r  r]   r;   r;   r<   _get_index_shifts  s"   
z"ArrayContraction._get_index_shiftsc                   s$   t |  t fdd|D }|S )Nc                 3  r  )c                 3  r  r0   r;   rf   r  r;   r<   r^     rv   zUArrayContraction._convert_outer_indices_to_inner_indices.<locals>.<genexpr>.<genexpr>Nr3  r[   r  r;   r<   r^     r  zKArrayContraction._convert_outer_indices_to_inner_indices.<locals>.<genexpr>)r   r#  rr   )r   outer_contraction_indicesr;   r  r<   rm    s   
z8ArrayContraction._convert_outer_indices_to_inner_indicesc                 G  s2   | j }tj| g|R  }|| }t| jg|R  S r0   )r   r   rm  r   r   )r   r$  r"  r   r;   r;   r<   r     s   zArrayContraction._flattenc                 G  r  r0   r  rL   r   r   r;   r;   r<   r    r  z:ArrayContraction._ArrayContraction_denest_ArrayContractionc                   s.   dd |D   fddt |jD }t| S )Nc                 S  r  r;   r;   r}   r;   r;   r<   ra     r  zGArrayContraction._ArrayContraction_denest_ZeroArray.<locals>.<listcomp>c                   s   g | ]
\}}| vr|qS r;   r;   r'  r6  r;   r<   ra     r   )r   r/   r   )rL   r   r   r/   r;   r&  r<   r    s   z3ArrayContraction._ArrayContraction_denest_ZeroArrayc                   r  )Nc                   r  r;   r  r[   r  r;   r<   ra     r   zFArrayContraction._ArrayContraction_denest_ArrayAdd.<locals>.<listcomp>r  r%  r;   r  r<   r    r  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  ri  r0   r;   rf   rB  r;   r<   r^     r   SArrayContraction._ArrayContraction_denest_PermuteDims.<locals>.<listcomp>.<genexpr>r3  r[   rB  r;   r<   ra     r   zIArrayContraction._ArrayContraction_denest_PermuteDims.<locals>.<listcomp>c                   r  )c                 3  r  r0   r;   rf   r   r;   r<   r^     r   r'  r  r  )r?  r   r<   ra     r   )r   r	  r5  r   r   r   r*   )rL   r   r   r  	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   rr   r   r\   rg   r   r;   r;   r<   ra   *  r  zVArrayContraction._ArrayContraction_denest_ArrayDiagonal.<locals>.<listcomp>.<listcomp>r;   r[   r;   r;   r<   ra   *  r  zKArrayContraction._ArrayContraction_denest_ArrayDiagonal.<locals>.<listcomp>c                 3      | ]}| v V  qd S r0   r;   r[   diag_indgrpr;   r<   r^   1  r   zJArrayContraction._ArrayContraction_denest_ArrayDiagonal.<locals>.<genexpr>c                 S  s   g | ]}|d ur|qS r0   r;   r[   r;   r;   r<   ra   6  r   )r   r   r  r   r   r   rz   r   r   r
  r   r   r5  r   r   )rL   r   r   r   down_contraction_indicesr?  contr_indgrpr   rg   new_diagonal_indices_down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&  r[   r)  r;   r<   ra   B  r   z@ArrayContraction._sort_fully_contracted_args.<locals>.<listcomp>c                 S  s   h | ]	}|D ]}|qqS r;   r;   r}   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;   rf   r&  r;   r<   r^   D  r   JArrayContraction._sort_fully_contracted_args.<locals>.<listcomp>.<genexpr>rW   )rh   re   r   )r6  r  r;   r<   ra   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  r[   r  r;   r<   ra   F  r  c                   s   g | ]} | D ]}|qqS r;   r;   r}   r-  r;   r<   ra   G  r   c                   r/  )c                 3  r0  r0   r;   rf   index_permutation_array_formr;   r<   r^   I  r   r2  r3  r[   r4  r;   r<   ra   I  r   )r/   r   r   r   re   ry   r   r   r
  r+   r$   r   )rL   r   r   new_posr   new_index_blocks_flatr?  r;   )r6  r  r   r3  r.  r5  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;   rf   mappingr;   r<   ra   j  rb   zGArrayContraction._get_contraction_tuples.<locals>.<listcomp>.<listcomp>r;   r[   r8  r;   r<   ra   j  r   z<ArrayContraction._get_contraction_tuples.<locals>.<listcomp>)r  r   rS   r;   r8  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  ru   zYArrayContraction._contraction_tuples_to_contraction_indices.<locals>.<listcomp>.<genexpr>r3  r[   r   r;   r<   ra   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   )_free_indicesrS   r;   r;   r<   r  s  r  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  r  rV   r  rS   r;   r;   r<   r     r  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   re   )r9   r   r   r9  r8  r]   r  rg   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;   rx  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<   ra     r   zAArrayContraction.sort_args_by_name.<locals>.<listcomp>.<listcomp>r;   r[   rA  r;   r<   ra     r   z6ArrayContraction.sort_args_by_name.<locals>.<listcomp>)r   r1   r   r   r
  r   r{   r:  r   r<  r   )r9   r   r   sorted_datar#  r;  c_tprq  r;   )r@  rB  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   dlinksr;   r;   r<   r'     s   )z'ArrayContraction._get_contraction_linksc                 C  r  rr  )r   rw   rn   r   r   rs  r;   r;   r<   rn     r  zArrayContraction.as_explicitN)r   r)  )%rA   rB   rC   ro   rK   r   r  r  r  r|  r   r  r5  r  r  r  r!  r#  rm  r   r  r  r  r  r  r  r:  r<  rq   r  r  r   r   r?  rE  r'   rn   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/   ri   r   rK   rr   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   )rH  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   rl   r/   rG  )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 )Nrn   r   )Array)
r   rw   rn   r1   r   sympyrI  r   rl   r/   )r9   eerI  r;   r;   r<   rn     s   



zReshape.as_explicitN)
rA   rB   rC   ro   rK   rq   r/   r   r   rn   r;   r;   r;   r<   rG    s    

	rG  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]rs   Nlist[int | None] | Nonec                 C  s4   || _ |d u rdd tt|D | _d S || _d S )Nc                 S  r  r0   r;   r[   r;   r;   r<   ra   <  r  z"_ArgE.__init__.<locals>.<listcomp>)r  re   r   rs   )r9   r  rs   r;   r;   r<   __init__9  s   
z_ArgE.__init__c                 C     d| j | jf S )Nz_ArgE(%s, %s))r  rs   rS   r;   r;   r<   __str__@     z_ArgE.__str__r0   )rs   rL  )rA   rB   rC   ro   rD   rM  rO  __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   rS  )r9   r   rS  r;   r;   r<   rM  M  s   
z_IndPos.__init__c                 C  rN  )Nz_IndPos(%i, %i)rT  rS   r;   r;   r<   rO  Q  rP  z_IndPos.__str__c                 c  s    | j | jgE d H  d S r0   rT  rS   r;   r;   r<   __iter__V  s   z_IndPos.__iter__N)r   r  rS  r  )rA   rB   rC   ro   rM  rO  rQ  rU  r;   r;   r;   r<   rR  F  s    
rR  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  rc   r;   )r	  r   r;   r;   r<   ra     rb   z2_EditArrayContraction.__init__.<locals>.<listcomp>r   )r1   r   r%   r   r   r   r   r  r   r   r   r   r   r   rs   r  ry   number_of_contraction_indices_track_permutation)r9   rV  r9  r   r   diagonalizedr   r  r]   contraction_tuplerg   arg_posrel_posr(  r;   r;   r<   rM  i  sX   







z_EditArrayContraction.__init__r   r	  new_argc                 C  s"   | j |}| j |d | d S rV   )r  ry  insert)r9   r   r^  posr;   r;   r<   r    s   z"_EditArrayContraction.insert_afterc                 C  s   |  j d7  _ | j d S rV   )rX  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;   r[   r;   r;   r<   r     r  z9_EditArrayContraction.refresh_indices.<locals>.<dictcomp>c                   s   g | ]}  |d qS r0   )r   r[   updatesr;   r<   ra     r   z9_EditArrayContraction.refresh_indices.<locals>.<listcomp>)r  r  rs   r   r
  ry   rX  )r9   arg_with_indr]   r(  r;   ra  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  r[   r;   r;   r<   ra     r   z7_EditArrayContraction.merge_scalars.<locals>.<listcomp>)_a2m_tensor_product)r  ry   rs   r   remover   r   r	  3sympy.tensor.array.expressions.from_array_to_matrixrf  r  )r9   scalarsrc  r]   scalarrf  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;   r[   r;   r;   r<   ra     r  z>_EditArrayContraction.to_array_contraction.<locals>.<listcomp>c                 S  s    g | ]}|d u s|dk r|qS rP   r;   r[   r;   r;   r<   ra     r   c                 S  s    g | ]}t |d krt|qS r  )ry   rr   )r\   rW  r;   r;   r<   ra     r   c                 S  r   r;   re  r   r;   r;   r<   ra     r   c                 S  r  r;   r;   r}   r;   r;   r<   ra     r  )r   r   r   r  r  rs   r   r   r   ry   r+   valuesrk  rd  get_contraction_indicesr   r   r   rY  r   )r9   r8  diag_indicescount_index_freqrc  free_index_count	inv_perm1	inv_perm2donecounter4counter2r]   r   r   diag_indices_filteredr   r   r   expr2permutation2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;   r[   r;   r;   r<   ra     r  zA_EditArrayContraction.get_contraction_indices.<locals>.<listcomp>r   rW   )re   rX  r  rs   r   )r9   r   current_positionrc  rg   r;   r;   r<   rm    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)rX  ri   r   r  rs   r   rR  )r9   r   r  r]   rc  rg   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;   r[   r;   r;   r<   ra     r  zP_EditArrayContraction.get_contraction_indices_to_ind_rel_pos.<locals>.<listcomp>)re   rX  r   r  rs   r   rR  )r9   r   r]   rc  rg   r   r;   r;   r<   &get_contraction_indices_to_ind_rel_pos  s   z<_EditArrayContraction.get_contraction_indices_to_ind_rel_posry  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  rs   )r9   ry  r8  rc  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;   )rs   r[   rx  r;   r<   ra   /  r  z=_EditArrayContraction.get_args_with_index.<locals>.<listcomp>)r  )r9   ry  rg  r;   rx  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;   r[   r;   r;   r<   r   6  r   zC_EditArrayContraction.number_of_diagonal_indices.<locals>.<setcomp>)r   r  r  rs   ry   )r9   rm   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\  r[   r;   r;   r<   r^   I  ru   z@_EditArrayContraction.track_permutation_start.<locals>.<genexpr>c                   s   g | ]} | qS r;   r;   r[   max_indr;   r<   ra   J  rb   zA_EditArrayContraction.track_permutation_start.<locals>.<listcomp>)r  rs   r   r]  rY  )r9   r   	perm_diagr8  ru  rc  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  ry  rY  r   r   )r9   r  r  index_destination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;   r[   r;   r;   r<   ra   Z  r   zA_EditArrayContraction.get_absolute_free_range.<locals>.<listcomp>argument not foundr  ry   rs   rx   )r9   r   r8  rc  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   r8  rc  number_indicesr;   r;   r<   r  `  s   


z(_EditArrayContraction.get_absolute_rangeN)rV  rW  )r   r	  r^  r	  )rG   rz  )rG   r|  )rG   r}  )ry  r  rG   r  )ry  r  rG   r  )r  r	  r  r	  )r   r	  rG   r  )rA   rB   rC   ro   rM  r  r  rd  rk  r
  rm  r  r~  r  r  rq   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   ry   r/   r   r  r    r!   rw   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<   r    s   

r  c                 C  s   t | dr| jS dS )Nr/   r;   )rw   r/   r  r;   r;   r<   r     s   
r   c                 C  s   t | tr	|  S | S r0   )r1   r   rh  r  r;   r;   r<   rh    s   
rh  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  rl  )r   r   r   r;   r;   r<   r     s   r   c                  O  r  r  )r   r  r;   r;   r<   rn    r  rn  c                 C  r>   r0   )r5   )r   rs   r;   r;   r<   r?     r@   r?   )a
__future__r   collections.abcr2   r   r   r   	functoolsr   rj   r   typingsympy.core.numbersr   sympy.core.relationalr   (sympy.functions.special.tensor_functionsr
   sympy.core.basicr   sympy.core.containersr   sympy.core.exprr   sympy.core.functionr   r   sympy.core.mulr   sympy.core.singletonr   sympy.core.sortingr   sympy.core.symbolr   r   sympy.matrices.matrixbaser   #sympy.matrices.expressions.diagonalr   "sympy.matrices.expressions.matexprr   "sympy.matrices.expressions.specialr   sympy.tensor.array.arrayopr   r   r   r   #sympy.tensor.array.dense_ndim_arrayr   sympy.tensor.array.ndim_arrayr   sympy.tensor.indexedr    r!   r"   $sympy.tensor.array.expressions.utilsr#   r$   r%   r&   r'   r(   r   r*    sympy.combinatorics.permutationsr+   sympy.core.sympifyr-   r.   rE   r5   r   r   r   r   r   r   r   r  r   rG  r	  rR  r  r   r   r  r   rh  r   r   r   r   rn  r?   r;   r;   r;   r<   <module>   s     5/Z;  Y Q)    ?  