a
    <bz7                     @   s  d dl mZmZ d dlmZ d dlmZmZmZ d dl	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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 Z0dd Z1dd Z2dd Z3dd Z4dd Z5d d! Z6d"d# Z7d$d% Z8d&d' Z9e9e2e4e8e6eed(d) e3e5ee7fZ:eee.ee: iZ;d*d+ Z<d,d- Z=e=ed< d.S )/    )askQ)handlers_dict)BasicsympifyS)mulMul)NumberIntegerDummy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
 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|}|r2ttt|}tj g|R  }| \}}|r\t|  |sd|S |rpt	|S |S )Nc                    s
    j | kS N)identity)icls q/Users/vegardjervell/Documents/master/model/venv/lib/python3.9/site-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/   r5   (   s    zMatMul.__new__c                 C   s$   dd | j D }|d j|d jfS )Nc                 S   s   g | ]}|j r|qS r.   	is_Matrix.0argr.   r.   r/   
<listcomp>D   r1   z MatMul.shape.<locals>.<listcomp>r   )r9   rowscols)selfr<   r.   r.   r/   shapeB   s    zMatMul.shapec                 C   s   | j d  S )Nr   )r9   could_extract_minus_signrF   r.   r.   r/   rH   G   s    zMatMul.could_extract_minus_signc                    sp  ddl m} ddlm  |  \}}t|dkrD||d ||f  S d gt|d  d gt|d  }|d< |d< dd }	|d|	 tdt|D ]}t|< qt	|d d D ]\}}
|
j
d d ||< qfd	d
t	|D }t|}t fdd|D rd}|||gtdd dgt| |R   }tdd |D s^d}|rl| S |S )Nr   )SumImmutableMatrixr   rC   c                  s   s    d} t d|  V  | d7 } qd S )Nr   zi_%ir   )counterr.   r.   r/   fY   s    zMatMul._entry.<locals>.fdummy_generatorc                    s,   g | ]$\}}|j | |d    dqS )r   )rO   )_entryr@   r+   rA   )rO   indicesr.   r/   rB   f   r1   z!MatMul._entry.<locals>.<listcomp>c                 3   s   | ]}|  V  qd S r)   Zhasr@   vrK   r.   r/   	<genexpr>h   r1   z MatMul._entry.<locals>.<genexpr>Tc                 s   s   | ]}t |ttfV  qd S r)   )
isinstancer   intrT   r.   r.   r/   rV   p   r1   F)Zsympy.concrete.summationsrJ   Zsympy.matrices.immutablerL   r6   lengetrangenext	enumeraterG   r	   fromiteranyzipdoit)rF   r+   jexpandkwargsrJ   coeffr<   Z
ind_rangesrN   rA   Zexpr_in_sumresultr.   )rL   rO   rR   r/   rP   J   s6    

zMatMul._entryc                 C   sB   dd | j D }dd | j D }t| }|jdu r:td||fS )Nc                 S   s   g | ]}|j s|qS r.   r=   r@   xr.   r.   r/   rB   u   r1   z,MatMul.as_coeff_matrices.<locals>.<listcomp>c                 S   s   g | ]}|j r|qS r.   r=   rg   r.   r.   r/   rB   v   r1   Fz3noncommutative scalars in MatMul are not supported.)r9   r	   is_commutativeNotImplementedError)rF   Zscalarsr<   re   r.   r.   r/   r6   t   s    
zMatMul.as_coeff_matricesc                 C   s   |   \}}|t| fS r)   )r6   r%   rF   re   r<   r.   r.   r/   as_coeff_mmul}   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   s   g | ]}t |qS r.   r   r?   r.   r.   r/   rB      r1   z*MatMul._eval_transpose.<locals>.<listcomp>NrC   )r6   r%   ra   rk   r.   r.   r/   _eval_transpose   s    zMatMul._eval_transposec                 C   s"   t dd | jd d d D   S )Nc                 S   s   g | ]}t |qS r.   r   r?   r.   r.   r/   rB      r1   z(MatMul._eval_adjoint.<locals>.<listcomp>rC   )r%   r9   ra   rI   r.   r.   r/   _eval_adjoint   s    zMatMul._eval_adjointc                 C   s<   |   \}}|dkr0ddlm} |||  S tdd S )Nr   )tracezCan't simplify any further)rl   ro   ra   rj   )rF   r;   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   r6   only_squaresrD   r	   r2   r4   )rF   rr   r;   r<   Zsquare_matricesr.   r.   r/   _eval_determinant   s    zMatMul._eval_determinantc                 C   sD   z$t dd | jd d d D   W S  ty>   t|  Y S 0 d S )Nc                 S   s&   g | ]}t |tr| n|d  qS )rC   )rW   r   inverser?   r.   r.   r/   rB      s   z(MatMul._eval_inverse.<locals>.<listcomp>rC   )r%   r9   ra   r   r   rI   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 f i  qS r.   )ra   r?   rd   r.   r/   rB      r1   zMatMul.doit.<locals>.<listcomp>)rZ   r9   r8   r%   )rF   rd   rw   r9   exprr.   rx   r/   ra      s    zMatMul.doitc                 K   s(   dd | j D }dd | j D }||gS )Nc                 S   s   g | ]}|j r|qS r.   ri   rg   r.   r.   r/   rB      r1   z#MatMul.args_cnc.<locals>.<listcomp>c                 S   s   g | ]}|j s|qS r.   rz   rg   r.   r.   r/   rB      r1   r9   )rF   rd   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 ]}| jd | }| j|d d  }|r`t|}nt| jd }|rt fddt|D }nt| jd }| j| 	}	|	D ]"}
|

| |
| ||
 qq,|S )Nr   	Transposec                    s   g | ]\}}|  r|qS r.   rS   rQ   rh   r.   r/   rB      r1   z8MatMul._eval_derivative_matrix_lines.<locals>.<listcomp>c                    s"   g | ]}|j r | n|qS r.   )r>   ra   )r@   r+   r}   r.   r/   rB      r1   r   )r   r~   r]   r9   r%   r^   r"   rG   reversed_eval_derivative_matrix_linesZappend_firstZappend_secondappend)rF   rh   Z
with_x_indlinesindZ	left_argsZ
right_argsZ	right_matZleft_revdr+   r.   )r~   rh   r/   r      s$    

z$MatMul._eval_derivative_matrix_linesN)T)__name__
__module____qualname____doc__Z	is_MatMulr#   r*   r5   propertyrG   rH   rP   r6   rl   rm   rn   rq   rt   rv   ra   r|   r   r.   r.   r.   r/   r%      s$   

*	r%   c                  G   sJ   t t| d D ]4}| ||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)r[   rY   rE   rD   r   )r<   r+   ABr.   r.   r/   r7      s    r7   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    | ]}|j p|jo|jV  qd S r)   )is_zeror>   Zis_ZeroMatrixr?   r.   r.   r/   rV      s   zany_zeros.<locals>.<genexpr>c                 S   s   g | ]}|j r|qS r.   r=   r?   r.   r.   r/   rB      r1   zany_zeros.<locals>.<listcomp>r   rC   )r_   r9   r!   rD   rE   )r   r<   r.   r.   r/   	any_zeros   s    r   c                 C   s   t dd | jD s| S g }| jd }| jdd D ]8}t|ttfr^t|ttfr^|| }q4|| |}q4|| 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)   )rW   r   r?   r.   r.   r/   rV     r1   z!merge_explicit.<locals>.<genexpr>r   r   N)r_   r9   rW   r   r
   r   r%   )matmulnewargslastrA   r.   r.   r/   merge_explicit   s    



r   c                 C   s>   |   \}}tdd |}||kr6t|g|jR  S | S d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/   r0   ,  r1   zremove_ids.<locals>.<lambda>N)rl   r   r   r9   )r   r;   rp   rf   r.   r.   r/   
remove_ids  s
    r   c                 C   s(   |   \}}|dkr$t|g|R  S | S Nr   )r6   r   )r   r;   r<   r.   r.   r/   factor_in_front2  s    r   c              	   C   s>  |   \}}|d g}|dd D ]}|d }|jdksD|jdkrP|| q"t|trf|j\}}n|tj }}t|tr|j\}}	n|tj }}	||kr||	 }
t||
jdd|d< q"ndt|t	s"z|
 }W n ty   d}Y n0 |dur"||kr"||	 }
t||
jdd|d< q"|| q"t|g|R  S )a  Combine consecutive powers with the same base into one, e.g.
    $$A \times A^2 \Rightarrow A^3$$

    This also cancels out the possible matrix inverses using the
    knowledgebase of :class:`~.Inverse`, e.g.,
    $$ Y \times X \times X^{-1} \Rightarrow Y $$
    r   r   NrC   F)rw   )r6   Z	is_squarer   rW   r   r9   r   ZOnera   r   ru   r   r   )r   r;   r9   new_argsr   r   ZA_baseZA_expZB_baseZB_expZnew_expZ
B_base_invr.   r.   r/   combine_powers8  s8    




r   c           	      C   s   | j }t|}|dk r| S |d g}td|D ]X}|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   rC   )r9   rY   r[   rW   r    r   r%   )	r   r9   lrf   r+   r   r   Zcycle_1Zcycle_2r.   r.   r/   combine_permutationsd  s     



r   c                 C   s   |   \}}|d g}|dd D ]^}|d }t|trBt|tsN|| 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   NrC   )r6   rW   r$   r   poprG   r   )r   r;   r9   r   r   r   r.   r.   r/   combine_one_matricesz  s    

r   c                    s   | j  t dkr~ddlm}  d jrN d jrN| 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%   ra   r@   matr{   r.   r/   rB     r1   z$distribute_monom.<locals>.<listcomp>c                    s   g | ]}t  d  | qS )r   r   r   r{   r.   r/   rB     r1   )r9   rY   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/   r0     r1   r0   c                  G   sp   | d j | d jkrtdg }d}t| D ]>\}}|j| | j kr,|t| ||d     |d }q,|S )z'factor matrices only if they are squarer   rC   z!Invalid matrices being multipliedr   )rD   rE   RuntimeErrorr]   r   r%   ra   )r<   outstartr+   Mr.   r.   r/   rs     s    
rs   c                 C   s   g }g }| j D ] }|jr$|| q|| q|d }|dd D ]h}||jkrrtt||rrt|jd }qD||	 krtt
||rt|jd }qD|| |}qD|| 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)r9   r>   r   Tr   r   Z
orthogonalr"   rG   	conjugateZunitaryr%   )ry   Zassumptionsr   Zexprargsr9   r   rA   r.   r.   r/   refine_MatMul  s     


r   N)>Zsympy.assumptions.askr   r   Zsympy.assumptions.refiner   Z
sympy.corer   r   r   Zsympy.core.mulr   r	   Zsympy.core.numbersr
   r   Zsympy.core.symbolr   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_handlerclassr7   r   r   r   r   r   r   r   r   r   rulesr8   rs   r   r.   r.   r.   r/   <module>   sF   $ F
*,"