U
    L?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<   b/var/www/html/venv/lib/python3.8/site-packages/sympy/tensor/array/expressions/array_expressions.py__getitem__*   s    z_ArrayExpr.__getitem__c                 C   s
   t | |S r1   )_get_array_element_or_slicer9   r<   r<   r=   r8   0   s    z_ArrayExpr._getN)__name__
__module____qualname__tTupler   __annotations__r>   r8   r<   r<   r<   r=   r/   '   s   
r/   c                   @   sB   e Zd ZdZejd d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=   rI   9   s
    
zArraySymbol.__new__c                 C   s
   | j d S Nr   _argsr:   r<   r<   r=   nameA   s    zArraySymbol.namec                 C   s
   | j d S N   rN   rP   r<   r<   r=   r0   E   s    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   s   | ]}|j V  qd S r1   Z
is_Integer.0ir<   r<   r=   	<genexpr>J   s     z*ArraySymbol.as_explicit.<locals>.<genexpr>z1cannot express explicit array with symbolic shapec                    s   g | ]} | qS r<   r<   rU   rP   r<   r=   
<listcomp>L   s     z+ArraySymbol.as_explicit.<locals>.<listcomp>c                 S   s   g | ]}t |qS r<   rangerV   jr<   r<   r=   rY   L   s     )allr0   
ValueError	itertoolsproductr   reshape)r:   datar<   rP   r=   as_explicitI   s    $zArraySymbol.as_explicitN)r@   rA   rB   __doc__typingr5   rI   propertyrQ   r0   rd   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 )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   rG   r   r.   r3   r4   r5   tupler7   r   rI   )rJ   rQ   indicesrL   r<   r<   r=   rI   Y   s    
zArrayElement.__new__c                 C   sp   t |}t|drRtd}t|t|jkr0|tdd t||jD rRtdtdd |D rltdd S )Nr0   z3number of indices does not match shape of the arrayc                 s   s   | ]\}}||kd kV  qdS )TNr<   )rV   rW   sr<   r<   r=   rX   k   s     z,ArrayElement._check_shape.<locals>.<genexpr>zshape is out of boundsc                 s   s   | ]}|d k dkV  qdS )r   TNr<   rU   r<   r<   r=   rX   m   s     zshape contains negative values)rh   hasattr
IndexErrorlenr0   anyzipr_   )rJ   rQ   ri   Zindex_errorr<   r<   r=   r7   d   s    
zArrayElement._check_shapec                 C   s
   | j d S rM   rN   rP   r<   r<   r=   rQ   p   s    zArrayElement.namec                 C   s
   | j d S rR   rN   rP   r<   r<   r=   ri   t   s    zArrayElement.indicesc                 C   sN   t |tstjS || krtjS |j| jkr0tjS tdd t| j	|j	D S )Nc                 s   s   | ]\}}t ||V  qd S r1   r   rV   rW   r]   r<   r<   r=   rX      s     z0ArrayElement._eval_derivative.<locals>.<genexpr>)
r2   r6   r   ZeroOnerQ   r   fromiterro   ri   )r:   rj   r<   r<   r=   _eval_derivativex   s    
zArrayElement._eval_derivativeN)r@   rA   rB   re   Z	_diff_wrtZ	is_symbolZis_commutativerI   classmethodr7   rg   rQ   ri   rt   r<   r<   r<   r=   r6   P   s   


r6   c                   @   s4   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   s0   t |dkrtjS tt|}tj| f| }|S rM   )rm   r   rq   rH   r.   r   rI   rJ   r0   rL   r<   r<   r=   rI      s
    
zZeroArray.__new__c                 C   s   | j S r1   rN   rP   r<   r<   r=   r0      s    zZeroArray.shapec                 C   s(   t dd | jD stdtj| j S )Nc                 s   s   | ]}|j V  qd S r1   rT   rU   r<   r<   r=   rX      s     z(ZeroArray.as_explicit.<locals>.<genexpr>/Cannot return explicit form for symbolic shape.)r^   r0   r_   r   ZzerosrP   r<   r<   r=   rd      s    zZeroArray.as_explicitc                 C   s   t jS r1   )r   rq   r9   r<   r<   r=   r8      s    zZeroArray._getN	r@   rA   rB   re   rI   rg   r0   rd   r8   r<   r<   r<   r=   rv      s   
rv   c                   @   s4   e Zd ZdZdd Zedd Zdd Zdd	 Zd
S )OneArrayz!
    Symbolic array of ones.
    c                 G   s0   t |dkrtjS tt|}tj| f| }|S rM   )rm   r   rr   rH   r.   r   rI   rw   r<   r<   r=   rI      s
    
zOneArray.__new__c                 C   s   | j S r1   rN   rP   r<   r<   r=   r0      s    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   s   | ]}|j V  qd S r1   rT   rU   r<   r<   r=   rX      s     z'OneArray.as_explicit.<locals>.<genexpr>rx   c                 S   s   g | ]
}t jqS r<   r   rr   rU   r<   r<   r=   rY      s     z(OneArray.as_explicit.<locals>.<listcomp>)	r^   r0   r_   r   r[   r   operatormulrb   rP   r<   r<   r=   rd      s    zOneArray.as_explicitc                 C   s   t jS r1   r{   r9   r<   r<   r=   r8      s    zOneArray._getNry   r<   r<   r<   r=   rz      s   
rz   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)	_subranksrP   r<   r<   r=   subranks   s    z_CodegenArrayAbstract.subranksc                 C   s
   t | jS )z*
        The sum of ``subranks``.
        )sumr   rP   r<   r<   r=   subrank   s    z_CodegenArrayAbstract.subrankc                 C   s   | j S r1   _shaperP   r<   r<   r=   r0      s    z_CodegenArrayAbstract.shapec                    s:     dd}|r.| j fdd| jD   S |  S d S )NdeepTc                    s   g | ]}|j f  qS r<   )doitrV   arghintsr<   r=   rY      s     z._CodegenArrayAbstract.doit.<locals>.<listcomp>)getfuncargs_canonicalize)r:   r   r   r<   r   r=   r      s    z_CodegenArrayAbstract.doitN)r@   rA   rB   rg   r   r   r0   r   r<   r<   r<   r=   r~      s   

r~   c                   @   s4   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| f| }||_dd |D }tdd |D rfd |_ntd	d |D |_|r| S |S )
Nc                 S   s   g | ]}t |qS r<   r-   r   r<   r<   r=   rY      s     z.ArrayTensorProduct.__new__.<locals>.<listcomp>canonicalizeFc                 S   s   g | ]}t |qS r<   get_rankr   r<   r<   r=   rY      s     c                 S   s   g | ]}t |qS r<   	get_shaperU   r<   r<   r=   rY      s     c                 s   s   | ]}|d kV  qd S r1   r<   rU   r<   r<   r=   rX      s     z-ArrayTensorProduct.__new__.<locals>.<genexpr>c                 s   s   | ]}|D ]
}|V  q
qd S r1   r<   rp   r<   r<   r=   rX      s       )popr   rI   r   rn   r   rh   r   )rJ   r   kwargsr   ranksrL   shapesr<   r<   r=   rI      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*|rt	t
| ttd t| S t|dkr|d S tdd |D rttjdd |D d	}t| S d
d t|D }|rJdd |D ttdg d d  t
dd |D  } fdd| D }t|f| S dd t|D }|rg }	g }
dd |D ttdg d d  t|D ]\}t|trt|t|j }t|j}|	 fddt|D  |
 fddt||| D  n"|	 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|f| t|	S | j|ddiS )Nc                 S   s   g | ]}t |qS r<   r   r   r<   r<   r=   rY     s     z4ArrayTensorProduct._canonicalize.<locals>.<listcomp>c                    s    g | ]} fd d|D qS )c                    s    g | ]}|t d    qS r1   )r   rV   krW   r   r<   r=   rY   	  s     z?ArrayTensorProduct._canonicalize.<locals>.<listcomp>.<listcomp>r<   r\   r   r<   r=   rY   	  s     rS   r   c                 s   s   | ]}t |ttfV  qd S r1   r2   rv   r   r   r<   r<   r=   rX     s     z3ArrayTensorProduct._canonicalize.<locals>.<genexpr>c                 S   s   g | ]}t |qS r<   r   rU   r<   r<   r=   rY     s     r<   c                 S   s    i | ]\}}t |tr||qS r<   )r2   ArrayContractionrV   rW   r   r<   r<   r=   
<dictcomp>  s     
  z4ArrayTensorProduct._canonicalize.<locals>.<dictcomp>c                 S   s&   g | ]}t |trt|nt|qS r<   )r2   r   _get_subrankr   r   r<   r<   r=   rY     s     c                 S   s    g | ]}t |tr|jn|qS r<   )r2   r   exprr   r<   r<   r=   rY     s     c                    s4   g | ],\ }|j D ]}t fd d|D qqS )c                 3   s   | ]}  | V  qd S r1   r<   r   cumulative_ranksrW   r<   r=   rX     s     >ArrayTensorProduct._canonicalize.<locals>.<listcomp>.<genexpr>)contraction_indicesrh   rV   r   r]   r   rW   r=   rY     s       c                 S   s    i | ]\}}t |tr||qS r<   )r2   ArrayDiagonalr   r<   r<   r=   r      s     
  c                 S   s   g | ]}t |qS r<   r   r   r<   r<   r=   rY   $  s     c                    s   g | ]}  | qS r<   r<   r\   r   r<   r=   rY   *  s     c                    s   g | ]}  | qS r<   r<   r\   r   r<   r=   rY   +  s     c                    s   g | ]}  | qS r<   r<   r\   r   r<   r=   rY   -  s     c                 S   s    g | ]}t |tr|jn|qS r<   )r2   r   r   r   r<   r<   r=   rY   /  s     c                 S   s&   g | ]}t |trt|nt|qS r<   )r2   r   r   r   r   r<   r<   r=   rY   0  s     c                    s4   g | ],\ }|j D ]}t fd d|D qqS )c                 3   s   | ]}  | V  qd S r1   r<   r   )cumulative_ranks2rW   r<   r=   rX   2  s     r   )diagonal_indicesrh   r   )r   r   r=   rY   2  s       r   F)r   _flatten	enumerater2   PermuteDimsextendpermutationcyclic_formr   _permute_dims_array_tensor_productr+   r   rm   rn   r   r|   addrv   listr   items_array_contractionr   r   r   r[   _array_diagonalr,   r   )r:   r   Zpermutation_cyclesr   r   Zcontractionstpr   Z	diagonalsinverse_permutationZ	last_permi1i2Zranks2r   r<   )r   r   rW   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   )rV   r   rW   rJ   r<   r=   rY   9  s       z/ArrayTensorProduct._flatten.<locals>.<listcomp>r<   )rJ   r   r<   r   r=   r   7  s    zArrayTensorProduct._flattenc                 C   s   t dd | jD  S )Nc                 S   s"   g | ]}t |d r| n|qS rd   rk   rd   r   r<   r<   r=   rY   =  s     z2ArrayTensorProduct.as_explicit.<locals>.<listcomp>)r   r   rP   r<   r<   r=   rd   <  s    zArrayTensorProduct.as_explicitN)	r@   rA   rB   re   rI   r   ru   r   rd   r<   r<   r<   r=   r      s   9
r   c                   @   s4   e Zd ZdZdd Zdd Zedd Zdd	 Zd
S )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rhtd	|d
d}tj| f| }||_tdd |D rd |_	n
|d |_	|r|
 S |S )Nc                 S   s   g | ]}t |qS r<   r-   r   r<   r<   r=   rY   F  s     z$ArrayAdd.__new__.<locals>.<listcomp>c                 S   s   g | ]}t |qS r<   r   r   r<   r<   r=   rY   G  s     rS   z!summing arrays of different ranksc                 S   s   g | ]
}|j qS r<   r0   r   r<   r<   r=   rY   K  s     c                 S   s   h | ]}|d k	r|qS r1   r<   rU   r<   r<   r=   	<setcomp>L  s      z#ArrayAdd.__new__.<locals>.<setcomp>zmismatching shapes in additionr   Fc                 s   s   | ]}|d kV  qd S r1   r<   rU   r<   r<   r=   rX   S  s     z#ArrayAdd.__new__.<locals>.<genexpr>r   )r   setrm   r_   r   r   rI   r   rn   r   r   )rJ   r   r   r   r   r   rL   r<   r<   r=   rI   E  s"    
zArrayAdd.__new__c                 C   s   | j }| |}dd |D }dd |D }t|dkr^tdd |D rRtdt|d  S t|dkrr|d S | j|d	d
iS )Nc                 S   s   g | ]}t |qS r<   r   r   r<   r<   r=   rY   a  s     z*ArrayAdd._canonicalize.<locals>.<listcomp>c                 S   s   g | ]}t |ttfs|qS r<   r   r   r<   r<   r=   rY   b  s      r   c                 s   s   | ]}|d kr|V  qd S r1   r<   rU   r<   r<   r=   rX   d  s      z)ArrayAdd._canonicalize.<locals>.<genexpr>zIcannot handle addition of ZeroMatrix/ZeroArray and undefined shape objectrS   r   F)r   _flatten_argsrm   rn   NotImplementedErrorrv   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)rJ   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   s"   g | ]}t |d r| n|qS r   r   r   r<   r<   r=   rY   x  s     z(ArrayAdd.as_explicit.<locals>.<listcomp>)r   r|   r   r   rP   r<   r<   r=   rd   u  s    zArrayAdd.as_explicitN)	r@   rA   rB   re   rI   r   ru   r   rd   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rJtd|dd}	t	| | }
t|g|
_
t|d krd |
_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<   rU   r   r0   r<   r=   rX     s     z&PermuteDims.__new__.<locals>.<genexpr>)sympy.combinatoricsr+   r.   r   _get_permutation_from_argumentssizer_   r   r   rI   r   r   r   rh   r[   rm   r   )rJ   r   r   index_order_oldindex_order_newr   r+   Z	expr_rankZpermutation_sizer   rL   r<   r   r=   rI     s$    "zPermuteDims.__new__c                    s   | j  | j}t tr. j } j}|| }| t trH|  |\ }t trb|  |\ }t tt	frt fdd|j
D  S |j
}|t|kr S | j |ddS )Nc                    s   g | ]} j | qS r<   r   rU   r   r<   r=   rY     s     z-PermuteDims._canonicalize.<locals>.<listcomp>F)r   )r   r   r2   r   r   '_PermuteDims_denestarg_ArrayContractionr   )_PermuteDims_denestarg_ArrayTensorProductrv   r   
array_formsortedr   )r:   r   ZsubexprZsubpermplistr<   r   r=   r     s"    


zPermuteDims._canonicalizec                 C   s
   | j d S rM   r   rP   r<   r<   r=   r     s    zPermuteDims.exprc                 C   s
   | j d S rR   r   rP   r<   r<   r=   r     s    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 rS   r<   rU   )cumulperm_image_formr<   r=   rY      s     zIPermuteDims._PermuteDims_denestarg_ArrayTensorProduct.<locals>.<listcomp>c                 S   s   g | ]\}}|t |fqS r<   )r   )rV   rW   compr<   r<   r=   rY     s     c                 S   s   | d S rR   r<   xr<   r<   r=   <lambda>      zGPermuteDims._PermuteDims_denestarg_ArrayTensorProduct.<locals>.<lambda>keyc                 S   s   g | ]}|d  qS r   r<   rU   r<   r<   r=   rY     s     c                    s   g | ]} | qS r<   r<   rU   r   r<   r=   rY   
  s     c                    s   g | ]} | qS r<   r<   rU   )perm_image_form_in_componentsr<   r=   rY     s     c                 S   s   g | ]}|D ]}|qqS r<   r<   rp   r<   r<   r=   rY     s       )r,   r   r   r   r   r   r[   rm   r   sortr+   r   )rJ   r   r   ZpsZperm_args_image_formargs_sortedZperm_image_form_sorted_argsnew_permutationr<   )r   r   r   r   r=   r     s    

z5PermuteDims._PermuteDims_denestarg_ArrayTensorProductc                    s  t |ts||fS t |jts&||fS |jj dd |jjD }|j}dd |D }ttdg| g t|j	}d}t
|D ]R\}}	g }
t| |d  D ]$}||krq|
||  |d7 }q|
 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| f| }ttdd fdd|D D }||fS )Nc                 S   s   g | ]}t |qS r<   r   r   r<   r<   r=   rY     s     zGPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<listcomp>c                 S   s   g | ]}|D ]}|qqS r<   r<   rp   r<   r<   r=   rY     s       r   rS   c                    s*   g | ]"\}}t t |  |d   qS r   r   r[   rV   rW   er   r<   r=   rY   ,  s     r   c                    s   g | ]} fd d|D qS )c                    s   g | ]}|d k	r |qS r1   r<   r\   r   r<   r=   rY   /  s      zRPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<listcomp>.<listcomp>r<   rU   r   r<   r=   rY   /  s     c                 S   s   | d S rR   r<   r   r<   r<   r=   r   4  r   zEPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<lambda>r   c                 S   s   g | ]}|d  qS r   r<   rU   r<   r<   r=   rY   7  s     c                    s   g | ]} | qS r<   r<   rU   index_blocksr<   r=   rY   9  s     c                 S   s   g | ]}|D ]}|qqS r<   r<   rp   r<   r<   r=   rY   :  s       c                    s   g | ]} | qS r<   r<   rU   r   r<   r=   rY   ;  s     c                    s"   g | ]}t  fd d|D qS )c                 3   s   | ]} | V  qd S r1   r<   r\   new_index_perm_array_formr<   r=   rX   <  s     zQPermuteDims._PermuteDims_denestarg_ArrayContraction.<locals>.<listcomp>.<genexpr>rh   rU   r   r<   r=   rY   <  s     c                 S   s   g | ]}|D ]}|qqS r<   r<   rp   r<   r<   r=   rY   >  s       c                    s   g | ]} | qS r<   r<   r   )permutation_array_blocks_upr<   r=   rY   >  s     )r2   r   r   r   r   r   r   r   r,   r   r   r[   r   r   _push_indices_upr   r   r   r+   )rJ   r   r   r   r   contraction_indices_flatZ
image_formcounterrW   r   currentr]   Zindex_blocks_upZindex_blocks_up_permutedZsorting_keysZnew_perm_image_formZnew_index_blocksr   new_contraction_indicesZnew_exprr   r<   )r   r   r   r   r   r   r=   r     sD    


$z3PermuteDims._PermuteDims_denestarg_ArrayContractionc                    s  j }fddtjD fddt D }tj|d  }g g t }t|D ]\}}| |kr g | }| || }	t	|	krdt
 fddD }
| }t| t|
|< || g qd ttt	}i }dgtt|  tt	|D ]\}fddt |  |d  D }t	|dkrrq6tt|}||kr6|||< q6g }g }|rt	|dkr| \}}|| n$|d	 }||krg }q||}||kr|| g }q|| q|D ]2}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<   )r[   r   )rV   rW   r   r]   r   r<   r=   rY   D  s       z:PermuteDims._check_permutation_mapping.<locals>.<listcomp>c                    s   g | ]} |qS r<   r<   rU   r   r<   r=   rY   E  s     r   c                    s   g | ]}|t   qS r<   minr\   )current_indicesr<   r=   rY   T  s     c                    s   h | ]} |  qS r<   r<   r\   )	index2argr   r<   r=   r   b  s     z9PermuteDims._check_permutation_mapping.<locals>.<setcomp>rS   r   c                    s*   g | ]"\ } fd dt |D qS )c                    s   g | ]}  |  qS r<   r<   r\   )cumulative_subranksrW   r   r<   r=   rY     s     zEPermuteDims._check_permutation_mapping.<locals>.<listcomp>.<listcomp>rZ   )rV   r   )r   r   r   r=   rY     s     c                    s   g | ]} | qS r<   r<   rU   )r   r<   r=   rY     s     c                    s   g | ]} | qS r<   r<   rU   )permutation_blocksr<   r=   rY     s     c                 S   s   g | ]}|D ]}|qqS r<   r<   rp   r<   r<   r=   rY     s       )r   r   r   r[   r   r   r   r   r   rm   r   r   r+   r   r   nextiterpopitemr   r   )rJ   r   r   r   Zpermuted_indicesZarg_candidate_indexZinserted_arg_cand_indicesrW   idxZarg_candidate_rankZlocal_current_indicesr   Zargs_positionsmapsrj   elemlinescurrent_liner   vliner   Znew_permutation_blocksZnew_permutation2r<   )r   r   r   r   r   r   r   r   r=   _check_permutation_mappingA  sr    




&




 z&PermuteDims._check_permutation_mappingc                    s   t |j}|j}|j}dgt t|  dd |D }dd |D }g }t|D ]\}	}
d}tt d D ]\||	   krl||	  d  k rlt| t	 fdd||	 D g|< d} qql|rP|
||	  qPt| t	||jd	fS )
Nr   c                 S   s   g | ]}t |qS r<   r   rU   r<   r<   r=   rY     s     zAPermuteDims._check_if_there_are_closed_cycles.<locals>.<listcomp>c                 S   s   g | ]}t |qS r<   maxrU   r<   r<   r=   rY     s     TrS   c                    s   g | ]}|   qS r<   r<   r   r   r]   r<   r=   rY     s     F)r   )r   r   r   r   r   r   r[   rm   r   r+   r   r   r   )rJ   r   r   r   r   r   Z
cyclic_minZ
cyclic_maxZcyclic_keeprW   cycleflagr<   r	  r=   !_check_if_there_are_closed_cycles  s"    
$,z-PermuteDims._check_if_there_are_closed_cyclesc                 C   s    |  | j| j}|dk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rlj}tj|f| }t|  fdd|jD }t	t
|j f| S t |trtfdd|jD  S d S )Nc                    s"   g | ]}t  fd d|D qS )c                 3   s   | ]} |V  qd S r1   r<   r\   newpermutationr<   r=   rX     s     z;PermuteDims._nest_permutation.<locals>.<listcomp>.<genexpr>r   rU   r  r<   r=   rY     s     z1PermuteDims._nest_permutation.<locals>.<listcomp>c                    s   g | ]}t | qS r<   r   r   r   r<   r=   rY     s     )r2   r   r   r  r   r   '_convert_outer_indices_to_inner_indicesr+   r   r   r   r   r   
_array_addr   )rJ   r   r   ZcyclesZ	newcyclesnew_contr_indicesr<   )r  r   r=   r    s    


zPermuteDims._nest_permutationc                 C   s$   | j }t|dr| }t|| jS Nrd   )r   rk   rd   r   r   r:   r   r<   r<   r=   rd     s    
zPermuteDims.as_explicitc                 C   sV   |d kr.|d ks|d kr t dt|||S |d k	r>t d|d k	rNt d|S d S )NzPermutation not definedz2index_order_new cannot be defined with permutationz2index_order_old cannot be defined with permutation)r_   r   "_get_permutation_from_index_orders)rJ   r   r   r   dimr<   r<   r=   r     s    z+PermuteDims._get_permutation_from_argumentsc                    sj   t t||krtdt t |kr0tdt tt|t dkrTt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                    s   g | ]}  |qS r<   indexrU   r   r<   r=   rY     s     zBPermuteDims._get_permutation_from_index_orders.<locals>.<listcomp>)rm   r   r_   symmetric_difference)rJ   r   r   r  r   r<   r  r=   r    s    z.PermuteDims._get_permutation_from_index_orders)NNN)r@   rA   rB   re   rI   r   rg   r   r   ru   r   r   r  r  r  r  rd   r   r  r<   r<   r<   r=   r   {  s.   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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 k	rV| j|f|| | ||\}}nd }t|dkrj|S tj| |f| }||_t	||_
||_|r| S |S )Nc                 S   s   g | ]}t t| qS r<   )r   r   rU   r<   r<   r=   rY     s     z)ArrayDiagonal.__new__.<locals>.<listcomp>r   Fr   )r.   r   r   	_validate_get_positions_shaperm   r   rI   
_positions_get_subranksr   r   r   )rJ   r   r   r   r   r0   	positionsrL   r<   r<   r=   rI     s"    
zArrayDiagonal.__new__c                 C   s  | j }| j}dd |D }t|dkr"dd t|D }dd t|D }dd |D }t| }t|}|| }	g }
d}t|tt|t|}|D ]T}||kr|
	|	||   qt
|ttfr|
	| |d7 }q|
	|	||   qt|
}t|dkrtt|f| |S t||S t
|tr>| j|f| S t
|trZ| j|f| S t
|trv| j|f| S t
|ttfr| |j|\}}t| S | j|f|d	d
iS )Nc                 S   s   g | ]}t |d kr|qS r   rm   rU   r<   r<   r=   rY     s      z/ArrayDiagonal._canonicalize.<locals>.<listcomp>r   c                 S   s&   i | ]\}}t |d kr|d |qS rS   r   r#  r   r<   r<   r=   r     s       z/ArrayDiagonal._canonicalize.<locals>.<dictcomp>c                 S   s"   i | ]\}}t |d kr||qS r   r#  r   r<   r<   r=   r     s       c                 S   s   g | ]}t |d kr|qS r   r#  rU   r<   r<   r=   rY   	  s      rS   r   F)r   r   rm   r   r   r   _push_indices_downr   r[   r   r2   r	   intr,   r   r   r   _ArrayDiagonal_denest_ArrayAdd#_ArrayDiagonal_denest_ArrayDiagonalr   !_ArrayDiagonal_denest_PermuteDimsrv   r   r  r0   r   )r:   r   r   Ztrivial_diagsZtrivial_posZdiag_posZdiagonal_indices_shortZrank1Zrank2Zrank3Zinv_permutationZcounter1Zindices_downrW   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rPtd|dd	spt|dkrptd
tt|t|krtdqd S )Nc                 3   s   | ]}|t  kV  qd S r1   r#  r\   r   r<   r=   rX   .  s     z*ArrayDiagonal._validate.<locals>.<genexpr>z%index is larger than expression shapec                    s   h | ]} | qS r<   r<   r\   r   r<   r=   r   0  s     z*ArrayDiagonal._validate.<locals>.<setcomp>rS   z-diagonalizing indices of different dimensionsZallow_trivial_diagsFz%need at least two axes to diagonalizezaxis index cannot be repeated)r   rn   r_   rm   r   r   )r   r   r   rW   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   rS   c                 s   s   | ]
}|V  qd S r1   r<   r\   r<   r<   r=   rX   9  s     zFArrayDiagonal._remove_trivial_dimensions.<locals>.<listcomp>.<genexpr>r   rU   r   r<   r=   rY   9  s      z<ArrayDiagonal._remove_trivial_dimensions.<locals>.<listcomp>r<   )r0   r   r<   r   r=   _remove_trivial_dimensions7  s    z(ArrayDiagonal._remove_trivial_dimensionsc                 C   s
   | j d S rM   r   rP   r<   r<   r=   r   ;  s    zArrayDiagonal.exprc                 C   s   | j dd  S rR   r   rP   r<   r<   r=   r   ?  s    zArrayDiagonal.diagonal_indicesc                    s   | j }dd |D }|  t| }t|}|| }dd t|D  d}d}t|D ]B}	||k r||| kr|d7 }|d7 }qZ |	  |7  < |d7 }qVt fdd|D }|| }
t| jf|
 S )Nc                 S   s   g | ]}|D ]}|qqS r<   r<   rp   r<   r<   r=   rY   F  s       z*ArrayDiagonal._flatten.<locals>.<listcomp>c                 S   s   g | ]}d qS r   r<   rU   r<   r<   r=   rY   L  s     r   rS   c                 3   s$   | ]}t  fd d|D V  qdS )c                 3   s   | ]} | | V  qd S r1   r<   r\   shiftsr<   r=   rX   U  s     z3ArrayDiagonal._flatten.<locals>.<genexpr>.<genexpr>Nr   rU   r+  r<   r=   rX   U  s     z)ArrayDiagonal._flatten.<locals>.<genexpr>)r   r   r   rm   r[   rh   r   r   )r   Zouter_diagonal_indicesZinner_diagonal_indices	all_inner
total_rank
inner_rank
outer_rankr   pointerrW   r   r<   r+  r=   r   C  s$    

zArrayDiagonal._flattenc                    s   t  fdd|jD  S )Nc                    s   g | ]}t |f  qS r<   )r   r   r   r<   r=   rY   [  s     z@ArrayDiagonal._ArrayDiagonal_denest_ArrayAdd.<locals>.<listcomp>r  r   rJ   r   r   r<   r2  r=   r'  Y  s    z,ArrayDiagonal._ArrayDiagonal_denest_ArrayAddc                 G   s   | j |f| S r1   r   r4  r<   r<   r=   r(  ]  s    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f| |S )	Nc                    s   g | ]} fd d|D qS )c                    s   g | ]}  |qS r<   r   r\   r   r<   r=   rY   c  s     zNArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<listcomp>.<listcomp>r<   rU   r   r<   r=   rY   c  s     zCArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<listcomp>c                    s&   g | ] t  fd dD s qS )c                 3   s   | ]} |kV  qd S r1   r<   r\   r   r<   r=   rX   d  s     zMArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<listcomp>.<genexpr>rn   rV   r2  r   r=   rY   d  s      c                    s   g | ]}  |qS r<   r   rU   r   r<   r=   rY   e  s     c                 S   s   i | ]\}}||qS r<   r<   r   r<   r<   r=   r   f  s      zCArrayDiagonal._ArrayDiagonal_denest_PermuteDims.<locals>.<dictcomp>c                    s   g | ]} | qS r<   r<   rU   )remapr<   r=   rY   g  s     c                    s   g | ]}|  qS r<   r<   rU   )shiftr<   r=   rY   i  s     )r[   r   r   r   rm   r   r   r   )	rJ   r   r   Zback_diagonal_indicesZnondiagZback_nondiagZnew_permutation1Zdiag_block_permr   r<   )r   r   r8  r9  r=   r)  a  s     z/ArrayDiagonal._ArrayDiagonal_denest_PermuteDimsc                    s    fdd}t ||S )Nc                    s   | t  jk r j|  S d S r1   )rm   r   r   rP   r<   r=   r   t  r   z<ArrayDiagonal._push_indices_down_nonstatic.<locals>.<lambda>r$   r:   ri   	transformr<   rP   r=   _push_indices_down_nonstatics  s    z*ArrayDiagonal._push_indices_down_nonstaticc                    s    fdd}t ||S )Nc                    sD   t  jD ]4\}}t|tr$| |ks6t|tr
| |kr
|  S q
d S r1   )r   r   r2   r&  rh   r   rW   r   rP   r<   r=   r<  y  s    $z;ArrayDiagonal._push_indices_up_nonstatic.<locals>.transformr:  r;  r<   rP   r=   _push_indices_up_nonstaticw  s    z(ArrayDiagonal._push_indices_up_nonstaticc                    s*   |  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  r[   r$   rJ   r   ri   rankr0   r<  r<   r@  r=   r%    s    z ArrayDiagonal._push_indices_downc                    s*   |  t||\ } fdd}t||S )Nc                    sF   t  D ]8\}}t|tr"| |ks8t|ttfr| |kr|  S qd S r1   )r   r2   r&  rh   r   r>  r@  r<   r=   r<    s    (z1ArrayDiagonal._push_indices_up.<locals>.transformrA  rB  r<   r@  r=   r     s    zArrayDiagonal._push_indices_upc           
         sp   t  fddtD }|r&t| nd\}}t fdd D }|rPt| nd\}}|| }	|| |	fS )Nc                 3   s0   | ](\ }t  fd dD s |fV  qdS )c                 3   s   | ]} |kV  qd S r1   r<   r\   r   r<   r=   rX     s     z?ArrayDiagonal._get_positions_shape.<locals>.<genexpr>.<genexpr>Nr6  rV   Zshpr2  r   r=   rX     s      z5ArrayDiagonal._get_positions_shape.<locals>.<genexpr>)r<   r<   c                 3   s   | ]}| |d   fV  qdS )r   Nr<   rU   r   r<   r=   rX     s     )rh   r   ro   )
rJ   r0   r   Zdata1Zpos1Zshp1Zdata2pos2Zshp2r"  r<   )r   r0   r=   r    s    z"ArrayDiagonal._get_positions_shapec                 C   s(   | j }t|dr| }t|f| j S r  )r   rk   rd   r   r   r  r<   r<   r=   rd     s    
zArrayDiagonal.as_explicitN)r@   rA   rB   re   rI   r   staticmethodr  r*  rg   r   r   r   ru   r'  r(  r   r)  r=  r?  r%  r   r  rd   r<   r<   r<   r=   r     s8   &






	



	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~   rI   r!  r   )rJ   functionelementrI  rL   r<   r<   r=   rI     s    

z!ArrayElementwiseApplyFunc.__new__c                 C   s
   | j d S rM   r   rP   r<   r<   r=   rJ    s    z"ArrayElementwiseApplyFunc.functionc                 C   s
   | j d S rR   r   rP   r<   r<   r=   r     s    zArrayElementwiseApplyFunc.exprc                 C   s   | j jS r1   r   r0   rP   r<   r<   r=   r0     s    zArrayElementwiseApplyFunc.shapec                 C   s>   t d}| |}||}t|tr0t|}n
t||}|S rH  )r   rJ  diffr2   r   typer   )r:   rI  rJ  Zfdiffr<   r<   r=   _get_function_fdiff  s    




z-ArrayElementwiseApplyFunc._get_function_fdiffc                 C   s$   | j }t|dr| }|| jS r  )r   rk   rd   Z	applyfuncrJ  r  r<   r<   r=   rd     s    
z%ArrayElementwiseApplyFunc.as_explicitN)
r@   rA   rB   rI   rg   rJ  r   r0   rO  rd   r<   r<   r<   r=   rG    s   




rG  c                   @   sR  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
d&d'd(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 )Ar   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| |f  }t||_t|j|_ fddt	t
|jD }||_t|}| j|f   |rt fddt|D }||_|r| S |S )Nr   Fc                    s(   i | ]  t  fd dD r  qS )c                 3   s   | ]} |kV  qd S r1   r<   )rV   Zcindr   r<   r=   rX     s     z6ArrayContraction.__new__.<locals>.<dictcomp>.<genexpr>)r^   r7  r   r   r=   r     s       z,ArrayContraction.__new__.<locals>.<dictcomp>c                 3   s,   | ]$\ }t  fd dD s|V  qdS )c                 3   s   | ]} |kV  qd S r1   r<   r\   r   r<   r=   rX     s     z5ArrayContraction.__new__.<locals>.<genexpr>.<genexpr>Nr6  rD  rP  r   r=   rX     s      z+ArrayContraction.__new__.<locals>.<genexpr>)r%   r.   r   r   rI   r!  r   r&   _mappingr[   r   _free_indices_to_positionr   r  rh   r   r   r   )rJ   r   r   r   r   rL   free_indices_to_positionr0   r<   rP  r=   rI     s     
zArrayContraction.__new__c                    s  | j  | j}t|dkr S t tr6| j f| S t ttfrT| j f| S t t	rn| j
 f| S t tr|  |\ }|  |\ }t|dkr S t tr| j f| S t tr| j f| S  fdd|D }t|dkr S | j f|ddiS )Nr   c                    s0   g | ](}t |d ks(t |d  d kr|qS r$  )rm   r   rU   r   r<   r=   rY     s       z2ArrayContraction._canonicalize.<locals>.<listcomp>r   F)r   r   rm   r2   r   )_ArrayContraction_denest_ArrayContractionrv   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   s   |dkr| S t dd S NrS   zDProduct of N-dim arrays is not uniquely defined. Use another method.r   r:   otherr<   r<   r=   __mul__
  s    zArrayContraction.__mul__c                 C   s   |dkr| S t dd S r[  r\  r]  r<   r<   r=   __rmul__  s    zArrayContraction.__rmul__c                    sD   t |   d k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<   r\   r   r<   r=   r     s      z-ArrayContraction._validate.<locals>.<setcomp>rS   z+contracting indices of different dimensions)r   rm   r_   )r   r   rW   r<   r   r=   r    s    zArrayContraction._validatec                 C   s(   dd |D }|   t|}t||S )Nc                 S   s   g | ]}|D ]}|qqS r<   r<   rp   r<   r<   r=   rY   #  s       z7ArrayContraction._push_indices_down.<locals>.<listcomp>)r   r)   r$   rJ   r   ri   flattened_contraction_indicesr<  r<   r<   r=   r%  !  s    z#ArrayContraction._push_indices_downc                 C   s(   dd |D }|   t|}t||S )Nc                 S   s   g | ]}|D ]}|qqS r<   r<   rp   r<   r<   r=   rY   *  s       z5ArrayContraction._push_indices_up.<locals>.<listcomp>)r   r'   r$   ra  r<   r<   r=   r   (  s    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 ]x}t	t
|jD ]Zt |j tsqjtfdd|D rj| fdd|D   |  qXqj|| qXt
|t
|kr||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   s   g | ]}g qS r<   r<   rU   r<   r<   r=   rY   8  s     zBArrayContraction._lower_contraction_to_addends.<locals>.<listcomp>c                 3   s2   | ]*}  |  ko$ d   k n  V  qdS )rS   Nr<   r   cumranksr]   r<   r=   rX   >  s     zAArrayContraction._lower_contraction_to_addends.<locals>.<genexpr>c                    s   g | ]}|   qS r<   r<   r   rc  r<   r=   rY   ?  s     c                    s   g | ]}| krd ndqS r$  r<   rU   )	backshiftr<   r=   rY   G  s     c                    s$   g | ]}t  fd d|D qS )c                 3   s   | ]}| |  V  qd S r1   r<   r\   r+  r<   r=   rX   H  s     zLArrayContraction._lower_contraction_to_addends.<locals>.<listcomp>.<genexpr>)r   rs   rU   r+  r<   r=   rY   H  s     c                 S   s   g | ]\}}t |f| qS r<   r   )rV   r   Zcontrr<   r<   r=   rY   I  s    )r2   r   r   r   r   r   r   r   r   r[   rm   r^   r   updater   r   ro   )	rJ   r   r   r   Zcontraction_indices_remainingZcontraction_indices_argscontraction_groupr.  r  r<   )re  rd  r]   r,  r=   rX  /  s6    



z.ArrayContraction._lower_contraction_to_addendsc                    s  t | }| j}g }t|D ]\ }t|dkr2q| }| jj|d  }g }g }|D ]\}	}
|j|	 }|j}|	|\}}d|
 }|| d|jks|dkdkr|jdkst
 fddt|D r|||
f qX|||
f qXt|dkrq|D ]\}}
t|j|_q|dd | |dd  }|d \}}
|j|
 }|dd	 D ]R\}}
||j|
< | }|jdd|
 kst||j|jd< || qP|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   rS   T)rS   rS   c                 3   s"   | ]\}}| kr|kV  qd S r1   r<   )rV   ZlilZindlZother_arg_absr<   r=   rX     s      z?ArrayContraction.split_multiple_contractions.<locals>.<genexpr>Nr   )_EditArrayContractionr   r   rm   get_mapping_for_indexr   r0   args_with_indrK  get_absolute_rangern   r   r   ri   get_new_contraction_indexr  AssertionErrorinsert_after_ArgErz   to_array_contraction)r:   Zeditorr   Zonearray_insertlinksr"  Zcurrent_dimensionZnot_vectorsZvectorsarg_indZrel_indr   ZmatZabs_arg_startZabs_arg_endZother_arg_posr  Zvectors_to_loopZfirst_not_vectorZ	new_indexZlast_vecr<   rk  r=   split_multiple_contractionsN  sV    





z,ArrayContraction.split_multiple_contractionsc                    s   t | jts| S | j| jj| j}g }| jjd d  }|D ]`}t|}|D ]<fdd|D  |dd  D   fdd|D }qL|t	t
| q<t||}tt| jjf| f| S )Nc                    s   g | ]} |kr|qS r<   r<   r   )r]   r<   r=   rY     s      zDArrayContraction.flatten_contraction_of_diagonal.<locals>.<listcomp>c                 S   s   g | ]}|D ]}|qqS r<   r<   )rV   r   rj  r<   r<   r=   rY     s       c                    s   g | ]}| kr|qS r<   r<   r   )diagonal_withr<   r=   rY     s      )r2   r   r   r%  r   r   r   r   r   r   r   r   r   r   )r:   Zcontraction_downr   r   rW   rh  r<   )rx  r]   r=   flatten_contraction_of_diagonal  s,    z0ArrayContraction.flatten_contraction_of_diagonalc                 C   sF   i }dd |D }d}| D ]&}||kr0|d7 }q|||< |d7 }q|S )Nc                 S   s   g | ]}|D ]}|qqS r<   r<   rp   r<   r<   r=   rY     s       zFArrayContraction._get_free_indices_to_position_map.<locals>.<listcomp>r   rS   r<   )free_indicesr   rS  rb  r   indr<   r<   r=   !_get_free_indices_to_position_map  s    

z2ArrayContraction._get_free_indices_to_position_mapc           
      C   s   | j }dd |D }|  t| }t|}|| }dd t|D }d}d}t|D ]B}	||k r||| kr|d7 }|d7 }qZ||	  |7  < |d7 }qV|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   s   g | ]}|D ]}|qqS r<   r<   rp   r<   r<   r=   rY     s       z6ArrayContraction._get_index_shifts.<locals>.<listcomp>c                 S   s   g | ]}d qS r   r<   rU   r<   r<   r=   rY     s     r   rS   )r   r   r   rm   r[   )
r   inner_contraction_indicesr-  r.  r/  r0  r,  r   r1  rW   r<   r<   r=   _get_index_shifts  s     

z"ArrayContraction._get_index_shiftsc                    s$   t |  t fdd|D }|S )Nc                 3   s$   | ]}t  fd d|D V  qdS )c                 3   s   | ]} | | V  qd S r1   r<   r\   r+  r<   r=   rX     s     zUArrayContraction._convert_outer_indices_to_inner_indices.<locals>.<genexpr>.<genexpr>Nr   rU   r+  r<   r=   rX     s     zKArrayContraction._convert_outer_indices_to_inner_indices.<locals>.<genexpr>)r   r~  rh   )r   outer_contraction_indicesr<   r+  r=   r    s    
z8ArrayContraction._convert_outer_indices_to_inner_indicesc                 G   s.   | j }tj| f| }|| }t| jf| S r1   )r   r   r  r   r   )r   r  r}  r   r<   r<   r=   r     s    zArrayContraction._flattenc                 G   s   | j |f| S r1   r5  rJ   r   r   r<   r<   r=   rT  	  s    z:ArrayContraction._ArrayContraction_denest_ArrayContractionc                    s.   dd |D   fddt |jD }t| S )Nc                 S   s   g | ]}|D ]}|qqS r<   r<   rp   r<   r<   r=   rY     s       zGArrayContraction._ArrayContraction_denest_ZeroArray.<locals>.<listcomp>c                    s   g | ]\}}| kr|qS r<   r<   r   r   r<   r=   rY     s      )r   r0   rv   )rJ   r   r   r0   r<   r  r=   rU    s    z3ArrayContraction._ArrayContraction_denest_ZeroArrayc                    s   t  fdd|jD  S )Nc                    s   g | ]}t |f  qS r<   rf  rU   rP  r<   r=   rY     s     zFArrayContraction._ArrayContraction_denest_ArrayAdd.<locals>.<listcomp>r3  r  r<   rP  r=   rZ    s    z2ArrayContraction._ArrayContraction_denest_ArrayAddc                    sV   |j j}fdd|D   fdd|D }|  |}tt|jf  t|S )Nc                    s"   g | ]}t  fd d|D qS )c                 3   s   | ]} |V  qd S r1   r<   r\   r   r<   r=   rX     s     SArrayContraction._ArrayContraction_denest_PermuteDims.<locals>.<listcomp>.<genexpr>r   rU   r   r<   r=   rY     s     zIArrayContraction._ArrayContraction_denest_PermuteDims.<locals>.<listcomp>c                    s&   g | ] t  fd dD s qS )c                 3   s   | ]} |kV  qd S r1   r<   r\   r   r<   r=   rX     s     r  r6  r7  )r   r   r=   rY     s      )r   r   r   r   r   r   r+   )rJ   r   r   r   Z	new_plistr<   )r   r   r=   rV    s    z5ArrayContraction._ArrayContraction_denest_PermuteDimsr   r   c                    s   t |j}||j|t|j}dd |D }g }|D ]f}|d d  }t|D ]:\}  d kr`qNt fdd|D rN|  d ||< qN|t	t
| q6dd |D }	t||	}
tt|jf| f|
 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   rh   r   rV   r]   r   r<   r<   r=   rY   (  s       zVArrayContraction._ArrayContraction_denest_ArrayDiagonal.<locals>.<listcomp>.<listcomp>r<   rU   r<   r<   r=   rY   (  s     zKArrayContraction._ArrayContraction_denest_ArrayDiagonal.<locals>.<listcomp>c                 3   s   | ]}| kV  qd S r1   r<   rU   Zdiag_indgrpr<   r=   rX   /  s     zJArrayContraction._ArrayContraction_denest_ArrayDiagonal.<locals>.<genexpr>c                 S   s   g | ]}|d k	r|qS r1   r<   rU   r<   r<   r=   rY   4  s      )r   r   r%  r   r   r   rn   r   r   r   r   r   r   r   r   )rJ   r   r   r   Zdown_contraction_indicesr   Zcontr_indgrpr{  r]   Znew_diagonal_indices_downZnew_diagonal_indicesr<   r  r=   rY  #  s(    


z7ArrayContraction._ArrayContraction_denest_ArrayDiagonalc                    s   j d k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   rU   r   r<   r=   rY   @  s     z@ArrayContraction._sort_fully_contracted_args.<locals>.<listcomp>c                 S   s   h | ]}|D ]}|qqS r<   r<   rp   r<   r<   r=   r   A  s       z?ArrayContraction._sort_fully_contracted_args.<locals>.<setcomp>c              	      s8   g | ]0\}}t  fd dt| |d  D qS )c                 3   s   | ]}| kV  qd S r1   r<   r\   r  r<   r=   rX   B  s     JArrayContraction._sort_fully_contracted_args.<locals>.<listcomp>.<genexpr>rS   )r^   r[   r   )r   r   r<   r=   rY   B  s     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                    s   g | ]} j | qS r<   r   rU   r   r<   r=   rY   D  s     c                    s   g | ]} | D ]}|qqS r<   r<   rp   r   r<   r=   rY   E  s     
  c                    s"   g | ]}t  fd d|D qS )c                 3   s   | ]} | V  qd S r1   r<   r\   index_permutation_array_formr<   r=   rX   G  s     r  r   rU   r  r<   r=   rY   G  s     )r0   r   r   r   r[   rm   r   r   r   r,   r%   r   )rJ   r   r   new_posr   Znew_index_blocks_flatr   r<   )r   r   r   r  r   r  r=   rW  ;  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                    s   g | ]} fd d|D qS )c                    s   g | ]} | qS r<   r<   r\   mappingr<   r=   rY   h  s     zGArrayContraction._get_contraction_tuples.<locals>.<listcomp>.<listcomp>r<   rU   r  r<   r=   rY   h  s     z<ArrayContraction._get_contraction_tuples.<locals>.<listcomp>)rQ  r   rP   r<   r  r=   _get_contraction_tuplesK  s    z(ArrayContraction._get_contraction_tuplesc                    s*   | j }dgtt|   fdd|D S )Nr   c                    s"   g | ]}t  fd d|D qS )c                 3   s   | ]\}} | | V  qd S r1   r<   r  r   r<   r=   rX   o  s     zYArrayContraction._contraction_tuples_to_contraction_indices.<locals>.<listcomp>.<genexpr>r   rU   r   r<   r=   rY   o  s     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   )Z_free_indicesrP   r<   r<   r=   rz  q  s    zArrayContraction.free_indicesc                 C   s
   t | jS r1   )dictrR  rP   r<   r<   r=   rS  u  s    z)ArrayContraction.free_indices_to_positionc                 C   s
   | j d S rM   r   rP   r<   r<   r=   r   y  s    zArrayContraction.exprc                 C   s   | j dd  S rR   r   rP   r<   r<   r=   r   }  s    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   rS   )r   r2   r   r   r   r   r[   )r:   r   r   r  r   rW   rC  r]   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
|f| 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 rR   r   r   r<   r<   r=   r     r   z4ArrayContraction.sort_args_by_name.<locals>.<lambda>r   c                    s   i | ]\}}|  |qS r<   r  r   )
pos_sortedr<   r=   r     s      z6ArrayContraction.sort_args_by_name.<locals>.<dictcomp>c                    s   g | ]} fd d|D qS )c                    s   g | ]\}} | |fqS r<   r<   r  reordering_mapr<   r=   rY     s     zAArrayContraction.sort_args_by_name.<locals>.<listcomp>.<listcomp>r<   rU   r  r<   r=   rY     s     z6ArrayContraction.sort_args_by_name.<locals>.<listcomp>)r   r2   r   r   r   r   ro   r  r   r  r   )r:   r   r   Zsorted_datar   r  Zc_tpr  r<   )r  r  r=   sort_args_by_name  s    
z"ArrayContraction.sort_args_by_namec                 C   s   t | g| jf| j \}}|S )ao  
        Returns a dictionary of links between arguments in the tensor product
        being contracted.

        See the example for an explanation of the values.

        Examples
        ========

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

        Matrix multiplications are pairwise contractions between neighboring
        matrices:

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

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

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

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

        The argument in position 1 (that is, matrix `B`) has two contractions,
        the ones provided by the indices `j` and `k`, respectively the first
        and second indices (0 and 1 in the sub-dict).  The link `(0, 1)` and
        `(2, 0)` respectively. `(0, 1)` is the index slot 1 (the 2nd) of
        argument in position 0 (that is, `A_{\ldot j}`), and so on.
        )r(   r   r   )r:   r   Zdlinksr<   r<   r=   r(     s    )z'ArrayContraction._get_contraction_linksc                 C   s(   | j }t|dr| }t|f| j S r  )r   rk   rd   r   r   r  r<   r<   r=   rd     s    
zArrayContraction.as_explicitN)%r@   rA   rB   re   rI   r   r_  r`  rF  r  ru   r%  r   rX  rw  ry  r|  r~  r  r   rT  rU  rZ  rV  rY  rW  r  r  rg   rz  rS  r   r   r  r  r(   rd   r<   r<   r<   r=   r     sd   #




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   rs   r0   r_   r   rI   rh   r   _expr)rJ   r   r0   rL   r<   r<   r=   rI     s    

zReshape.__new__c                 C   s   | j S r1   r   rP   r<   r<   r=   r0     s    zReshape.shapec                 C   s   | j S r1   )r  rP   r<   r<   r=   r     s    zReshape.exprc                 O   sH   | ddr| jj||}n| j}t|ttfr<|j| j S t|| jS )Nr   T)	r   r   r   r2   r   r    rb   r0   r  )r:   r   r   r   r<   r<   r=   r     s    zReshape.doitc                 C   sR   | j }t|dr| }t|tr8ddlm} ||}nt|trF| S |j| j	 S )Nrd   r   )Array)
r   rk   rd   r2   r   Zsympyr  r   rb   r0   )r:   eer  r<   r<   r=   rd     s    



zReshape.as_explicitN)
r@   rA   rB   re   rI   rg   r0   r   r   rd   r<   r<   r<   r=   r    s   

	r  c                   @   sJ   e Zd ZU dZeee  ed< d	eeee   dddZdd Z	e	Z
dS )
rs  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.
    ri   Nri   c                 C   s2   || _ |d kr(dd tt|D | _n|| _d S )Nc                 S   s   g | ]}d qS r1   r<   rU   r<   r<   r=   rY   :  s     z"_ArgE.__init__.<locals>.<listcomp>)rK  r[   r   ri   )r:   rK  ri   r<   r<   r=   __init__7  s    z_ArgE.__init__c                 C   s   d| j | jf S )Nz_ArgE(%s, %s))rK  ri   rP   r<   r<   r=   __str__>  s    z_ArgE.__str__)N)r@   rA   rB   re   r   r   r&  rD   r  r  __repr__r<   r<   r<   r=   rs  %  s
   
rs  c                   @   s4   e Zd ZdZee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   relc                 C   s   || _ || _d S r1   r  )r:   r   r  r<   r<   r=   r  K  s    z_IndPos.__init__c                 C   s   d| j | jf S )Nz_IndPos(%i, %i)r  rP   r<   r<   r=   r  O  s    z_IndPos.__str__c                 c   s   | j | jgE d H  d S r1   r  rP   r<   r<   r=   __iter__T  s    z_IndPos.__iter__N)	r@   rA   rB   re   r&  r  r  r  r  r<   r<   r<   r=   r  D  s
   r  c                   @   s  e Zd ZdZejeeef dddZ	e
e
dddZdd	 Zd
d Zdd Zdd Zeee  dddZee dddZeee  dddZeedddZeee
 dddZedd Zdd Ze
e
d d!d"Ze
ejeef d#d$d%Ze
ejeef d#d&d'Zd(S ))rl  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}nt |trt |jtrlt|jj}|jj}t|jj|j}|jj}qt |jt	ri }|j}|j}g }qi }|j}|j}g }nt |t	r|}g }d}nt
 t |t	rt|j}n|g}dd |D }t|D ].\}}	|	D ] }
||
 \}}||| j|< q q|| _t|| _d | _t|j}t|D ]6\}}|D ]&}
||
 \}}d| | j| j|< qXqLd S )Nr<   c                 S   s   g | ]}t |qS r<   )rs  r   r<   r<   r=   rY     s     z2_EditArrayContraction.__init__.<locals>.<listcomp>r   )r2   r   r&   r   r   r   r   r%  r   r   r   r   r   r   ri   rn  rm   number_of_contraction_indices_track_permutation)r:   r  r  r   r   Zdiagonalizedr   rn  rW   Zcontraction_tupler]   Zarg_posZrel_posr   r<   r<   r=   r  g  sR    







z_EditArrayContraction.__init__)r   new_argc                 C   s"   | j |}| j |d | d S rR   )rn  r  insert)r:   r   r  posr<   r<   r=   rr    s    z"_EditArrayContraction.insert_afterc                 C   s   |  j d7  _ | j d S rR   )r  rP   r<   r<   r=   rp    s    z/_EditArrayContraction.get_new_contraction_indexc                    st   i  | j D ]} dd |jD  q
tt D ]\}}| |< q2t | _| j D ]} fdd|jD |_qTd S )Nc                 S   s   i | ]}|d k	r|dqS )Nr   r<   rU   r<   r<   r=   r     s       z9_EditArrayContraction.refresh_indices.<locals>.<dictcomp>c                    s   g | ]}  |d qS r1   )r   rU   Zupdatesr<   r=   rY     s     z9_EditArrayContraction.refresh_indices.<locals>.<listcomp>)rn  rg  ri   r   r   rm   r  )r:   arg_with_indrW   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rr| j t| n&ddlm	} ||| j d j
| j d _
d S )Nr   c                 S   s   g | ]
}|j qS r<   rK  rU   r<   r<   r=   rY     s     z7_EditArrayContraction.merge_scalars.<locals>.<listcomp>)_a2m_tensor_product)rn  rm   ri   r   remover   rs   rs  Z3sympy.tensor.array.expressions.from_array_to_matrixr  rK  )r:   Zscalarsr  rW   Zscalarr  r<   r<   r=   merge_scalars  s    
z#_EditArrayContraction.merge_scalarsc                 C   s  d}t t}t }| jD ]}|t|j q|d  }g }g }t }d}	| jD ]}d}
|jD ]}|d kr||	 |
d7 }
|	d7 }	q\|dkrq\|d|  ||
  || dkr||kr||d |  || n$||kr||d |  || |
d7 }
q\dd |jD |_|t	dd |jD 7 }qN|| }t
|}dd | D }|   |   dd | jD }|  }tt| f| }t|f| }| jd k	rt
d	d | jD }t||}t||}|S )
Nr   rS   r   c                 S   s$   g | ]}|d k	r|dkr|nd qS rM   r<   rU   r<   r<   r=   rY     s     z>_EditArrayContraction.to_array_contraction.<locals>.<listcomp>c                 S   s    g | ]}|d ks|dk r|qS rM   r<   rU   r<   r<   r=   rY     s       c                 S   s    g | ]}t |d krt|qS r   )rm   rh   )rV   r  r<   r<   r=   rY     s      c                 S   s   g | ]
}|j qS r<   r  r   r<   r<   r=   rY     s     c                 S   s   g | ]}|D ]}|qqS r<   r<   rp   r<   r<   r=   rY     s       )r   r   r   rn  rg  ri   r   r   r   rm   r,   valuesr  r  get_contraction_indicesr   r   r   r  r   )r:   r   Zdiag_indicesZcount_index_freqr  Zfree_index_countZ	inv_perm1Z	inv_perm2doneZcounter4counter2rW   r   r   Zdiag_indices_filteredr   r   r   Zexpr2Zpermutation2Zexpr3r<   r<   r=   rt    sX    







z*_EditArrayContraction.to_array_contraction)rF   c                 C   sR   dd t | jD }d}| jD ].}|jD ]"}|d k	rB|| | |d7 }q(q|S )Nc                 S   s   g | ]}g qS r<   r<   rU   r<   r<   r=   rY     s     zA_EditArrayContraction.get_contraction_indices.<locals>.<listcomp>r   rS   )r[   r  rn  ri   r   )r:   r   current_positionr  r]   r<   r<   r=   r    s    

z-_EditArrayContraction.get_contraction_indicesc                 C   sZ   || j krtdg }t| jD ]4\}}t|jD ] \}}||kr2|t|| q2q |S )Nz%index value exceeding the index range)r  r_   r   rn  ri   r   r  )r:   r{  r"  rW   r  r]   rv  r<   r<   r=   rm    s    
z+_EditArrayContraction.get_mapping_for_indexc                 C   s\   dd t | jD }t| jD ]8\}}t|jD ]$\}}|d k	r0|| t|| q0q|S )Nc                 S   s   g | ]}g qS r<   r<   rU   r<   r<   r=   rY     s     zP_EditArrayContraction.get_contraction_indices_to_ind_rel_pos.<locals>.<listcomp>)r[   r  r   rn  ri   r   r  )r:   r   rW   r  r]   r{  r<   r<   r=   &get_contraction_indices_to_ind_rel_pos  s    z<_EditArrayContraction.get_contraction_indices_to_ind_rel_pos)r  rF   c                 C   s&   d}| j D ]}||jkr
|d7 }q
|S )zJ
        Count the number of arguments that have the given index.
        r   rS   )rn  ri   )r:   r  r   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 kr|qS r<   r  rU   r  r<   r=   rY   -  s     
 z=_EditArrayContraction.get_args_with_index.<locals>.<listcomp>)rn  )r:   r  r  r<   r  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 k	r|dk r|qS rM   r<   rU   r<   r<   r=   r   4  s       zC_EditArrayContraction.number_of_diagonal_indices.<locals>.<setcomp>)r   rn  rg  ri   rm   )r:   rc   r   r<   r<   r=   number_of_diagonal_indices0  s    
z0_EditArrayContraction.number_of_diagonal_indicesc                    s   g }g }d}d}| j D ]T}g }|jD ]:}|d k	rL|dk r$|| |d8 }q$|| |d7 }q$|| q|rtdd |D nd  fdd|D }||g | _d S )Nr   r   rS   c                 s   s   | ]}|rt |nd V  qdS )r   Nr  rU   r<   r<   r=   rX   G  s     z@_EditArrayContraction.track_permutation_start.<locals>.<genexpr>c                    s   g | ]} | qS r<   r<   rU   Zmax_indr<   r=   rY   H  s     zA_EditArrayContraction.track_permutation_start.<locals>.<listcomp>)rn  ri   r   r  r  )r:   r   Z	perm_diagr   r  r  permrW   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   )rn  r  r  r   r   )r:   r  r  Zindex_destinationZindex_elementr<   r<   r=   track_permutation_mergeK  s    z-_EditArrayContraction.track_permutation_merge)r   rF   c                 C   sP   d}| j D ]8}tdd |jD }||kr:||| f  S ||7 }q
tddS )zw
        Return the range of the free indices of the arg as absolute positions
        among all free indices.
        r   c                 S   s   g | ]}|d kr|qS r1   r<   rU   r<   r<   r=   rY   X  s      zA_EditArrayContraction.get_absolute_free_range.<locals>.<listcomp>argument not foundNrn  rm   ri   rl   )r:   r   r   r  Znumber_free_indicesr<   r<   r=   get_absolute_free_rangeQ  s    

z-_EditArrayContraction.get_absolute_free_rangec                 C   sF   d}| j D ].}t|j}||kr0||| f  S ||7 }q
tddS )zc
        Return the absolute range of indices for arg, disregarding dummy
        indices.
        r   r  Nr  )r:   r   r   r  Znumber_indicesr<   r<   r=   ro  ^  s    


z(_EditArrayContraction.get_absolute_rangeN)r@   rA   rB   re   rf   Unionr   r   r   r  rs  rr  rp  r  r  rt  r   r&  r  r  rm  r  r  r  rg   r  r  r  r   r  ro  r<   r<   r<   r=   rl  X  s$   9
C



rl  c                 C   s   t | ttfrdS t | tr&t| jS t | tr8|  S t | trH| jS t | t	rl| j}|d krddS t|S t
| drt| jS dS )Nri  r   r0   r   )r2   r   r#   r~   rm   r0   r    rC  r!   r"   rk   rL  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 d 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<   )rk   r0   r   r<   r<   r=   r     s    
r   c                 C   s   t | tr|  S | S d S r1   )r2   r   r  r   r<   r<   r=   r    s    
r  c                  O   s   t | ddi|S Nr   T)r   r   r   r<   r<   r=   r     s    r   c                 O   s   t | f|ddi|S r  )r   )r   r   r   r<   r<   r=   r     s    r   c                 O   s   t | f|ddi|S r  )r   )r   r   r   r<   r<   r=   r     s    r   c                 K   s   t | |fddi|S r  r  )r   r   r   r<   r<   r=   r     s    r   c                  O   s   t | ddi|S r  )r   r  r<   r<   r=   r    s    r  c                 C   s
   t | |S r1   )r6   )r   ri   r<   r<   r=   r?     s    r?   )bcollections.abcr3   r|   r   r   	functoolsr   r`   r   rf   r   r   r   rC   Zsympy.core.numbersr	   Zsympy.core.relationalr
   Z(sympy.functions.special.tensor_functionsr   Zsympy.core.basicr   Zsympy.core.containersZsympy.core.exprr   Zsympy.core.functionr   r   Zsympy.core.mulr   Zsympy.core.singletonr   Zsympy.core.sortingr   Zsympy.core.symbolr   r   Zsympy.matrices.matrixbaser   Z#sympy.matrices.expressions.diagonalr   Z"sympy.matrices.expressions.matexprr   Z"sympy.matrices.expressions.specialr   Zsympy.tensor.array.arrayopr   r   r   r   Z#sympy.tensor.array.dense_ndim_arrayr   Zsympy.tensor.array.ndim_arrayr    Zsympy.tensor.indexedr!   r"   r#   Z$sympy.tensor.array.expressions.utilsr$   r%   r&   r'   r(   r)   r   r+   Z sympy.combinatorics.permutationsr,   Zsympy.core.sympifyr.   r/   rE   r6   rv   rz   r~   r   r   r   r   rG  r   r  rs  r  rl  r   r   r!  r   r  r   r   r   r   r  r?   r<   r<   r<   r=   <module>   s    5/Z;  Y Q)    ?  