o
    8Va5                     @   s   d dl mZmZ d dlmZ d dlmZ d dlmZm	Z	 d dl
mZmZmZmZmZmZ dd ZG dd	 d	eZd
d Zdd Zdd ZG dd deZdS )    )Mulsympify)
ShapeError)
MatrixExpr)
ZeroMatrix	OneMatrix)unpackflatten	conditionexhaustrm_idsortc                  G   sB   | st dt|   t| dkr| d S dd | D } t|   S )a~  
    Return the elementwise (aka Hadamard) product of matrices.

    Examples
    ========

    >>> from sympy.matrices import hadamard_product, MatrixSymbol
    >>> A = MatrixSymbol('A', 2, 3)
    >>> B = MatrixSymbol('B', 2, 3)
    >>> hadamard_product(A)
    A
    >>> hadamard_product(A, B)
    HadamardProduct(A, B)
    >>> hadamard_product(A, B)[0, 1]
    A[0, 1]*B[0, 1]
    z#Empty Hadamard product is undefined   r   c                 S   s   g | ]}|j s|qS  )Zis_Identity.0ir   r   E/usr/lib/python3/dist-packages/sympy/matrices/expressions/hadamard.py
<listcomp>!   s    z$hadamard_product.<locals>.<listcomp>)	TypeErrorvalidatelenHadamardProductdoit)Zmatricesr   r   r   hadamard_product
   s   r   c                       s`   e Zd ZdZdZd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  ZS )r   a1  
    Elementwise product of matrix expressions

    Examples
    ========

    Hadamard product for matrix symbols:

    >>> from sympy.matrices import hadamard_product, HadamardProduct, MatrixSymbol
    >>> A = MatrixSymbol('A', 5, 5)
    >>> B = MatrixSymbol('B', 5, 5)
    >>> isinstance(hadamard_product(A, B), HadamardProduct)
    True

    Notes
    =====

    This is a symbolic object that simply stores its argument without
    evaluating it. To actually compute the product, use the function
    ``hadamard_product()`` or ``HadamardProduct.doit``
    TF)evaluatecheckc                   sB   t tt|}|rt|  t j| g|R  }|r|jdd}|S )NF)Zdeep)listmapr   r   super__new__r   )clsr   r   argsobj	__class__r   r   r    =   s   zHadamardProduct.__new__c                 C   s   | j d jS Nr   )r"   shapeselfr   r   r   r'   G   s   zHadamardProduct.shapec                    s   t  fdd| jD  S )Nc                    s    g | ]}|j  fi qS r   )_entryr   argr   jkwargsr   r   r   L   s     z*HadamardProduct._entry.<locals>.<listcomp>)r   r"   )r)   r   r.   r/   r   r-   r   r*   K   s   zHadamardProduct._entryc                 C   s    ddl m} ttt|| j S Nr   )	transpose)$sympy.matrices.expressions.transposer1   r   r   r   r"   r)   r1   r   r   r   _eval_transposeN   s   zHadamardProduct._eval_transposec                    s   | j fdd| jD  }ddlm  ddlm}  fdd|jD rEfdd|jD }|dd t D j| j }t	|g|  }t
|S )	Nc                    s   g | ]
}|j d i  qS )r   )r   r   )ignoredr   r   r   S   s    z(HadamardProduct.doit.<locals>.<listcomp>r   
MatrixBase)ImmutableMatrixc                    s   g | ]	}t | r|qS r   )
isinstancer   r6   r   r   r   W   s    c                    s   g | ]}| vr|qS r   r   r   )explicitr   r   r   Y   s    c                 S   s   g | ]}t |qS r   )r   fromiterr   r   r   r   r   Z   s    
)funcr"   sympyr7   Zsympy.matrices.immutabler8   zipZreshaper'   r   canonicalize)r)   r5   exprr8   Z	remainderZexpl_matr   )r7   r:   r5   r   r   R   s   zHadamardProduct.doitc                 C   sp   ddl m} g }t| j}tt|D ]}|d | || |g ||d d   }|t|  q|	|S )Nr   )Addr   )
r=   rA   r   r"   ranger   diffappendr   r;   )r)   xrA   Ztermsr"   r   Zfactorsr   r   r   _eval_derivativea   s   
,
z HadamardProduct._eval_derivativec                    sH  ddl m} ddlm} ddlm} ddlm} fddt jD }g }|D ]y} jd | }	 j|d d  }
 j| 	}t
|
|	  }d	d
g} fddt|D }|D ]G}|j|j }|j|j }|||||||g||||ggg|}|jd jd j|_d|_|jd jd j|_d|_|g|_|| qYq(|S )Nr   ExprBuilderArrayDiagonalArrayTensorProduct_make_matrixc                    s   g | ]\}}|  r|qS r   )Zhas)r   r   r,   rE   r   r   r   p   s    zAHadamardProduct._eval_derivative_matrix_lines.<locals>.<listcomp>r   )r            c                    s"   g | ]\}} j | d kr|qS r   )r'   r   r.   er(   r   r   r   y   s   " rP   )sympy.core.exprrH   0sympy.tensor.array.expressions.array_expressionsrJ   rL   "sympy.matrices.expressions.matexprrN   	enumerater"   _eval_derivative_matrix_linesr   _lines_first_line_index_second_line_index_first_pointer_parent_first_pointer_index_second_pointer_parent_second_pointer_indexrD   )r)   rE   rH   rJ   rL   rN   Z
with_x_indlinesZindZ	left_argsZ
right_argsdZhadamdiagonalr   l1l2subexprr   )r)   rE   r   r[   j   sJ   

	z-HadamardProduct._eval_derivative_matrix_lines)__name__
__module____qualname____doc__Zis_HadamardProductr    propertyr'   r*   r4   r   rF   r[   __classcell__r   r   r$   r   r   %   s    

	r   c                  G   sT   t dd | D std| d }| dd  D ]}|j|jkr'td||f qd S )Nc                 s   s    | ]}|j V  qd S N)	is_Matrixr+   r   r   r   	<genexpr>   s    zvalidate.<locals>.<genexpr>z Mix of Matrix and Scalar symbolsr   r   z"Matrices %s and %s are not aligned)allr   r'   r   )r"   ABr   r   r   r      s   r   c           
      C   s   ddl m} tdd t}t|}|| } tdd tdd }|| } dd }td	d |}|| } t| trddd
lm	} || j
}g }| D ]\}}	|	dkrW|| qI|t||	 qIt| } tdd t|}|| } t| } | S )a  Canonicalize the Hadamard product ``x`` with mathematical properties.

    Examples
    ========

    >>> from sympy.matrices.expressions import MatrixSymbol, HadamardProduct
    >>> from sympy.matrices.expressions import OneMatrix, ZeroMatrix
    >>> from sympy.matrices.expressions.hadamard import canonicalize
    >>> from sympy import init_printing
    >>> init_printing(use_unicode=False)

    >>> A = MatrixSymbol('A', 2, 2)
    >>> B = MatrixSymbol('B', 2, 2)
    >>> C = MatrixSymbol('C', 2, 2)

    Hadamard product associativity:

    >>> X = HadamardProduct(A, HadamardProduct(B, C))
    >>> X
    A.*(B.*C)
    >>> canonicalize(X)
    A.*B.*C

    Hadamard product commutativity:

    >>> X = HadamardProduct(A, B)
    >>> Y = HadamardProduct(B, A)
    >>> X
    A.*B
    >>> Y
    B.*A
    >>> canonicalize(X)
    A.*B
    >>> canonicalize(Y)
    A.*B

    Hadamard product identity:

    >>> X = HadamardProduct(A, OneMatrix(2, 2))
    >>> X
    A.*1
    >>> canonicalize(X)
    A

    Absorbing element of Hadamard product:

    >>> X = HadamardProduct(A, ZeroMatrix(2, 2))
    >>> X
    A.*0
    >>> canonicalize(X)
    0

    Rewriting to Hadamard Power

    >>> X = HadamardProduct(A, A, A)
    >>> X
    A.*A.*A
    >>> canonicalize(X)
     .3
    A

    Notes
    =====

    As the Hadamard product is associative, nested products can be flattened.

    The Hadamard product is commutative so that factors can be sorted for
    canonical form.

    A matrix of only ones is an identity for Hadamard product,
    so every matrices of only ones can be removed.

    Any zero matrix will make the whole product a zero matrix.

    Duplicate elements can be collected and rewritten as HadamardPower

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Hadamard_product_(matrices)
    r   )default_sort_keyc                 S   
   t | tS ro   r9   r   rO   r   r   r   <lambda>      
 zcanonicalize.<locals>.<lambda>c                 S   rv   ro   rw   rO   r   r   r   rx      ry   c                 S   rv   ro   )r9   r   rO   r   r   r   rx      ry   c                 S   s"   t dd | jD rt| j S | S )Nc                 s   s    | ]}t |tV  qd S ro   )r9   r   )r   cr   r   r   rq     s    z/canonicalize.<locals>.absorb.<locals>.<genexpr>)anyr"   r   r'   rO   r   r   r   absorb  s   
zcanonicalize.<locals>.absorbc                 S   rv   ro   rw   rO   r   r   r   rx   
  ry   )Counterr   c                 S   rv   ro   rw   rO   r   r   r   rx     ry   )Zsympy.core.compatibilityru   r
   r	   r   r   r9   r   collectionsr}   r"   itemsrD   HadamardPowerr   r   )
rE   ru   ZruleZfunr|   r}   ZtallyZnew_argbaseexpr   r   r   r?      sD   R


r?   c                 C   sB   t | } t |}|dkr| S | js| | S |jrtdt| |S )Nr   z#cannot raise expression to a matrix)r   rp   
ValueErrorr   )r   r   r   r   r   hadamard_power)  s   
r   c                       sd   e Zd ZdZ fddZedd Zedd Zedd	 Zd
d Z	dd Z
dd Zdd Z  ZS )r   a  
    Elementwise power of matrix expressions

    Parameters
    ==========

    base : scalar or matrix

    exp : scalar or matrix

    Notes
    =====

    There are four definitions for the hadamard power which can be used.
    Let's consider `A, B` as `(m, n)` matrices, and `a, b` as scalars.

    Matrix raised to a scalar exponent:

    .. math::
        A^{\circ b} = \begin{bmatrix}
        A_{0, 0}^b   & A_{0, 1}^b   & \cdots & A_{0, n-1}^b   \\
        A_{1, 0}^b   & A_{1, 1}^b   & \cdots & A_{1, n-1}^b   \\
        \vdots       & \vdots       & \ddots & \vdots         \\
        A_{m-1, 0}^b & A_{m-1, 1}^b & \cdots & A_{m-1, n-1}^b
        \end{bmatrix}

    Scalar raised to a matrix exponent:

    .. math::
        a^{\circ B} = \begin{bmatrix}
        a^{B_{0, 0}}   & a^{B_{0, 1}}   & \cdots & a^{B_{0, n-1}}   \\
        a^{B_{1, 0}}   & a^{B_{1, 1}}   & \cdots & a^{B_{1, n-1}}   \\
        \vdots         & \vdots         & \ddots & \vdots           \\
        a^{B_{m-1, 0}} & a^{B_{m-1, 1}} & \cdots & a^{B_{m-1, n-1}}
        \end{bmatrix}

    Matrix raised to a matrix exponent:

    .. math::
        A^{\circ B} = \begin{bmatrix}
        A_{0, 0}^{B_{0, 0}}     & A_{0, 1}^{B_{0, 1}}     &
        \cdots & A_{0, n-1}^{B_{0, n-1}}     \\
        A_{1, 0}^{B_{1, 0}}     & A_{1, 1}^{B_{1, 1}}     &
        \cdots & A_{1, n-1}^{B_{1, n-1}}     \\
        \vdots                  & \vdots                  &
        \ddots & \vdots                      \\
        A_{m-1, 0}^{B_{m-1, 0}} & A_{m-1, 1}^{B_{m-1, 1}} &
        \cdots & A_{m-1, n-1}^{B_{m-1, n-1}}
        \end{bmatrix}

    Scalar raised to a scalar exponent:

    .. math::
        a^{\circ b} = a^b
    c                    sd   t |}t |}|jr|jr|| S |jr(|jr(|j|jkr(td|j|jt | ||}|S )NzGThe shape of the base {} and the shape of the exponent {} do not match.)r   	is_scalarrp   r'   r   formatr   r    )r!   r   r   r#   r$   r   r   r    n  s   zHadamardPower.__new__c                 C   
   | j d S r&   Z_argsr(   r   r   r   r   ~     
zHadamardPower.basec                 C   r   )Nr   r   r(   r   r   r   r     r   zHadamardPower.expc                 C   s   | j jr| j jS | jjS ro   )r   rp   r'   r   r(   r   r   r   r'     s   zHadamardPower.shapec                 K   s   | j }| j}|jr|j||fi |}n|jr|}ntd||jr2|j||fi |}|| S |jr;|}|| S td|)Nz)The base {} must be a scalar or a matrix.z-The exponent {} must be a scalar or a matrix.)r   r   rp   r*   r   r   r   )r)   r   r.   r/   r   r   abr   r   r   r*     s$   zHadamardPower._entryc                 C   s   ddl m} t|| j| jS r0   )r2   r1   r   r   r   r3   r   r   r   r4     s   zHadamardPower._eval_transposec                 C   sF   ddl m} | j|}| j|}||}t|| | j|  | S )Nr   )log)r=   r   r   rC   r   Z	applyfuncr   )r)   rE   r   ZdexpZlogbaseZdlbaser   r   r   rF     s   
zHadamardPower._eval_derivativec                    s  ddl m} ddl m} ddlm} ddlm}  j|}|D ]d}ddg} fdd	t	|D }|j
|j }	|j
|j }
|||||||	g jt j jd
  |||
ggg||jd}|jd jd j|_d|_d|_|jd jd j|_d|_d|_|g|_
q |S )Nr   rK   rI   rG   rM   )r   rP   rQ   c                    s$   g | ]\}} j j| d kr|qS rT   )r   r'   rU   r(   r   r   r     s   $ z?HadamardPower._eval_derivative_matrix_lines.<locals>.<listcomp>r   )Z	validatorrP   )rX   rL   rJ   rW   rH   rY   rN   r   r[   rZ   r\   r]   r^   r   r   Z	_validater"   r_   r`   ra   rb   )r)   rE   rL   rJ   rH   rN   Zlrr   re   rf   rg   rh   r   r(   r   r[     s@   

	

z+HadamardPower._eval_derivative_matrix_lines)ri   rj   rk   rl   r    rm   r   r   r'   r*   r4   rF   r[   rn   r   r   r$   r   r   5  s    8



r   N)Z
sympy.corer   r   Zsympy.matrices.commonr   rY   r   Z"sympy.matrices.expressions.specialr   r   Zsympy.strategiesr   r	   r
   r   r   r   r   r   r   r?   r   r   r   r   r   r   <module>   s     p 
