o
    h,                    @   s  d dl Zd dlZd dlmZmZ d dlmZ d dlZd dlmZ d dl	m
Z
mZmZ d dl	Z	d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZmZ d dlmZ d dlmZ d dl m!Z! d dl"m#Z#m$Z$ d dl%m&Z& d dl'm(Z( d dl)m*Z* d dl+m,Z, d dl-m.Z.m/Z/m0Z0m1Z1 d dl2m3Z3 d dl4m5Z5 d dl6m7Z7m8Z8 d dl)m9Z9 d dl:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@ d dlAmBZB d dlCmDZD d dlEmFZF G dd deZGG d d! d!eGZHG d"d# d#eZIG d$d% d%eGZJG d&d' d'eGZKG d(d) d)eZLG d*d+ d+eLZMG d,d- d-eLZNG d.d/ d/eLZOG d0d1 d1eLZPG d2d3 d3eLZQG d4d5 d5eLZRG d6d7 d7eLZSG d8d9 d9ZTG d:d; d;ZUG d<d= d=ZVd>d? ZWd@dA ZXdBdC ZYdDdE ZZdFdG Z[dHdI Z\dJdK Z]dLdM Z^dNdO Z_dPdQ Z`dRdS ZadS )T    N)defaultdictCounter)reduce)
accumulate)OptionalListTuple)Integer)EqualityKroneckerDelta)Basic)r   )Expr)FunctionLambda)Mul)Sdefault_sort_key)DummySymbol)
MatrixBase)diagonalize_vector)
MatrixExpr)
ZeroMatrix)permutedimstensorcontractiontensordiagonaltensorproduct)ImmutableDenseNDimArray)	NDimArray)IndexedIndexedBase)MatrixElement)$_apply_recursively_over_nested_lists_sort_contraction_indices_get_mapping_from_subranks*_build_push_indices_up_func_transformation_get_contraction_links,_build_push_indices_down_func_transformationPermutation)
_af_invert_sympifyc                   @   s.   e Zd ZU eedf ed< dd Zdd ZdS )
_ArrayExpr.shapec                 C   s*   t |tjjs
|f}t| | | |S N)
isinstancecollectionsabcIterableArrayElement_check_shape_getselfitem r<   d/var/www/vscode/kcb/lib/python3.10/site-packages/sympy/tensor/array/expressions/array_expressions.py__getitem__*   s   
z_ArrayExpr.__getitem__c                 C   
   t | |S r1   )_get_array_element_or_slicer9   r<   r<   r=   r8   0      
z_ArrayExpr._getN)__name__
__module____qualname__tTupler   __annotations__r>   r8   r<   r<   r<   r=   r/   '   s   
 r/   c                   @   sD   e Zd ZdZdejdd fddZedd Zedd	 Z	d
d Z
dS )ArraySymbolz1
    Symbol representing an array expression
    r0   returnc                 C   s2   t |tr	t|}ttt| }t| ||}|S r1   )r2   strr   r   mapr.   r   __new__)clssymbolr0   objr<   r<   r=   rK   9   s
   
zArraySymbol.__new__c                 C   
   | j d S Nr   _argsr:   r<   r<   r=   nameA      
zArraySymbol.namec                 C   rO   N   rQ   rS   r<   r<   r=   r0   E   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 r1   
is_Integer.0ir<   r<   r=   	<genexpr>J       z*ArraySymbol.as_explicit.<locals>.<genexpr>z1cannot express explicit array with symbolic shapec                       g | ]} | qS r<   r<   r[   rS   r<   r=   
<listcomp>L       z+ArraySymbol.as_explicit.<locals>.<listcomp>c                 S      g | ]}t |qS r<   ranger\   jr<   r<   r=   ra   L   rb   )allr0   
ValueError	itertoolsproductr   reshape)r:   datar<   rS   r=   as_explicitI   s   $zArraySymbol.as_explicitN)rB   rC   rD   __doc__typingr5   rK   propertyrT   r0   rn   r<   r<   r<   r=   rG   4   s    

rG   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 )r6   z!
    An element of an array.
    Tc                 C   sX   t |tr	t|}t|}t |tjjs|f}tt|}| || t	
| ||}|S r1   )r2   rI   r   r.   r3   r4   r5   tupler7   r   rK   )rL   rT   indicesrN   r<   r<   r=   rK   Y   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 )Nr0   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^   k       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^   m       zshape contains negative values)rr   hasattr
IndexErrorlenr0   anyzipri   )rL   rT   rs   index_errorr<   r<   r=   r7   d   s   
zArrayElement._check_shapec                 C   rO   rP   rQ   rS   r<   r<   r=   rT   p   rU   zArrayElement.namec                 C   rO   rV   rQ   rS   r<   r<   r=   rs   t   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 r1   r   r\   r]   rg   r<   r<   r=   r^          z0ArrayElement._eval_derivative.<locals>.<genexpr>)
r2   r6   r   ZeroOnerT   r   fromiterr{   rs   )r:   rt   r<   r<   r=   _eval_derivativex   s   
zArrayElement._eval_derivativeN)rB   rC   rD   ro   	_diff_wrt	is_symbolis_commutativerK   classmethodr7   rq   rT   rs   r   r<   r<   r<   r=   r6   P   s    


r6   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   r0   rN   r<   r<   r=   rK      
   
zZeroArray.__new__c                 C      | j S r1   rQ   rS   r<   r<   r=   r0         zZeroArray.shapec                 C   s(   t dd | jD stdtj| j S )Nc                 s   rX   r1   rY   r[   r<   r<   r=   r^      r_   z(ZeroArray.as_explicit.<locals>.<genexpr>/Cannot return explicit form for symbolic shape.)rh   r0   ri   r   zerosrS   r<   r<   r=   rn      s   zZeroArray.as_explicitc                 C      t jS r1   )r   r   r9   r<   r<   r=   r8         zZeroArray._getN	rB   rC   rD   ro   rK   rq   r0   rn   r8   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   r1   rQ   rS   r<   r<   r=   r0      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   r1   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   r0   ri   r   re   r   operatormulrl   rS   r<   r<   r=   rn      s   (zOneArray.as_explicitc                 C   r   r1   r   r9   r<   r<   r=   r8      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   r1   _shaperS   r<   r<   r=   r0      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)r:   r   r   r<   r   r=   r      s   z_CodegenArrayAbstract.doitN)rB   rC   rD   rq   r   r   r0   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 r1   r<   r[   r<   r<   r=   r^          z-ArrayTensorProduct.__new__.<locals>.<genexpr>c                 s   s    | ]
}|D ]}|V  qqd S r1   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 r1   )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 r1   r2   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<   )r2   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<   )r2   r   _get_subrankr   r   r<   r<   r=   ra        & c                 S       g | ]}t |tr|jn|qS r<   )r2   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 r1   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<   )r2   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<   )r2   r   r   r   r<   r<   r=   ra   /  r   c                 S   r   r<   )r2   r   r   r   r   r<   r<   r=   ra   0  r   c                    r   )c                 3   r   r1   r<   r   )cumulative_ranks2r]   r<   r=   r^   2  rv   r   )diagonal_indicesrr   r   )r   r   r=   ra   2  r   r   F)r   _flatten	enumerater2   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   )r:   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<   )r2   r   )r\   r   r]   rL   r<   r=   ra   9  s   , z/ArrayTensorProduct._flatten.<locals>.<listcomp>r<   )rL   r   r<   r   r=   r   7  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)	rB   rC   rD   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   F  rb   z$ArrayAdd.__new__.<locals>.<listcomp>c                 S   rc   r<   r   r   r<   r<   r=   ra   G  rb   rW   z!summing arrays of different ranksc                 S      g | ]}|j qS r<   r0   r   r<   r<   r=   ra   K  r   c                 S   s   h | ]}|d ur|qS r1   r<   r[   r<   r<   r=   	<setcomp>L  r   z#ArrayAdd.__new__.<locals>.<setcomp>zmismatching shapes in additionr   Fc                 s   r   r1   r<   r[   r<   r<   r=   r^   S  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   E  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   a  rb   z*ArrayAdd._canonicalize.<locals>.<listcomp>c                 S   s   g | ]}t |ttfs|qS r<   r   r   r<   r<   r=   ra   b      r   c                 s   s    | ]	}|d u r|V  qd S r1   r<   r[   r<   r<   r=   r^   d  rv   z)ArrayAdd._canonicalize.<locals>.<genexpr>zIcannot handle addition of ZeroMatrix/ZeroArray and undefined shape objectrW   r   F)r   _flatten_argsry   rz   NotImplementedErrorr   r   )r:   r   r   r<   r<   r=   r   [  s   
zArrayAdd._canonicalizec                 C   s4   g }|D ]}t |tr||j q|| q|S r1   )r2   r   r   r   append)rL   r   new_argsr   r<   r<   r=   r   k  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   x  r   z(ArrayAdd.as_explicit.<locals>.<listcomp>)r   r   r   r   rS   r<   r<   r=   rn   u  s   zArrayAdd.as_explicitN)	rB   rC   rD   ro   rK   r   r   r   rn   r<   r<   r<   r=   r   @  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 r1   r<   r[   r   r0   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   r2   r   r   '_PermuteDims_denestarg_ArrayContractionr   )_PermuteDims_denestarg_ArrayTensorProductr   r   
array_formsortedr   )r:   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
|D ])\}}	g }
t| |d  D ]}||v rXqQ|
||  |d7 }qQ|
 q@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 r1   r<   rf   r   r<   r=   ra   /  r   zRPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<listcomp>.<listcomp>r<   r[   r,  r<   r=   ra   /  r   c                 S   r  rV   r<   r  r<   r<   r=   r  4  r  zEPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<lambda>r  c                 S   r  r  r<   r[   r<   r<   r=   ra   7  rb   c                    r`   r<   r<   r[   index_blocksr<   r=   ra   9  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 r1   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   )r2   r   r   r   r   r   r   r   r,   r	  r   re   r   r   _push_indices_upr   r   r   r+   )rL   r   r   r   r   contraction_indices_flat
image_formcounterr]   r(  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   D     ( z:PermuteDims._check_permutation_mapping.<locals>.<listcomp>c                    s   g | ]} |qS r<   r<   r[   r   r<   r=   ra   E  rb   r   c                    s   g | ]}|t   qS r<   minrf   )current_indicesr<   r=   ra   T  r   c                    s   h | ]} |  qS r<   r<   rf   )	index2argr%  r<   r=   r   b  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_mappingA  sz   




&


z&PermuteDims._check_permutation_mappingc                    s   t |j}|j}|j}dgt t|  dd |D }dd |D }g }t|D ]F\}	}
d}tt d D ].||	   krd||	  d  k rdt| t	 fdd||	 D g|< d} nq6|rn|
||	  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   )r:   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 r1   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  )r2   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   r:   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)rB   rC   rD   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ef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   r0   	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   r2   r	   intr,   r   r   r   _ArrayDiagonal_denest_ArrayAdd#_ArrayDiagonal_denest_ArrayDiagonalr   !_ArrayDiagonal_denest_PermuteDimsr   r   r}  r0   r   )r:   r   r   trivial_diagstrivial_posdiag_posdiagonal_indices_shortrank1rank2rank3inv_permutationcounter1indices_downr]   r   r  r0   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 r1   r  rf   r   r<   r=   r^   .  rv   z*ArrayDiagonal._validate.<locals>.<genexpr>z%index is larger than expression shapec                    s   h | ]} | qS r<   r<   rf   r   r<   r=   r   0  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 r1   r<   rf   r<   r<   r=   r^   9  s    zFArrayDiagonal._remove_trivial_dimensions.<locals>.<listcomp>.<genexpr>r3  r[   r   r<   r=   ra   9     . z<ArrayDiagonal._remove_trivial_dimensions.<locals>.<listcomp>r<   )r0   r   r<   r   r=   _remove_trivial_dimensions7     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   ?     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   F  r  z*ArrayDiagonal._flatten.<locals>.<listcomp>c                 S      g | ]}d qS r  r<   r[   r<   r<   r=   ra   L      r   rW   c                 3   &    | ]}t  fd d|D V  qdS )c                 3       | ]	} | | V  qd S r1   r<   rf   shiftsr<   r=   r^   U  rv   z3ArrayDiagonal._flatten.<locals>.<genexpr>.<genexpr>Nr3  r[   r  r<   r=   r^   U     $ 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   C  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  Y     z,ArrayDiagonal._ArrayDiagonal_denest_ArrayAddc                 G      | j |g|R  S r1   r   r  r<   r<   r=   r  ]  r  z1ArrayDiagonal._ArrayDiagonal_denest_ArrayDiagonalr   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   c  r  zNArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<listcomp>.<listcomp>r<   r[   r  r<   r=   ra   c  r   zCArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<listcomp>c                    &   g | ] t  fd dD s qS )c                 3       | ]} |v V  qd S r1   r<   rf   r   r<   r=   r^   d  r   zMArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<listcomp>.<genexpr>rz   r\   r  r   r=   ra   d  r   c                    rw  r<   rB  r[   r  r<   r=   ra   e  r  c                 S   s   i | ]\}}||qS r<   r<   r'  r<   r<   r=   r   f  r  zCArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<dictcomp>c                    r`   r<   r<   r[   )remapr<   r=   ra   g  rb   c                    s   g | ]}|  qS r<   r<   r[   )shiftr<   r=   ra   i  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  a  s    z/ArrayDiagonal._ArrayDiagonal_denest_PermuteDimsc                        fdd}t ||S )Nc                    s   | t  jk r j|  S d S r1   )ry   r~  r  rS   r<   r=   r  t  r   z<ArrayDiagonal._push_indices_down_nonstatic.<locals>.<lambda>r$   r:   rs   	transformr<   rS   r=   _push_indices_down_nonstatics  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 r1   )r   r~  r2   r  rr   r  r]   r(  rS   r<   r=   r  y  s
   $z;ArrayDiagonal._push_indices_up_nonstatic.<locals>.transformr  r  r<   rS   r=   _push_indices_up_nonstaticw  s   
z(ArrayDiagonal._push_indices_up_nonstaticc                    *   |  t||\ } fdd}t||S )Nc                    s   | t  k r
 |  S d S r1   r  r  r  r<   r=   r    r   z2ArrayDiagonal._push_indices_down.<locals>.<lambda>r}  re   r$   rL   r   rs   rankr0   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 r1   )r   r2   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  r1   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   r0   r   data1pos1shp1data2pos2shp2r  r<   )r   r0   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)rB   rC   rD   ro   rK   r   staticmethodr|  r  rq   r   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)r2   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 r1   r   r0   rS   r<   r<   r=   r0     s   zArrayElementwiseApplyFunc.shapec                 C   s@   t d}| |}||}t|trt|}|S t||}|S r  )r   r  diffr2   r   typer   )r:   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)
rB   rC   rD   rK   rq   r  r   r0   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 r1   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  r1   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_positionr0   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   r2   r   )_ArrayContraction_denest_ArrayContractionr   r   "_ArrayContraction_denest_ZeroArrayr   $_ArrayContraction_denest_PermuteDimsr   _sort_fully_contracted_args_lower_contraction_to_addendsr   &_ArrayContraction_denest_ArrayDiagonalr   !_ArrayContraction_denest_ArrayAddr   )r:   r   r<   r  r=   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   r:   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   8  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   ?  r   c                    s   g | ]
}| v r
d ndqS r  r<   r[   )	backshiftr<   r=   ra   G  r   c                    s$   g | ]}t  fd d|D qS )c                 3   s    | ]	}| |  V  qd S r1   r<   rf   r  r<   r=   r^   H  rv   zLArrayContraction._lower_contraction_to_addends.<locals>.<listcomp>.<genexpr>)r   r   r[   r  r<   r=   ra   H  r  c                 S   s    g | ]\}}t |g|R  qS r<   r   )r\   r   contrr<   r<   r=   ra   I  s    )r2   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  /  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 r1   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   r0   args_with_indr  get_absolute_rangerz   r   r   rs   get_new_contraction_indexry  insert_after_ArgEr   to_array_contraction)r:   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_contractionsN  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   )r2   r   r   r  r   r   r   r   r   r
  r   r5  r   r   )r:   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  r1   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 r1   )r   r   rm  r   r   )r   r$  r"  r   r<   r<   r=   r     s   zArrayContraction._flattenc                 G   r  r1   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   r0   r   )rL   r   r   r0   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  r1   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  r1   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   r   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<   )r2   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 r1   r<   r[   diag_indgrpr<   r=   r^   /  r   zJArrayContraction._ArrayContraction_denest_ArrayDiagonal.<locals>.<genexpr>c                 S   s   g | ]}|d ur|qS r1   r<   r[   r<   r<   r=   ra   4  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   @  r   z@ArrayContraction._sort_fully_contracted_args.<locals>.<listcomp>c                 S   s   h | ]	}|D ]}|qqS r<   r<   r}   r<   r<   r=   r   A  r  z?ArrayContraction._sort_fully_contracted_args.<locals>.<setcomp>c              	      s8   g | ]\}}t  fd dt| |d  D qS )c                 3   r*  r1   r<   rf   r&  r<   r=   r^   B  r   JArrayContraction._sort_fully_contracted_args.<locals>.<listcomp>.<genexpr>rW   )rh   re   r   )r6  r  r<   r=   ra   B  s   8 c                    s   |  rdt  j|  fS dS )Nr   r  )r   r   r  )r   fully_contractedr<   r=   r  C  r   z>ArrayContraction._sort_fully_contracted_args.<locals>.<lambda>r  c                    r  r<   r  r[   r  r<   r=   ra   D  r  c                    s   g | ]} | D ]}|qqS r<   r<   r}   r-  r<   r=   ra   E  r   c                    r/  )c                 3   r0  r1   r<   rf   index_permutation_array_formr<   r=   r^   G  r   r1  r3  r[   r3  r<   r=   ra   G  r   )r0   r   r   r   re   ry   r   r   r
  r,   r%   r   )rL   r   r   new_posr   new_index_blocks_flatr?  r<   )r6  r  r   r2  r.  r4  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   h  rb   zGArrayContraction._get_contraction_tuples.<locals>.<listcomp>.<listcomp>r<   r[   r7  r<   r=   ra   h  r   z<ArrayContraction._get_contraction_tuples.<locals>.<listcomp>)r  r   rS   r<   r7  r=   _get_contraction_tuplesK  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 r1   r<   r)  r   r<   r=   r^   o  ru   zYArrayContraction._contraction_tuples_to_contraction_indices.<locals>.<listcomp>.<genexpr>r3  r[   r   r<   r=   ra   o  r   zOArrayContraction._contraction_tuples_to_contraction_indices.<locals>.<listcomp>)r   r   r   )r   contraction_tuplesr   r<   r   r=   *_contraction_tuples_to_contraction_indicesj  s   z;ArrayContraction._contraction_tuples_to_contraction_indicesc                 C   s   | j d d  S r1   )_free_indicesrS   r<   r<   r=   r  q  r  zArrayContraction.free_indicesc                 C   r   r1   )dictr  rS   r<   r<   r=   r  u  rU   z)ArrayContraction.free_indices_to_positionc                 C   rO   rP   r  rS   r<   r<   r=   r   y  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   r2   r   r   r   r   re   )r:   r   r   r8  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[   r@  r<   r=   ra     r   z6ArrayContraction.sort_args_by_name.<locals>.<listcomp>)r   r2   r   r   r
  r   r{   r9  r   r;  r   )r:   r   r   sorted_datar#  r:  c_tprq  r<   )r?  rA  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   )r:   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   )%rB   rC   rD   ro   rK   r   r  r  r  r|  r   r  r5  r  r  r  r!  r#  rm  r   r  r  r  r  r  r  r9  r;  rq   r  r  r   r   r>  rD  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.   r2   r   r
   r   r   r0   ri   r   rK   rr   r   _expr)rL   r   r0   rN   r<   r<   r=   rK     s   

zReshape.__new__c                 C   r   r1   r   rS   r<   r<   r=   r0     r   zReshape.shapec                 C   r   r1   )rG  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   r2   r   r    rl   r0   rF  )r:   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   r2   r   sympyrH  r   rl   r0   )r:   eerH  r<   r<   r=   rn     s   



zReshape.as_explicitN)
rB   rC   rD   ro   rK   rq   r0   r   r   rn   r<   r<   r<   r=   rF    s    

	rF  c                   @   sJ   e Zd ZU dZeee  ed< ddeeee   f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.
    rs   Nc                 C   s4   || _ |d u rdd tt|D | _d S || _d S )Nc                 S   r  r1   r<   r[   r<   r<   r=   ra   :  r  z"_ArgE.__init__.<locals>.<listcomp>)r  re   r   rs   )r:   r  rs   r<   r<   r=   __init__7  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__r1   )rB   rC   rD   ro   r   r   r  rF   rK  rM  __repr__r<   r<   r<   r=   r	  %  s   
 r	  c                   @   s6   e Zd ZdZdedef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   relc                 C   s   || _ || _d S r1   r   rQ  )r:   r   rQ  r<   r<   r=   rK  K  s   
z_IndPos.__init__c                 C   rL  )Nz_IndPos(%i, %i)rR  rS   r<   r<   r=   rM  O  rN  z_IndPos.__str__c                 c   s    | j | jgE d H  d S r1   rR  rS   r<   r<   r=   __iter__T  s   z_IndPos.__iter__N)	rB   rC   rD   ro   r  rK  rM  rO  rS  r<   r<   r<   r=   rP  D  s    rP  c                   @   s   e Zd ZdZdejeeef fddZ	de
de
fddZd	d
 Zdd Zdd Zdd Zdeee  fddZdee fddZdeee  fddZdedefddZdedee
 fddZedd Zdd  Zd!e
d"e
fd#d$Zde
dejeef fd%d&Zde
dejeef fd'd(Zd)S )*r  a  
    Utility class to help manipulate array contraction objects.

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

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

    Once editing is finished, the ``ArrayContraction`` object may be recreated
    by calling the ``.to_array_contraction()`` method.
    
base_arrayc                 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   )r2   r   r&   r   r   r   r   r  r   r   r   r   r   r   rs   r  ry   number_of_contraction_indices_track_permutation)r:   rT  r8  r   r   diagonalizedr   r  r]   contraction_tuplerg   arg_posrel_posr(  r<   r<   r=   rK  g  sX   







z_EditArrayContraction.__init__r   new_argc                 C   s"   | j |}| j |d | d S rV   )r  ry  insert)r:   r   r[  posr<   r<   r=   r    s   z"_EditArrayContraction.insert_afterc                 C   s   |  j d7  _ | j d S rV   )rU  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 r1   )r   r[   updatesr<   r=   ra     r   z9_EditArrayContraction.refresh_indices.<locals>.<listcomp>)r  r  rs   r   r
  ry   rU  )r:   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  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_matrixrc  r  )r:   scalarsr`  r]   scalarrc  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<   rb  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,   valuesrh  ra  get_contraction_indicesr   r   r   rV  r   )r:   r8  diag_indicescount_index_freqr`  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_contractionrH   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   rU  r  rs   r   )r:   r   current_positionr`  rg   r<   r<   r=   rj    s   


z-_EditArrayContraction.get_contraction_indicesc                 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)rU  ri   r   r  rs   r   rP  )r:   r   r  r]   r`  rg   r  r<   r<   r=   r    s   
z+_EditArrayContraction.get_mapping_for_indexc                 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   rU  r   r  rs   r   rP  )r:   r   r]   r`  rg   r   r<   r<   r=   &get_contraction_indices_to_ind_rel_pos  s   z<_EditArrayContraction.get_contraction_indices_to_ind_rel_posry  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   )r:   ry  r8  r`  r<   r<   r=   count_args_with_index  s   

z+_EditArrayContraction.count_args_with_indexc                    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  )r:   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   4  r   zC_EditArrayContraction.number_of_diagonal_indices.<locals>.<setcomp>)r   r  r  rs   ry   )r:   rm   r   r<   r<   r=   number_of_diagonal_indices0  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^   G  ru   z@_EditArrayContraction.track_permutation_start.<locals>.<genexpr>c                    s   g | ]} | qS r<   r<   r[   max_indr<   r=   ra   H  rb   zA_EditArrayContraction.track_permutation_start.<locals>.<listcomp>)r  rs   r   r]  rV  )r:   r   	perm_diagr8  rr  r`  permr]   r<   r|  r=   track_permutation_start7  s$   




z-_EditArrayContraction.track_permutation_startdestinationfrom_elementc                 C   s>   | j |}| j |}| j| | j|  | j| d S r1   )r  ry  rV  r   r   )r:   r  r  index_destinationindex_elementr<   r<   r=   track_permutation_mergeK  s   z-_EditArrayContraction.track_permutation_mergec                 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 r1   r<   r[   r<   r<   r=   ra   X  r   zA_EditArrayContraction.get_absolute_free_range.<locals>.<listcomp>argument not foundr  ry   rs   rx   )r:   r   r8  r`  number_free_indicesr<   r<   r=   get_absolute_free_rangeQ  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  )r:   r   r8  r`  number_indicesr<   r<   r=   r  ^  s   


z(_EditArrayContraction.get_absolute_rangeN)rB   rC   rD   ro   rp   Unionr   r   r   rK  r	  r  r  ra  rh  r
  r   r  rj  rP  r  rx  ry  rz  rq   r{  r  r  r   r  r  r<   r<   r<   r=   r  X  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   r0   r   )r2   r   r#   r   ry   r0   r    r  r!   r"   rw   r  r<   r<   r=   r   l  s    






r   c                 C   s   t | tr	|  S t| S r1   )r2   r   r   r   r  r<   r<   r=   r     s   
r   c                 C   s   t | tr| jS t| gS r1   )r2   r   r   r   r  r<   r<   r=   r    s   

r  c                 C   s   t | dr| jS dS )Nr0   r<   )rw   r0   r  r<   r<   r=   r     s   
r   c                 C   s   t | tr	|  S | S r1   )r2   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?   r1   )r6   )r   rs   r<   r<   r=   r@     rA   r@   )bcollections.abcr3   r   r   r   	functoolsr   rj   r   rp   r   r   r   rE   sympy.core.numbersr	   sympy.core.relationalr
   (sympy.functions.special.tensor_functionsr   sympy.core.basicr   sympy.core.containerssympy.core.exprr   sympy.core.functionr   r   sympy.core.mulr   sympy.core.singletonr   sympy.core.sortingr   sympy.core.symbolr   r   sympy.matrices.matrixbaser   #sympy.matrices.expressions.diagonalr   "sympy.matrices.expressions.matexprr   "sympy.matrices.expressions.specialr   sympy.tensor.array.arrayopr   r   r   r   #sympy.tensor.array.dense_ndim_arrayr   sympy.tensor.array.ndim_arrayr    sympy.tensor.indexedr!   r"   r#   $sympy.tensor.array.expressions.utilsr$   r%   r&   r'   r(   r)   r   r+    sympy.combinatorics.permutationsr,   sympy.core.sympifyr.   r/   rG   r6   r   r   r   r   r   r   r   r  r   rF  r	  rP  r  r   r   r  r   rh  r   r   r   r   rn  r@   r<   r<   r<   r=   <module>   s     5/Z;  Y Q)    ?  