o
    jgG                     @   s   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 d d	lmZmZ d d
lmZ dd Zdd Zdd Zdd Zdd Zdd ZdddZG dd deZdS )    N)Iterable)	Printable)Tuplediff)S)_sympify	NDimArray)DenseNDimArrayImmutableDenseNDimArraySparseNDimArrayc                 C   s8   ddl m} t| tr| S t| |tttfrt| S | S )Nr   
MatrixBase)sympy.matricesr   
isinstancer
   listtupler   r   )ar    r   R/var/www/html/zoom/venv/lib/python3.10/site-packages/sympy/tensor/array/arrayop.py_arrayfy   s   
r   c                     sX  ddl m}m} t| dkrtjS t| dkrt| d S ddlm ddlm	} ddlm
 ddlm  t fdd	| D rF||  S t| d
kr_tt| d | d g| d
d R  S tt| \}t|trpttst| S t||rt|rtfdd|j D }|||jj S fddt|D }t||jj S )a  
    Tensor product among scalars or array-like objects.

    The equivalent operator for array expressions is ``ArrayTensorProduct``,
    which can be used to keep the expression unevaluated.

    Examples
    ========

    >>> from sympy.tensor.array import tensorproduct, Array
    >>> from sympy.abc import x, y, z, t
    >>> A = Array([[1, 2], [3, 4]])
    >>> B = Array([x, y])
    >>> tensorproduct(A, B)
    [[[x, y], [2*x, 2*y]], [[3*x, 3*y], [4*x, 4*y]]]
    >>> tensorproduct(A, x)
    [[x, 2*x], [3*x, 4*x]]
    >>> tensorproduct(A, B, B)
    [[[[x**2, x*y], [x*y, y**2]], [[2*x**2, 2*x*y], [2*x*y, 2*y**2]]], [[[3*x**2, 3*x*y], [3*x*y, 3*y**2]], [[4*x**2, 4*x*y], [4*x*y, 4*y**2]]]]

    Applying this function on two matrices will result in a rank 4 array.

    >>> from sympy import Matrix, eye
    >>> m = Matrix([[x, y], [z, t]])
    >>> p = tensorproduct(eye(3), m)
    >>> p
    [[[[x, y], [z, t]], [[0, 0], [0, 0]], [[0, 0], [0, 0]]], [[[0, 0], [0, 0]], [[x, y], [z, t]], [[0, 0], [0, 0]]], [[[0, 0], [0, 0]], [[0, 0], [0, 0]], [[x, y], [z, t]]]]

    See Also
    ========

    sympy.tensor.array.expressions.array_expressions.ArrayTensorProduct

    r   )r   ImmutableSparseNDimArray   _CodegenArrayAbstract)ArrayTensorProduct
_ArrayExprMatrixSymbolc                 3   s     | ]}t | fV  qd S N)r   ).0arg)r!   r   r   r   r   	<genexpr>F   s    z tensorproduct.<locals>.<genexpr>   Nc                    s6   i | ]\}} j  D ]\}}| | || qqS r   )_sparse_arrayitems)r#   k1v1k2v2)blpr   r   
<dictcomp>S   s   6 z!tensorproduct.<locals>.<dictcomp>c                    s"   g | ]}t  D ]}|| qqS r   Flatten)r#   ij)r-   r   r   
<listcomp>V      " z!tensorproduct.<locals>.<listcomp>)sympy.tensor.arrayr   r   lenr   Oner   0sympy.tensor.array.expressions.array_expressionsr   r   r   "sympy.matrices.expressions.matexprr!   anytensorproductmapr   r
   r'   r(   shaper1   r   )argsr   r   r   r   	new_arrayproduct_listr   )r!   r   r   r-   r.   r   r<      s,   #&r<   c                    sP  t   t |D ]/}t|tstd j|d  }|D ]}|v r'td| j| kr2td| qq	  }fddt jD }dg| d}t	|D ]}||| d < |t
 j|| d  9 }qT fddt	|D }	g }
|D ]$}g }t	 j|d  D ]|tfd	d
|D  q|
| q} |	||
fS )Nz1collections of contraction/diagonal axes expectedr   z"dimension specified more than oncezBcannot contract or diagonalize between axes of different dimensionc                    s   g | ]
\}}| vr|qS r   r   )r#   r2   dim)
taken_dimsr   r   r4   n   s    z._util_contraction_diagonal.<locals>.<listcomp>r   c                    s2   g | ]  vr fd dt j  D qS )c                    s   g | ]}  | qS r   r   )r#   r3   )	cum_shaper2   r   r   r4   |   s    z9_util_contraction_diagonal.<locals>.<listcomp>.<listcomp>)ranger>   r#   )arrayrD   rC   )r2   r   r4   |   s    
c                 3   s    | ]	} |  V  qd S r"   r   )r#   ig)rD   jsr   r   r%          z-_util_contraction_diagonal.<locals>.<genexpr>)r   setr   r   
ValueErrorr>   addrank	enumeraterE   intappendsum)rG   contraction_or_diagonal_axes
axes_grouprB   drN   remaining_shape_cumulr2   remaining_indicessummed_deltaslidxr   )rG   rD   rI   rC   r   _util_contraction_diagonalZ   s<   

	 r[   c                 G   s   ddl m} ddl m} ddl m} ddlm} t| |||fr(|| g|R  S t| g|R  \} }}}g }	tj	| D ]%}
t
|
}tj}tj	| D ]}| |t
| }|| | 7 }qI|	| q;t|dkrst|	dksoJ |	d S t| |	|S )a  
    Contraction of an array-like object on the specified axes.

    The equivalent operator for array expressions is ``ArrayContraction``,
    which can be used to keep the expression unevaluated.

    Examples
    ========

    >>> from sympy import Array, tensorcontraction
    >>> from sympy import Matrix, eye
    >>> tensorcontraction(eye(3), (0, 1))
    3
    >>> A = Array(range(18), (3, 2, 3))
    >>> A
    [[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]], [[12, 13, 14], [15, 16, 17]]]
    >>> tensorcontraction(A, (0, 2))
    [21, 30]

    Matrix multiplication may be emulated with a proper combination of
    ``tensorcontraction`` and ``tensorproduct``

    >>> from sympy import tensorproduct
    >>> from sympy.abc import a,b,c,d,e,f,g,h
    >>> m1 = Matrix([[a, b], [c, d]])
    >>> m2 = Matrix([[e, f], [g, h]])
    >>> p = tensorproduct(m1, m2)
    >>> p
    [[[[a*e, a*f], [a*g, a*h]], [[b*e, b*f], [b*g, b*h]]], [[[c*e, c*f], [c*g, c*h]], [[d*e, d*f], [d*g, d*h]]]]
    >>> tensorcontraction(p, (1, 2))
    [[a*e + b*g, a*f + b*h], [c*e + d*g, c*f + d*h]]
    >>> m1*m2
    Matrix([
    [a*e + b*g, a*f + b*h],
    [c*e + d*g, c*f + d*h]])

    See Also
    ========

    sympy.tensor.array.expressions.array_expressions.ArrayContraction

    r   )_array_contractionr   r   r    r   )r9   r\   r   r   r:   r!   r   r[   	itertoolsproductrR   r   Zero_get_tuple_indexrQ   r7   type)rG   contraction_axesr\   r   r   r!   rX   rV   rY   contracted_arrayicontribindex_base_positionisumsum_to_indexidxr   r   r   tensorcontraction   s&   +
ri   c                 G   s$  t dd |D rtdddlm} ddlm} ddlm}m} ddlm} t	| |||fr7|| g|R  S |j
| g|R   t| g|R  \} }}}	g }
d	d
 |	D }tj| D ].}t|}g }tj|	 D ]}| |t| }|| |  qgt| |j| }|
| qZt| |
|| S )aP  
    Diagonalization of an array-like object on the specified axes.

    This is equivalent to multiplying the expression by Kronecker deltas
    uniting the axes.

    The diagonal indices are put at the end of the axes.

    The equivalent operator for array expressions is ``ArrayDiagonal``, which
    can be used to keep the expression unevaluated.

    Examples
    ========

    ``tensordiagonal`` acting on a 2-dimensional array by axes 0 and 1 is
    equivalent to the diagonal of the matrix:

    >>> from sympy import Array, tensordiagonal
    >>> from sympy import Matrix, eye
    >>> tensordiagonal(eye(3), (0, 1))
    [1, 1, 1]

    >>> from sympy.abc import a,b,c,d
    >>> m1 = Matrix([[a, b], [c, d]])
    >>> tensordiagonal(m1, [0, 1])
    [a, d]

    In case of higher dimensional arrays, the diagonalized out dimensions
    are appended removed and appended as a single dimension at the end:

    >>> A = Array(range(18), (3, 2, 3))
    >>> A
    [[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]], [[12, 13, 14], [15, 16, 17]]]
    >>> tensordiagonal(A, (0, 2))
    [[0, 7, 14], [3, 10, 17]]
    >>> from sympy import permutedims
    >>> tensordiagonal(A, (0, 2)) == permutedims(Array([A[0, :, 0], A[1, :, 1], A[2, :, 2]]), [1, 0])
    True

    See Also
    ========

    sympy.tensor.array.expressions.array_expressions.ArrayDiagonal

    c                 s   s    | ]	}t |d kV  qdS )r   Nr7   r#   r2   r   r   r   r%     rJ   z!tensordiagonal.<locals>.<genexpr>z%need at least two axes to diagonalizer   r   r   )ArrayDiagonal_array_diagonalr    c                 S      g | ]}t |qS r   rj   rk   r   r   r   r4         z"tensordiagonal.<locals>.<listcomp>)r;   rL   r9   r   r   rl   rm   r:   r!   r   	_validater[   r]   r^   rR   r`   rQ   ra   reshape)rG   diagonal_axesr   r   rl   rm   r!   rX   rV   diagonal_deltasdiagonalized_arraydiagonal_shaperd   re   rf   rg   rh   r   r   r   tensordiagonal   s*   .
rv   c                    s$  ddl m} ddlm} t|tf}t||r&t|}|D ]	}|js%t	dqt |rqt tr5 
  nt  t||rlt |rVt  fddtt|D }n fddt|D }t ||j j S  |S t  t||rt fd	dt|D |jS t|}t |S )
a  
    Derivative by arrays. Supports both arrays and scalars.

    The equivalent operator for array expressions is ``array_derive``.

    Explanation
    ===========

    Given the array `A_{i_1, \ldots, i_N}` and the array `X_{j_1, \ldots, j_M}`
    this function will return a new array `B` defined by

    `B_{j_1,\ldots,j_M,i_1,\ldots,i_N} := \frac{\partial A_{i_1,\ldots,i_N}}{\partial X_{j_1,\ldots,j_M}}`

    Examples
    ========

    >>> from sympy import derive_by_array
    >>> from sympy.abc import x, y, z, t
    >>> from sympy import cos
    >>> derive_by_array(cos(x*t), x)
    -t*sin(t*x)
    >>> derive_by_array(cos(x*t), [x, y, z, t])
    [-t*sin(t*x), 0, 0, -x*sin(t*x)]
    >>> derive_by_array([x, y**2*z], [[x, y], [z, t]])
    [[[1, 0], [0, 2*y*z]], [[0, y**2], [0, 0]]]

    r   r   r   zcannot derive by this arrayc                    s8   i | ]\}}  |j D ]\}}||  |qqS r   )r   r'   r(   )r#   r2   xkvexprr.   r   r   r/   Y  s    z#derive_by_array.<locals>.<dictcomp>c                    s"   g | ]  fd dt D qS )c                    s   g | ]}|  qS r   r   )r#   yrw   r   r   r4   ]      z.derive_by_array.<locals>.<listcomp>.<listcomp>r0   rF   r{   r}   r   r4   ]  r5   z#derive_by_array.<locals>.<listcomp>c                    s   g | ]}  |qS r   r   rk   r   r   r   r4   d  r~   )r   r   r6   r   r   r
   r   r   	_diff_wrtrL   as_immutabler7   rO   r1   ra   r>   r   r   )r{   dxr   r   array_typesr2   r@   r   rz   r   derive_by_array*  s6   










r   c                    sf  ddl m} ddlm} ddlm} ddlm} ddlm} ddlm	}	 ddlm
}
 |	|||
 t |||frA| S t tsJt  dd	lm} t|s[|tj  krftd
 } j}t |rt  fdd j D |S dd  jD }dgt  }ttj| D ]\}}||} | ||< qt ||S )a?  
    Permutes the indices of an array.

    Parameter specifies the permutation of the indices.

    The equivalent operator for array expressions is ``PermuteDims``, which can
    be used to keep the expression unevaluated.

    Examples
    ========

    >>> from sympy.abc import x, y, z, t
    >>> from sympy import sin
    >>> from sympy import Array, permutedims
    >>> a = Array([[x, y, z], [t, sin(x), 0]])
    >>> a
    [[x, y, z], [t, sin(x), 0]]
    >>> permutedims(a, (1, 0))
    [[x, t], [y, sin(x)], [z, 0]]

    If the array is of second order, ``transpose`` can be used:

    >>> from sympy import transpose
    >>> transpose(a)
    [[x, t], [y, sin(x)], [z, 0]]

    Examples on higher dimensions:

    >>> b = Array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
    >>> permutedims(b, (2, 1, 0))
    [[[1, 5], [3, 7]], [[2, 6], [4, 8]]]
    >>> permutedims(b, (1, 2, 0))
    [[[1, 5], [2, 6]], [[3, 7], [4, 8]]]

    An alternative way to specify the same permutations as in the previous
    lines involves passing the *old* and *new* indices, either as a list or as
    a string:

    >>> permutedims(b, index_order_old="cba", index_order_new="abc")
    [[[1, 5], [3, 7]], [[2, 6], [4, 8]]]
    >>> permutedims(b, index_order_old="cab", index_order_new="abc")
    [[[1, 5], [2, 6]], [[3, 7], [4, 8]]]

    ``Permutation`` objects are also allowed:

    >>> from sympy.combinatorics import Permutation
    >>> permutedims(b, Permutation([1, 2, 0]))
    [[[1, 5], [2, 6]], [[3, 7], [4, 8]]]

    See Also
    ========

    sympy.tensor.array.expressions.array_expressions.PermuteDims

    r   r   r   r   )_permute_dimsr    )PermuteDims)get_rank)Permutationzwrong permutation sizec                    s$   i | ]\}}t  ||qS r   )r   r`   )r#   rx   ry   r{   permr   r   r/     s    zpermutedims.<locals>.<dictcomp>c                 S   rn   r   )rE   rk   r   r   r   r4     ro   zpermutedims.<locals>.<listcomp>N)r6   r   r9   r   r   r   r:   r!   sympy.tensor.array.expressionsr   r   _get_permutation_from_argumentsr   r
   r   sympy.combinatoricsr   r   sizerN   rL   r>   ra   r'   r(   r7   rO   r]   r^   )r{   r   index_order_oldindex_order_newr   r   r   r   r!   r   r   r   iperm	new_shapeindices_spanr@   r2   rh   tr   r   r   permutedimsj  s>   8




r   c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )r1   aO  
    Flatten an iterable object to a list in a lazy-evaluation way.

    Notes
    =====

    This class is an iterator with which the memory cost can be economised.
    Optimisation has been considered to ameliorate the performance for some
    specific data types like DenseNDimArray and SparseNDimArray.

    Examples
    ========

    >>> from sympy.tensor.array.arrayop import Flatten
    >>> from sympy.tensor.array import Array
    >>> A = Array(range(6)).reshape(2, 3)
    >>> Flatten(A)
    Flatten([[0, 1, 2], [3, 4, 5]])
    >>> [i for i in Flatten(A)]
    [0, 1, 2, 3, 4, 5]
    c                 C   sP   ddl m} ddlm} t|t|fstdt|tr ||}|| _d| _	d S )Nr   r   r	   zData type not yet supported)
sympy.matrices.matrixbaser   r6   r
   r   r   NotImplementedErrorr   _iter_idx)selfiterabler   r
   r   r   r   __init__  s   

zFlatten.__init__c                 C   s   | S r"   r   r   r   r   r   __iter__  s   zFlatten.__iter__c                 C   s   ddl m} t| j| jkrTt| jtr| jj| j }n:t| jtr4| j| jj	v r1| jj	| j }n%d}n"t| j|rA| j| j }nt
| jdrMt| j}n	| j| j }nt|  jd7  _|S )Nr   r   __next__r   )r   r   r7   r   r   r   r   _arrayr   r'   hasattrnextStopIteration)r   r   resultr   r   r   r     s    zFlatten.__next__c                 C   s   |   S r"   )r   r   r   r   r   r     s   zFlatten.nextc                 C   s   t | jd || j d S )N())ra   __name___printr   )r   printerr   r   r   	_sympystr  s   zFlatten._sympystrN)	r   
__module____qualname____doc__r   r   r   r   r   r   r   r   r   r1     s    r1   )NNN)r]   collections.abcr   sympy.core._print_helpersr   sympy.core.containersr   sympy.core.functionr   sympy.core.singletonr   sympy.core.sympifyr   sympy.tensor.array.ndim_arrayr
   #sympy.tensor.array.dense_ndim_arrayr   r   $sympy.tensor.array.sparse_ndim_arrayr   r   r<   r[   ri   rv   r   r   r1   r   r   r   r   <module>   s$    
A0MS
@`