o
    8Va~4                     @   sJ  d Z ddlmZ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 ddlmZ dd	lmZmZmZmZmZmZ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# dd Z$G dd de
Z%dd Z&dd Z'dd Z(dd Z)ee)ee'fZ*eedd ee* Z+dd Z,d d! Z-d"d# Z.d$d% Z/d&d' Z0d(S ))z'Implementation of the Kronecker product    )Mulprodsympify)adjoint)
ShapeError)
MatrixExpr)	transpose)Identity)
MatrixBase)canon	condition
distributedo_oneexhaustflattentypedunpack)	bottom_up)sift   )MatAdd)MatMul)MatPowc                  G   s4   | st dt|   t| dkr| d S t|   S )af  
    The Kronecker product of two or more arguments.

    This computes the explicit Kronecker product for subclasses of
    ``MatrixBase`` i.e. explicit matrices. Otherwise, a symbolic
    ``KroneckerProduct`` object is returned.


    Examples
    ========

    For ``MatrixSymbol`` arguments a ``KroneckerProduct`` object is returned.
    Elements of this matrix can be obtained by indexing, or for MatrixSymbols
    with known dimension the explicit matrix can be obtained with
    ``.as_explicit()``

    >>> from sympy.matrices import kronecker_product, MatrixSymbol
    >>> A = MatrixSymbol('A', 2, 2)
    >>> B = MatrixSymbol('B', 2, 2)
    >>> kronecker_product(A)
    A
    >>> kronecker_product(A, B)
    KroneckerProduct(A, B)
    >>> kronecker_product(A, B)[0, 1]
    A[0, 0]*B[0, 1]
    >>> kronecker_product(A, B).as_explicit()
    Matrix([
        [A[0, 0]*B[0, 0], A[0, 0]*B[0, 1], A[0, 1]*B[0, 0], A[0, 1]*B[0, 1]],
        [A[0, 0]*B[1, 0], A[0, 0]*B[1, 1], A[0, 1]*B[1, 0], A[0, 1]*B[1, 1]],
        [A[1, 0]*B[0, 0], A[1, 0]*B[0, 1], A[1, 1]*B[0, 0], A[1, 1]*B[0, 1]],
        [A[1, 0]*B[1, 0], A[1, 0]*B[1, 1], A[1, 1]*B[1, 0], A[1, 1]*B[1, 1]]])

    For explicit matrices the Kronecker product is returned as a Matrix

    >>> from sympy.matrices import Matrix, kronecker_product
    >>> sigma_x = Matrix([
    ... [0, 1],
    ... [1, 0]])
    ...
    >>> Isigma_y = Matrix([
    ... [0, 1],
    ... [-1, 0]])
    ...
    >>> kronecker_product(sigma_x, Isigma_y)
    Matrix([
    [ 0, 0,  0, 1],
    [ 0, 0, -1, 0],
    [ 0, 1,  0, 0],
    [-1, 0,  0, 0]])

    See Also
    ========
        KroneckerProduct

    z$Empty Kronecker product is undefinedr   r   )	TypeErrorvalidatelenKroneckerProductdoit)matrices r   F/usr/lib/python3/dist-packages/sympy/matrices/expressions/kronecker.pykronecker_product   s   8r!   c                       s   e Zd ZdZdZdd fdd
Zedd Zdd	 Zd
d Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Z  ZS )"r   a  
    The Kronecker product of two or more arguments.

    The Kronecker product is a non-commutative product of matrices.
    Given two matrices of dimension (m, n) and (s, t) it produces a matrix
    of dimension (m s, n t).

    This is a symbolic object that simply stores its argument without
    evaluating it. To actually compute the product, use the function
    ``kronecker_product()`` or call the the ``.doit()`` or  ``.as_explicit()``
    methods.

    >>> from sympy.matrices import KroneckerProduct, MatrixSymbol
    >>> A = MatrixSymbol('A', 5, 5)
    >>> B = MatrixSymbol('B', 5, 5)
    >>> isinstance(KroneckerProduct(A, B), KroneckerProduct)
    True
    T)checkc                   st   t tt|}tdd |D r*ttdd |D }tdd |D r(| S |S |r0t|  t j	| g|R  S )Nc                 s       | ]}|j V  qd S N)Zis_Identity.0ar   r   r    	<genexpr>m       z+KroneckerProduct.__new__.<locals>.<genexpr>c                 s   r#   r$   rowsr%   r   r   r    r(   n   r)   c                 s       | ]}t |tV  qd S r$   
isinstancer
   r%   r   r   r    r(   o       )
listmapr   allr	   r   Zas_explicitr   super__new__)clsr"   argsret	__class__r   r    r4   k   s   zKroneckerProduct.__new__c                 C   s@   | j d j\}}| j dd  D ]}||j9 }||j9 }q||fS )Nr   r   )r6   shaper+   cols)selfr+   r;   matr   r   r    r:   x   s
   
zKroneckerProduct.shapec                 K   sH   d}t | jD ]}t||j\}}t||j\}}||||f 9 }q|S Nr   )reversedr6   divmodr+   r;   )r<   ijkwargsresultr=   mnr   r   r    _entry   s   zKroneckerProduct._entryc                 C      t ttt| j  S r$   )r   r0   r1   r   r6   r   r<   r   r   r    _eval_adjoint      zKroneckerProduct._eval_adjointc                 C   s   t dd | jD   S )Nc                 S      g | ]}|  qS r   )	conjugater%   r   r   r    
<listcomp>       z4KroneckerProduct._eval_conjugate.<locals>.<listcomp>)r   r6   r   rI   r   r   r    _eval_conjugate   rK   z KroneckerProduct._eval_conjugatec                 C   rH   r$   )r   r0   r1   r   r6   r   rI   r   r   r    _eval_transpose   rK   z KroneckerProduct._eval_transposec                    s$   ddl m   t fdd| jD S )Nr   tracec                 3   s    | ]} |V  qd S r$   r   r%   rR   r   r    r(      s    z/KroneckerProduct._eval_trace.<locals>.<genexpr>)rS   r   r6   rI   r   rR   r    _eval_trace   s   zKroneckerProduct._eval_tracec                    sL   ddl m m} tdd | jD s|| S | jt fdd| jD S )Nr   )detDeterminantc                 s   r#   r$   Z	is_squarer%   r   r   r    r(      r)   z5KroneckerProduct._eval_determinant.<locals>.<genexpr>c                 3   s"    | ]} ||j   V  qd S r$   r*   r%   rU   rE   r   r    r(      s     )ZdeterminantrU   rV   r2   r6   r+   r   )r<   rV   r   rX   r    _eval_determinant   s
   z"KroneckerProduct._eval_determinantc                 C   s>   zt dd | jD  W S  ty   ddlm} ||  Y S w )Nc                 S   rL   r   )Zinverser%   r   r   r    rN      rO   z2KroneckerProduct._eval_inverse.<locals>.<listcomp>r   )Inverse)r   r6   r   Z"sympy.matrices.expressions.inverserZ   )r<   rZ   r   r   r    _eval_inverse   s   zKroneckerProduct._eval_inversec                 C   sF   t |to"| j|jko"t| jt|jko"tdd t| j|jD S )a  Determine whether two matrices have the same Kronecker product structure

        Examples
        ========

        >>> from sympy import KroneckerProduct, MatrixSymbol, symbols
        >>> m, n = symbols(r'm, n', integer=True)
        >>> A = MatrixSymbol('A', m, m)
        >>> B = MatrixSymbol('B', n, n)
        >>> C = MatrixSymbol('C', m, m)
        >>> D = MatrixSymbol('D', n, n)
        >>> KroneckerProduct(A, B).structurally_equal(KroneckerProduct(C, D))
        True
        >>> KroneckerProduct(A, B).structurally_equal(KroneckerProduct(D, C))
        False
        >>> KroneckerProduct(A, B).structurally_equal(C)
        False
        c                 s   s     | ]\}}|j |j kV  qd S r$   r:   r&   r'   br   r   r    r(          z6KroneckerProduct.structurally_equal.<locals>.<genexpr>)r.   r   r:   r   r6   r2   zipr<   otherr   r   r    structurally_equal   s   

z#KroneckerProduct.structurally_equalc                 C   sF   t |to"| j|jko"t| jt|jko"tdd t| j|jD S )aq  Determine whether two matrices have the appropriate structure to bring matrix
        multiplication inside the KroneckerProdut

        Examples
        ========
        >>> from sympy import KroneckerProduct, MatrixSymbol, symbols
        >>> m, n = symbols(r'm, n', integer=True)
        >>> A = MatrixSymbol('A', m, n)
        >>> B = MatrixSymbol('B', n, m)
        >>> KroneckerProduct(A, B).has_matching_shape(KroneckerProduct(B, A))
        True
        >>> KroneckerProduct(A, B).has_matching_shape(KroneckerProduct(A, B))
        False
        >>> KroneckerProduct(A, B).has_matching_shape(A)
        False
        c                 s   s     | ]\}}|j |jkV  qd S r$   )r;   r+   r]   r   r   r    r(      r_   z6KroneckerProduct.has_matching_shape.<locals>.<genexpr>)r.   r   r;   r+   r   r6   r2   r`   ra   r   r   r    has_matching_shape   s   

z#KroneckerProduct.has_matching_shapec                 K   s   t tttttti| S r$   )r   r   r   r   r   r   )r<   Zhintsr   r   r    _eval_expand_kroneckerproduct   s   z.KroneckerProduct._eval_expand_kroneckerproductc                 C   s0   |  |r| jdd t| j|jD  S | | S )Nc                 S   s   g | ]\}}|| qS r   r   r]   r   r   r    rN          z3KroneckerProduct._kronecker_add.<locals>.<listcomp>)rc   r9   r`   r6   ra   r   r   r    _kronecker_add      
zKroneckerProduct._kronecker_addc                 C   s0   |  |r| jdd t| j|jD  S | | S )Nc                 S   s   g | ]\}}|| qS r   r   r]   r   r   r    rN      rf   z3KroneckerProduct._kronecker_mul.<locals>.<listcomp>)rd   r9   r`   r6   ra   r   r   r    _kronecker_mul   rh   zKroneckerProduct._kronecker_mulc                    s8     dd}|r fdd| jD }n| j}tt| S )NdeepTc                    s   g | ]
}|j d i  qS )r   )r   r&   argrC   r   r    rN      s    z)KroneckerProduct.doit.<locals>.<listcomp>)getr6   canonicalizer   )r<   rC   rj   r6   r   rm   r    r      s
   zKroneckerProduct.doit)__name__
__module____qualname____doc__Zis_KroneckerProductr4   propertyr:   rG   rJ   rP   rQ   rT   rY   r[   rc   rd   re   rg   ri   r   __classcell__r   r   r8   r    r   V   s&    
r   c                  G   s   t dd | D stdd S )Nc                 s   r#   r$   )Z	is_Matrixrk   r   r   r    r(      r)   zvalidate.<locals>.<genexpr>z Mix of Matrix and Scalar symbols)r2   r   )r6   r   r   r    r      s   r   c                 C   sZ   g }g }| j D ]}| \}}|| |t| qt| }|dkr+|t|  S | S r>   )r6   Zargs_cncextendappendr   Z
_from_argsr   )kronZc_partZnc_partrl   cZncr   r   r    extract_commutative   s   

rz   c            
   	   G   s   t dd | D stdt|  | d }t| dd D ]=}|j}|j}t|D ].}||||   }t|d D ]}||||| | d   }q9|dkrR|}q)||}q)|}qt	| dd	 d
j
}	t||	rk|S |	|S )a  Compute the Kronecker product of a sequence of SymPy Matrices.

    This is the standard Kronecker product of matrices [1].

    Parameters
    ==========

    matrices : tuple of MatrixBase instances
        The matrices to take the Kronecker product of.

    Returns
    =======

    matrix : MatrixBase
        The Kronecker product matrix.

    Examples
    ========

    >>> from sympy import Matrix
    >>> from sympy.matrices.expressions.kronecker import (
    ... matrix_kronecker_product)

    >>> m1 = Matrix([[1,2],[3,4]])
    >>> m2 = Matrix([[1,0],[0,1]])
    >>> matrix_kronecker_product(m1, m2)
    Matrix([
    [1, 0, 2, 0],
    [0, 1, 0, 2],
    [3, 0, 4, 0],
    [0, 3, 0, 4]])
    >>> matrix_kronecker_product(m2, m1)
    Matrix([
    [1, 2, 0, 0],
    [3, 4, 0, 0],
    [0, 0, 1, 2],
    [0, 0, 3, 4]])

    References
    ==========

    [1] https://en.wikipedia.org/wiki/Kronecker_product
    c                 s   r,   r$   r-   r&   rE   r   r   r    r(   -  r/   z+matrix_kronecker_product.<locals>.<genexpr>z&Sequence of Matrices expected, got: %sNr   r   c                 S   s   | j S r$   )Z_class_priority)Mr   r   r    <lambda>I  s    z*matrix_kronecker_product.<locals>.<lambda>)key)r2   r   reprr?   r+   r;   rangeZrow_joinZcol_joinmaxr9   r.   )
r   Zmatrix_expansionr=   r+   r;   rA   startrB   nextZMatrixClassr   r   r    matrix_kronecker_product   s,   -

r   c                 C   s"   t dd | jD s| S t| j S )Nc                 s   r,   r$   r-   r{   r   r   r    r(   R  r/   z-explicit_kronecker_product.<locals>.<genexpr>)r2   r6   r   )rx   r   r   r    explicit_kronecker_productP  s   
r   c                 C   s
   t | tS r$   )r.   r   )xr   r   r    r~   ]     
 r~   c                 C   s"   t | trtdd | jD S dS )Nc                 s   r#   r$   r\   r%   r   r   r    r(   c  r)   z&_kronecker_dims_key.<locals>.<genexpr>r   )r.   r   tupler6   exprr   r   r    _kronecker_dims_keya  s   
r   c                    sZ   ddl m  t| jt}|dd }|s| S  fdd| D }|s't| S t| | S )Nr   reducer   c                    s   g | ]	} d d |qS )c                 S   s
   |  |S r$   )rg   )r   yr   r   r    r~   o  r   z.kronecker_mat_add.<locals>.<listcomp>.<lambda>r   )r&   groupr   r   r    rN   o  s    z%kronecker_mat_add.<locals>.<listcomp>)	functoolsr   r   r6   r   popvaluesr   )r   r6   ZnonkronsZkronsr   r   r    kronecker_mat_addh  s   
r   c                 C   s   |   \}}d}|t|d k r?|||d  \}}t|tr3t|tr3||||< ||d  n|d7 }|t|d k s|t|  S )Nr   r      )Zas_coeff_matricesr   r.   r   ri   r   r   )r   Zfactorr   rA   ABr   r   r    kronecker_mat_mulx  s   r   c                    s@   t  jtrtdd  jjD rt fdd jjD  S  S )Nc                 s   r#   r$   rW   r%   r   r   r    r(     r)   z$kronecker_mat_pow.<locals>.<genexpr>c                    s   g | ]}t | jqS r   )r   Zexpr%   r   r   r    rN     rf   z%kronecker_mat_pow.<locals>.<listcomp>)r.   baser   r2   r6   r   r   r   r    kronecker_mat_pow  s   "r   c                 C   sT   dd }t tt t|ttttttt	i}|| }t
|dd}|dur(| S |S )a-  Combine KronekeckerProduct with expression.

    If possible write operations on KroneckerProducts of compatible shapes
    as a single KroneckerProduct.

    Examples
    ========

    >>> from sympy.matrices.expressions import MatrixSymbol, KroneckerProduct, combine_kronecker
    >>> from sympy import symbols
    >>> m, n = symbols(r'm, n', integer=True)
    >>> A = MatrixSymbol('A', m, n)
    >>> B = MatrixSymbol('B', n, m)
    >>> combine_kronecker(KroneckerProduct(A, B)*KroneckerProduct(B, A))
    KroneckerProduct(A*B, B*A)
    >>> combine_kronecker(KroneckerProduct(A, B)+KroneckerProduct(B.T, A.T))
    KroneckerProduct(A + B.T, B + A.T)
    >>> C = MatrixSymbol('C', n, n)
    >>> D = MatrixSymbol('D', m, m)
    >>> combine_kronecker(KroneckerProduct(C, D)**m)
    KroneckerProduct(C**m, D**m)
    c                 S   s   t | to	| tS r$   )r.   r   Zhasr   r   r   r   r    haskron  s   z"combine_kronecker.<locals>.haskronr   N)r   r   r   r   r   r   r   r   r   r   getattr)r   r   ZrulerD   r   r   r   r    combine_kronecker  s   
r   N)1rs   Z
sympy.corer   r   r   Zsympy.functionsr   Zsympy.matrices.commonr   Z"sympy.matrices.expressions.matexprr   Z$sympy.matrices.expressions.transposer   Z"sympy.matrices.expressions.specialr	   Zsympy.matrices.matricesr
   Zsympy.strategiesr   r   r   r   r   r   r   r   Zsympy.strategies.traverser   Zsympy.utilitiesr   Zmataddr   matmulr   Zmatpowr   r!   r   r   rz   r   r   Zrulesro   r   r   r   r   r   r   r   r   r    <module>   sD    (A P
