B
    [0                 @   s^  d Z ddlmZmZ ddl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mZ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/ Z0dd Z1d d! Z2d"d# Z3d$d% Z4d&d' Z5d(S ))z'Implementation of the Kronecker product    )divisionprint_function)AddMulPowprodsympify)range)adjoint)
MatrixExpr
ShapeErrorIdentity)	transpose)
MatrixBase)canon	condition
distributedo_oneexhaustflattentypedunpack)	bottom_up)sift   )MatAdd)MatMul)MatPowc              G   s8   | st dt|   t| dkr(| d S t|   S d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   N)	TypeErrorvalidatelenKroneckerProductdoit)matrices r$   Clib/python3.7/site-packages/sympy/matrices/expressions/kronecker.pykronecker_product   s    8r&   c                   s   e Zd ZdZdZ 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
    Tc                s   t tt|}tdd |D rTttdd |D }tdd |D rP| S |S |dd}|rlt|  t	t
| j| f| S )Nc             s   s   | ]}|j V  qd S )N)Zis_Identity).0ar$   r$   r%   	<genexpr>m   s    z+KroneckerProduct.__new__.<locals>.<genexpr>c             s   s   | ]}|j V  qd S )N)rows)r'   r(   r$   r$   r%   r)   n   s    c             s   s   | ]}t |tV  qd S )N)
isinstancer   )r'   r(   r$   r$   r%   r)   o   s    checkT)listmapr   allr   r   Zas_explicitgetr   superr!   __new__)clsargskwargsZretr,   )	__class__r$   r%   r2   k   s    zKroneckerProduct.__new__c             C   sD   | j d j\}}x*| j dd  D ]}||j9 }||j9 }q W ||fS )Nr   r   )r4   shaper*   cols)selfr*   r8   matr$   r$   r%   r7   y   s
    
zKroneckerProduct.shapec             C   sL   d}xBt | jD ]4}t||j\}}t||j\}}||||f 9 }qW |S )Nr   )reversedr4   divmodr*   r8   )r9   ijresultr:   mnr$   r$   r%   _entry   s    zKroneckerProduct._entryc             C   s   t ttt| j  S )N)r!   r-   r.   r
   r4   r"   )r9   r$   r$   r%   _eval_adjoint   s    zKroneckerProduct._eval_adjointc             C   s   t dd | jD   S )Nc             S   s   g | ]}|  qS r$   )	conjugate)r'   r(   r$   r$   r%   
<listcomp>   s    z4KroneckerProduct._eval_conjugate.<locals>.<listcomp>)r!   r4   r"   )r9   r$   r$   r%   _eval_conjugate   s    z KroneckerProduct._eval_conjugatec             C   s   t ttt| j  S )N)r!   r-   r.   r   r4   r"   )r9   r$   r$   r%   _eval_transpose   s    z KroneckerProduct._eval_transposec                s$   ddl m   t fdd| jD S )Nr   )tracec             3   s   | ]} |V  qd S )Nr$   )r'   r(   )rH   r$   r%   r)      s    z/KroneckerProduct._eval_trace.<locals>.<genexpr>)rH   r   r4   )r9   r$   )rH   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   s   | ]}|j V  qd S )N)Z	is_square)r'   r(   r$   r$   r%   r)      s    z5KroneckerProduct._eval_determinant.<locals>.<genexpr>c             3   s    | ]} ||j   V  qd S )N)r*   )r'   r(   )rJ   r@   r$   r%   r)      s    )ZdeterminantrJ   rK   r/   r4   r*   r   )r9   rK   r$   )rJ   r@   r%   _eval_determinant   s
    z"KroneckerProduct._eval_determinantc             C   s>   yt dd | jD  S  tk
r8   ddlm} || S X d S )Nc             S   s   g | ]}|  qS r$   )Zinverse)r'   r(   r$   r$   r%   rE      s    z2KroneckerProduct._eval_inverse.<locals>.<listcomp>r   )Inverse)r!   r4   r   Z"sympy.matrices.expressions.inverserM   )r9   rM   r$   r$   r%   _eval_inverse   s
    zKroneckerProduct._eval_inversec             C   sF   t |toD| j|jkoDt| jt|jkoDt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 )N)r7   )r'   r(   br$   r$   r%   r)      s    z6KroneckerProduct.structurally_equal.<locals>.<genexpr>)r+   r!   r7   r    r4   r/   zip)r9   otherr$   r$   r%   structurally_equal   s    
z#KroneckerProduct.structurally_equalc             C   sF   t |toD| j|jkoDt| jt|jkoDt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 )N)r8   r*   )r'   r(   rO   r$   r$   r%   r)      s    z6KroneckerProduct.has_matching_shape.<locals>.<genexpr>)r+   r!   r8   r*   r    r4   r/   rP   )r9   rQ   r$   r$   r%   has_matching_shape   s    
z#KroneckerProduct.has_matching_shapec             K   s   t tttttti| S )N)r   r   r   r!   r   r   )r9   Zhintsr$   r$   r%   _eval_expand_kroneckerproduct   s    z.KroneckerProduct._eval_expand_kroneckerproductc             C   s4   |  |r(| jdd t| j|jD  S | | S d S )Nc             S   s   g | ]\}}|| qS r$   r$   )r'   r(   rO   r$   r$   r%   rE      s    z3KroneckerProduct._kronecker_add.<locals>.<listcomp>)rR   r6   rP   r4   )r9   rQ   r$   r$   r%   _kronecker_add   s    
zKroneckerProduct._kronecker_addc             C   s4   |  |r(| jdd t| j|jD  S | | S d S )Nc             S   s   g | ]\}}|| qS r$   r$   )r'   r(   rO   r$   r$   r%   rE      s    z3KroneckerProduct._kronecker_mul.<locals>.<listcomp>)rS   r6   rP   r4   )r9   rQ   r$   r$   r%   _kronecker_mul   s    
zKroneckerProduct._kronecker_mulc                s8     dd}|r& fdd| jD }n| j}tt| S )NdeepTc                s   g | ]}|j f  qS r$   )r"   )r'   arg)r5   r$   r%   rE      s    z)KroneckerProduct.doit.<locals>.<listcomp>)r0   r4   canonicalizer!   )r9   r5   rW   r4   r$   )r5   r%   r"      s
    zKroneckerProduct.doit)__name__
__module____qualname____doc__Zis_KroneckerProductr2   propertyr7   rB   rC   rF   rG   rI   rL   rN   rR   rS   rT   rU   rV   r"   __classcell__r$   r$   )r6   r%   r!   V   s"   r!   c              G   s   t dd | D stdd S )Nc             s   s   | ]}|j V  qd S )N)Z	is_Matrix)r'   rX   r$   r$   r%   r)      s    zvalidate.<locals>.<genexpr>z Mix of Matrix and Scalar symbols)r/   r   )r4   r$   r$   r%   r      s    r   c             C   s^   g }g }x4| j D ]*}| \}}|| |t| qW t| }|dkrZ|t|  S | S )Nr   )r4   Zargs_cncextendappendr   Z
_from_argsr!   )kronZc_partZnc_partrX   cZncr$   r$   r%   extract_commutative   s    
rd   c        
   	   G   s   t dd | D s"tdt|  | d }xt| d d D ]}|j}|j}xlt|D ]`}||||   }x2t|d D ]"}||||| | d   }qxW |dkr|}qV||}qVW |}q<W t	| dd d	j
}	t||	r|S |	|S d S )
Nc             s   s   | ]}t |tV  qd S )N)r+   r   )r'   r@   r$   r$   r%   r)     s    z+matrix_kronecker_product.<locals>.<genexpr>z&Sequence of Matrices expected, got: %sr   r   c             S   s   | j S )N)Z_class_priority)Mr$   r$   r%   <lambda>   s    z*matrix_kronecker_product.<locals>.<lambda>)key)r/   r   reprr;   r*   r8   r	   Zrow_joinZcol_joinmaxr6   r+   )
r#   Zmatrix_expansionr:   r*   r8   r=   startr>   nextZMatrixClassr$   r$   r%   matrix_kronecker_product  s(    
rm   c             C   s"   t dd | jD s| S t| j S )Nc             s   s   | ]}t |tV  qd S )N)r+   r   )r'   r@   r$   r$   r%   r)   )  s    z-explicit_kronecker_product.<locals>.<genexpr>)r/   r4   rm   )rb   r$   r$   r%   explicit_kronecker_product'  s    rn   c             C   s
   t | tS )N)r+   r!   )xr$   r$   r%   rg   4  s    rg   c             C   s&   t | trtdd | jD S dS d S )Nc             s   s   | ]}|j V  qd S )N)r7   )r'   r(   r$   r$   r%   r)   :  s    z&_kronecker_dims_key.<locals>.<genexpr>)r   )r+   r!   tupler4   )exprr$   r$   r%   _kronecker_dims_key8  s    
rr   c                s^   ddl m  t| jt}|dd }|s,| S  fdd| D }|sNt| S t| | S d S )Nr   )reduce)r   c                s   g | ]} d d |qS )c             S   s
   |  |S )N)rU   )ro   yr$   r$   r%   rg   F  s    z.kronecker_mat_add.<locals>.<listcomp>.<lambda>r$   )r'   group)rs   r$   r%   rE   F  s   z%kronecker_mat_add.<locals>.<listcomp>)	functoolsrs   r   r4   rr   popvaluesr   )rq   r4   ZnonkronsZkronsr$   )rs   r%   kronecker_mat_add?  s    
ry   c             C   s   |   \}}d}xb|t|d k rr|||d  \}}t|trht|trh||||< ||d  q|d7 }qW |t|  S )Nr   r      )Zas_coeff_matricesr    r+   r!   rV   rw   r   )rq   Zfactorr#   r=   ABr$   r$   r%   kronecker_mat_mulO  s    r}   c                s.   t  jtr&t fdd jjD  S  S d S )Nc                s   g | ]}t | jqS r$   )r   Zexp)r'   r(   )rq   r$   r%   rE   a  s    z%kronecker_mat_pow.<locals>.<listcomp>)r+   baser!   r4   )rq   r$   )rq   r%   kronecker_mat_pow_  s    r   c             C   sX   dd }t tt t|ttttttt	i}|| }y|
 S  tk
rR   |S X d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)
    >>> combine_kronecker(KroneckerProduct(A, B)**m)
    KroneckerProduct(A**m, B**m)
    c             S   s   t | to| tS )N)r+   r   Zhasr!   )rq   r$   r$   r%   haskron{  s    z"combine_kronecker.<locals>.haskronN)r   r   r   r   r   ry   r   r}   r   r   r"   AttributeError)rq   r   Zruler?   r$   r$   r%   combine_kroneckerf  s    
r   N)6r]   Z
__future__r   r   Z
sympy.corer   r   r   r   r   Zsympy.core.compatibilityr	   Zsympy.functionsr
   Z"sympy.matrices.expressions.matexprr   r   r   Z$sympy.matrices.expressions.transposer   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   rd   rm   rn   ZrulesrY   rr   ry   r}   r   r   r$   r$   r$   r%   <module>   s>   (A &
