o
    8Vad6                     @   s  d dl mZ d dl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mZmZmZ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 ddlm Z  ddl!m"Z"m#Z#m$Z$m%Z% G dd deeZ&e'ee&f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" Z0d#d$ Z1e1e*e,e0e.eed%d& e+e-ee/fZ2eee&ee2 iZ3d'd( Z4d d)l5m6Z6m7Z7 d d*l8m9Z9 d+d, Z:e:e9d< d-S ).    )Number)MulBasicsympifyS)muladjoint)rm_idunpacktypedflattenexhaustdo_onenew)
ShapeErrorNonInvertibleMatrixError)
MatrixBase   )Inverse)
MatrixExpr)MatPow	transpose)PermutationMatrix)
ZeroMatrixIdentityGenericIdentity	OneMatrixc                   @   s   e Zd ZdZdZe ZddddddZedd Z	d 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S )!MatMula  
    A product of matrix expressions

    Examples
    ========

    >>> from sympy import MatMul, MatrixSymbol
    >>> A = MatrixSymbol('A', 5, 4)
    >>> B = MatrixSymbol('B', 4, 3)
    >>> C = MatrixSymbol('C', 3, 6)
    >>> MatMul(A, B, C)
    A*B*C
    TF)evaluatecheck_sympifyc                   st   |s j S tt fdd|}|rttt|}tj g|R  }| \}}|r.t|  |s2|S |r8t	|S |S )Nc                    s
    j | kS N)identity)icls C/usr/lib/python3/dist-packages/sympy/matrices/expressions/matmul.py<lambda>+      
 z MatMul.__new__.<locals>.<lambda>)
r$   listfiltermapr   r   __new__as_coeff_matricesvalidatecanonicalize)r'   r    r!   r"   argsobjfactormatricesr(   r&   r)   r/   %   s   zMatMul.__new__c                 C   s$   dd | j D }|d j|d jfS )Nc                 S      g | ]}|j r|qS r(   	is_Matrix.0argr(   r(   r)   
<listcomp>A       z MatMul.shape.<locals>.<listcomp>r   )r3   rowscols)selfr6   r(   r(   r)   shape?   s   zMatMul.shapec                    sv  ddl m m}m}mm |  \}}t|dkr$||d ||f  S d gt|d  d gt|d  }	|d< |d<  fdd}
|d|
 t	dt|D ]}t
|< qRt|d d D ]\}}|jd d |	|< qcfdd	t|D }||}tfd
d|D rd}|||gtdd dgt|	 |	R   }tfdd|	D sd}|r| S |S )Nr   )DummySumr   ImmutableMatrixIntegerr   r?   c                  3   s     d} 	  d|  V  | d7 } q)Nr   Tzi_%ir(   )Zcounter)rD   r(   r)   fQ   s   zMatMul._entry.<locals>.fdummy_generatorc                    s,   g | ]\}}|j | |d    dqS )r   )rI   )_entryr;   r%   r<   )rI   indicesr(   r)   r=   ^   s   , z!MatMul._entry.<locals>.<listcomp>c                 3   s    | ]}|  V  qd S r#   Zhasr;   v)rF   r(   r)   	<genexpr>`       z MatMul._entry.<locals>.<genexpr>Tc                 3   s    | ]
}t | tfV  qd S r#   )
isinstanceintrN   )rG   r(   r)   rP   h   s    F)sympyrD   rE   r   rF   rG   r0   lengetrangenext	enumeraterC   fromiteranyzipdoit)rB   r%   jexpandkwargsrE   r   coeffr6   Z
ind_rangesrH   r<   Zexpr_in_sumresultr(   )rD   rF   rG   rI   rL   r)   rJ   D   s4   

zMatMul._entryc                 C   sB   dd | j D }dd | j D }t| }|jdu rtd||fS )Nc                 S      g | ]}|j s|qS r(   r8   r;   xr(   r(   r)   r=   m   r>   z,MatMul.as_coeff_matrices.<locals>.<listcomp>c                 S   r7   r(   r8   rd   r(   r(   r)   r=   n   r>   Fz3noncommutative scalars in MatMul are not supported.)r3   r   is_commutativeNotImplementedError)rB   Zscalarsr6   ra   r(   r(   r)   r0   l   s   
zMatMul.as_coeff_matricesc                 C   s   |   \}}|t| fS r#   )r0   r   rB   ra   r6   r(   r(   r)   as_coeff_mmulu   s   zMatMul.as_coeff_mmulc                 C   s4   |   \}}t|gdd |ddd D R   S )a  Transposition of matrix multiplication.

        Notes
        =====

        The following rules are applied.

        Transposition for matrix multiplied with another matrix:
        `\left(A B\right)^{T} = B^{T} A^{T}`

        Transposition for matrix multiplied with scalar:
        `\left(c A\right)^{T} = c A^{T}`

        References
        ==========

        .. [1] https://en.wikipedia.org/wiki/Transpose
        c                 S      g | ]}t |qS r(   r   r:   r(   r(   r)   r=          z*MatMul._eval_transpose.<locals>.<listcomp>Nr?   )r0   r   r]   rh   r(   r(   r)   _eval_transposey   s   zMatMul._eval_transposec                 C   s"   t dd | jd d d D   S )Nc                 S   rj   r(   r   r:   r(   r(   r)   r=      rk   z(MatMul._eval_adjoint.<locals>.<listcomp>r?   )r   r3   r]   rB   r(   r(   r)   _eval_adjoint   s   "zMatMul._eval_adjointc                 C   s8   |   \}}|dkrddlm} |||  S td)Nr   )tracezCan't simplify any further)ri   ro   r]   rg   )rB   r5   mmulro   r(   r(   r)   _eval_trace   s
   zMatMul._eval_tracec                 C   s<   ddl m} |  \}}t| }|| j ttt||  S )Nr   )Determinant)Z&sympy.matrices.expressions.determinantrr   r0   only_squaresr@   r   r,   r.   )rB   rr   r5   r6   Zsquare_matricesr(   r(   r)   _eval_determinant   s   zMatMul._eval_determinantc                 C   s@   zt dd | jd d d D   W S  ty   t|  Y S w )Nc                 S   s&   g | ]}t |tr| n|d  qS )r?   )rR   r   inverser:   r(   r(   r)   r=      s    z(MatMul._eval_inverse.<locals>.<listcomp>r?   )r   r3   r]   r   r   rm   r(   r(   r)   _eval_inverse   s   zMatMul._eval_inversec                    s<     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:   r`   r(   r)   r=      s    zMatMul.doit.<locals>.<listcomp>)rV   r3   r2   r   )rB   r`   rw   r3   exprr(   rx   r)   r]      s   zMatMul.doitc                 K   s(   dd | j D }dd | j D }||gS )Nc                 S   r7   r(   rf   rd   r(   r(   r)   r=      r>   z#MatMul.args_cnc.<locals>.<listcomp>c                 S   rc   r(   rz   rd   r(   r(   r)   r=      r>   r3   )rB   r`   Zcoeff_cZcoeff_ncr(   r(   r)   args_cnc   s   zMatMul.args_cncc                    s   ddl m  fddt| jD }g }|D ]U}| jd | }| j|d d  }|r0t|}nt| jd }|rHt fddt|D }nt| jd }| j| 	}	|	D ]}
|

| |
| ||
 qYq|S )Nr   	Transposec                    s   g | ]\}}|  r|qS r(   rM   rK   re   r(   r)   r=          z8MatMul._eval_derivative_matrix_lines.<locals>.<listcomp>c                    s"   g | ]}|j r | n|qS r(   )r9   r]   )r;   r%   r}   r(   r)   r=      s   " r   )r   r~   rY   r3   r   rZ   r   rC   reversed_eval_derivative_matrix_linesZappend_firstZappend_secondappend)rB   re   Z
with_x_indlinesZindZ	left_argsZ
right_argsZ	right_matZleft_revdr%   r(   )r~   re   r)   r      s&   

z$MatMul._eval_derivative_matrix_linesN)T)__name__
__module____qualname____doc__Z	is_MatMulr   r$   r/   propertyrC   rJ   r0   ri   rl   rn   rq   rt   rv   r]   r|   r   r(   r(   r(   r)   r      s$    

(	r   c                  G   sJ   t t| d D ]}| ||d  \}}|j|jkr"td||f qdS )z, Checks for valid shapes for args of MatMul r      z"Matrices %s and %s are not alignedN)rW   rU   rA   r@   r   )r6   r%   ABr(   r(   r)   r1      s   r1   c                  G   s(   | d dkr| dd  } t tg| R  S )Nr   r   )r   r   r{   r(   r(   r)   newmul   s   r   c                 C   s>   t dd | jD rdd | jD }t|d j|d jS | S )Nc                 S   s   g | ]}|j p|jo|jqS r(   )Zis_zeror9   Zis_ZeroMatrixr:   r(   r(   r)   r=      s    zany_zeros.<locals>.<listcomp>c                 S   r7   r(   r8   r:   r(   r(   r)   r=      r>   r   r?   )r[   r3   r   r@   rA   )r   r6   r(   r(   r)   	any_zeros   s   r   c                 C   s   t dd | jD s| S g }| jd }| jdd D ]}t|ttfr/t|ttfr/|| }q|| |}q|| t| S )a   Merge explicit MatrixBase arguments

    >>> from sympy import MatrixSymbol, Matrix, MatMul, pprint
    >>> from sympy.matrices.expressions.matmul import merge_explicit
    >>> A = MatrixSymbol('A', 2, 2)
    >>> B = Matrix([[1, 1], [1, 1]])
    >>> C = Matrix([[1, 2], [3, 4]])
    >>> X = MatMul(A, B, C)
    >>> pprint(X)
      [1  1] [1  2]
    A*[    ]*[    ]
      [1  1] [3  4]
    >>> pprint(merge_explicit(X))
      [4  6]
    A*[    ]
      [4  6]

    >>> X = MatMul(B, A, C)
    >>> pprint(X)
    [1  1]   [1  2]
    [    ]*A*[    ]
    [1  1]   [3  4]
    >>> pprint(merge_explicit(X))
    [1  1]   [1  2]
    [    ]*A*[    ]
    [1  1]   [3  4]
    c                 s   s    | ]}t |tV  qd S r#   )rR   r   r:   r(   r(   r)   rP     rQ   z!merge_explicit.<locals>.<genexpr>r   r   N)r[   r3   rR   r   r   r   r   )matmulnewargslastr<   r(   r(   r)   merge_explicit   s   



r   c                 C   s:   |   \}}tdd |}||krt|g|jR  S | S )z Remove Identities from a MatMul

    This is a modified version of sympy.strategies.rm_id.
    This is necesssary because MatMul may contain both MatrixExprs and Exprs
    as args.

    See Also
    ========

    sympy.strategies.rm_id
    c                 S   s
   | j du S )NT)Zis_Identityr   r(   r(   r)   r*   $  r+   zremove_ids.<locals>.<lambda>)ri   r
   r   r3   )r   r5   rp   rb   r(   r(   r)   
remove_ids  s
   r   c                 C   s(   |   \}}|dkrt|g|R  S | S Nr   )r0   r   )r   r5   r6   r(   r(   r)   factor_in_front*  s   r   c              	   C   s4  |   \}}|d g}|dd D ]}|d }|jdks!|jdkr'|| qt|tr2|j\}}n|tj}}t|trC|j\}}	n|tj}}	||kr]||	 }
t||
jdd|d< qt|t	sz|
 }W n tys   d}Y nw |dur||kr||	 }
t||
jdd|d< q|| qt|g|R  S )zCombine consecutive powers with the same base into one

    e.g. A*A**2 -> A**3

    This also cancels out the possible matrix inverses using the
    knowledgebase of ``Inverse``.

    e.g. Y * X * X.I -> Y
    r   r   Nr?   F)rw   )r0   Z	is_squarer   rR   r   r3   r   ZOner]   r   ru   r   r   )r   r5   r3   new_argsr   r   ZA_baseZA_expZB_baseZB_expZnew_expZ
B_base_invr(   r(   r)   combine_powers0  s:   





r   c           	      C   s   | j }t|}|dk r| S |d g}td|D ],}|d }|| }t|tr>t|tr>|j d }|j d }t|| |d< q|| qt| S )zGRefine products of permutation matrices as the products of cycles.
    r   r   r   r?   )r3   rU   rW   rR   r   r   r   )	r   r3   lrb   r%   r   r   Zcycle_1Zcycle_2r(   r(   r)   combine_permutations^  s    



r   c                 C   s   |   \}}|d g}|dd D ]/}|d }t|tr!t|ts'|| q|  |t|jd |jd  ||jd 9 }qt|g|R  S )zj
    Combine products of OneMatrix

    e.g. OneMatrix(2, 3) * OneMatrix(3, 4) -> 3 * OneMatrix(2, 4)
    r   r   Nr?   )r0   rR   r   r   poprC   r   )r   r5   r3   r   r   r   r(   r(   r)   combine_one_matricest  s   

r   c                    s   | j  t dkr?ddlm}  d jr' d jr'| fdd d j D  S  d jr? d jr?| fdd d j D  S | S )zr
    Simplify MatMul expressions but distributing
    rational term to MatMul.

    e.g. 2*(A+B) -> 2*A + 2*B
    r   r   )MatAddr   c                    s   g | ]}t | d   qS )r   r   r]   r;   Zmatr{   r(   r)   r=     r   z$distribute_monom.<locals>.<listcomp>c                    s   g | ]}t  d  | qS )r   r   r   r{   r(   r)   r=     r   )r3   rU   Zmataddr   Z	is_MatAddZis_Rational)r   r   r(   r{   r)   distribute_monom  s   r   c                 C   s   | dkS r   r(   r   r(   r(   r)   r*     s    r*   c                  G   sp   | d j | d jkrtdg }d}t| D ]\}}|j| | j kr5|t| ||d     |d }q|S )z'factor matrices only if they are squarer   r?   z!Invalid matrices being multipliedr   )r@   rA   RuntimeErrorrY   r   r   r]   )r6   outstartr%   Mr(   r(   r)   rs     s   rs   )askQ)handlers_dictc                 C   s   g }g }| j D ]}|jr|| q|| q|d }|dd D ]4}||jkr9tt||r9t|jd }q"||	 krOtt
||rOt|jd }q"|| |}q"|| t| S )z
    >>> from sympy import MatrixSymbol, Q, assuming, refine
    >>> X = MatrixSymbol('X', 2, 2)
    >>> expr = X * X.T
    >>> print(expr)
    X*X.T
    >>> with assuming(Q.orthogonal(X)):
    ...     print(refine(expr))
    I
    r   r   N)r3   r9   r   Tr   r   Z
orthogonalr   rC   	conjugateZunitaryr   )ry   Zassumptionsr   Zexprargsr3   r   r<   r(   r(   r)   refine_MatMul  s    


r   N);rT   r   Z
sympy.corer   r   r   r   Zsympy.core.mulr   Zsympy.functionsr	   Zsympy.strategiesr
   r   r   r   r   r   r   Zsympy.matrices.commonr   r   Zsympy.matrices.matricesr   ru   r   Zmatexprr   Zmatpowr   r   Zpermutationr   Zspecialr   r   r   r   r   Zregister_handlerclassr1   r   r   r   r   r   r   r   r   r   Zrulesr2   rs   Zsympy.assumptions.askr   r   Zsympy.assumptions.refiner   r   r(   r(   r(   r)   <module>   sF    $ A
*."