B
    [o                 @   s   d dl mZmZ d dl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 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 ddlmZ ddlmZ G dd deZ G dd de eZ!dS )    )print_functiondivisionN)defaultdict)Dict)Expr)is_sequenceas_intrangeCallable)	fuzzy_and)S)Abs)sqrt)uniq   )
MatrixBase
ShapeError)Matrix)a2idxc               @   s  e Zd Z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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ed0d1 Zd2d3 Zd4d5 Zd6d7 Ze d8d9 Z!d:d; Z"d<d= Z#d>d? Z$d@dA Z%dBdC Z&dDdE Z'dFdG Z(dHdI Z)dJdK Z*dLdM Z+dNdO Z,dPdQ Z-dRdS Z.d[dUdVZ/d\dWdXZ0e e,dYdYdZZ1e e'dYdYdZZ2dYS )]SparseMatrixaj  
    A sparse matrix (a matrix with a large number of zero elements).

    Examples
    ========

    >>> from sympy.matrices import SparseMatrix
    >>> SparseMatrix(2, 2, range(4))
    Matrix([
    [0, 1],
    [2, 3]])
    >>> SparseMatrix(2, 2, {(1, 1): 2})
    Matrix([
    [0, 0],
    [0, 2]])

    See Also
    ========
    sympy.matrices.dense.Matrix
    c          	   O   sZ  t | }t|dkrPt|d trP|d j|_|d j|_t|d j|_|S i |_t|dkrt	|d |_t	|d |_t|d t
r|d }xTt|jD ]F}x@t|jD ]2}||||||}|r||j||f< qW qW nt|d ttfr>x|d  D ](}|d | }	|	r||	|j|< qW nt|d rVt|d |j|j krtdt|d |j|j f |d }
xt|jD ]H}x@t|jD ]2}||
||j |  }|r||j||f< qW qW nntj| \}}}||_||_xPt|jD ]B}x:t|jD ],}||j| |  }|r ||j||f< q W qW |S )Nr   r         z%List length (%s) != rows*columns (%s))object__new__len
isinstancer   rowscolsdict_smatr   r
   r	   _sympifyr   keysr   
ValueErrorr   Z_handle_creation_inputs)clsargskwargsselfopijvaluekeyvZ	flat_listrcZ_list r/   4lib/python3.7/site-packages/sympy/matrices/sparse.pyr   *   sV    
zSparseMatrix.__new__c             C   s^   yD| j |j krdS t|tr(| j|jkS t|trB| jt|jkS W n tk
rX   dS X d S )NF)shaper   r   r   r   MutableSparseMatrixAttributeError)r&   otherr/   r/   r0   __eq__]   s    

zSparseMatrix.__eq__c       
   	   C   s  t |tr0|\}}y"| |\}}| j||ftjS  ttfk
r.   t |t	rjt
t| j| }nJt|rtn@t |tr|jsddlm} || ||S || jkrtd|g}t |t	rt
t| j| }nPt|rnFt |tr|jsddlm} || ||S || jkrtd|g}| ||S X t |t	r|t| d d \}}g }x>t||D ]0}t|| j\}}	|| j||	ftj qfW |S tt|t| | j\}}| j||ftjS )Nr   )MatrixElementzRow index out of boundszCol index out of boundsr   )r   tupleZkey2ijr   getr   Zero	TypeError
IndexErrorslicelistr	   r   r   r   Z	is_numberZ"sympy.matrices.expressions.matexprr6   r   extractindicesr   divmodappendr   )
r&   r+   r(   r)   r6   lohiLmnr/   r/   r0   __getitem__h   sH    


 zSparseMatrix.__getitem__c             C   s
   t  d S )N)NotImplementedError)r&   r+   r*   r/   r/   r0   __setitem__   s    zSparseMatrix.__setitem__c             C   s"   |   }||}|j|}|S )N)_cholesky_sparse_lower_triangular_solveT_upper_triangular_solve)r&   rhsrD   Yrvr/   r/   r0   _cholesky_solve   s    
zSparseMatrix._cholesky_solvec       	   	   C   sr  |   }| | j}xVtt|D ]D}x<|| D ].}||kr| ||f |||f< d}x\|| D ]P}||k rfxB|| D ]4}||k r||kr||||f |||f  7 }q|P q|W P qfW |||f  |8  < |||f  |||f   < q6| ||f |||f< d}x4|| D ](}||k r2||||f d 7 }nP qW |||f  |8  < t|||f |||f< q6W q$W |S )z@Algorithm for numeric Cholesky factorization of a sparse matrix.r   r   )row_structure_symbolic_choleskyzerosr   r	   r   r   )	r&   Z	CrowstrucCr(   r)   summp1p2kr/   r/   r0   rJ      s4    
 zSparseMatrix._cholesky_sparsec                s    jd fddS )zDiagonal solve.r   c                s    | df | | f  S )Nr   r/   )r(   r)   )rN   r&   r/   r0   <lambda>   s    z.SparseMatrix._diagonal_solve.<locals>.<lambda>)_newr   )r&   rN   r/   )rN   r&   r0   _diagonal_solve   s    zSparseMatrix._diagonal_solvec       	         s   |   }|  }||j |sF|j}|dddf }|| }|   |dd}|dkrb|jn|dkrr|jntd| |j	 fddt
 jD  }|s||dddf  d	 }|| }| |S )
a  Return the matrix inverse using Cholesky or LDL (default)
        decomposition as selected with the ``method`` keyword: 'CH' or 'LDL',
        respectively.

        Examples
        ========

        >>> from sympy import SparseMatrix, Matrix
        >>> A = SparseMatrix([
        ... [ 2, -1,  0],
        ... [-1,  2, -1],
        ... [ 0,  0,  2]])
        >>> A.inv('CH')
        Matrix([
        [2/3, 1/3, 1/6],
        [1/3, 2/3, 1/3],
        [  0,   0, 1/2]])
        >>> A.inv(method='LDL') # use of 'method=' is optional
        Matrix([
        [2/3, 1/3, 1/6],
        [1/3, 2/3, 1/3],
        [  0,   0, 1/2]])
        >>> A * _
        Matrix([
        [1, 0, 0],
        [0, 1, 0],
        [0, 0, 1]])

        r   NmethodLDLZCHz$Method may be "CH" or "LDL", not %s.c                s    g | ]} d d |f qS )Nr/   ).0r(   )Isolver/   r0   
<listcomp>   s    z.SparseMatrix._eval_inverse.<locals>.<listcomp>)r   r   )is_symmetric
as_mutableeyer   rL   r8   
_LDL_solverQ   rH   Zhstackr	   r   rZ   )	r&   r%   ZsymMtZr1r\   rP   Zscaler/   )r_   r`   r0   _eval_inverse   s(    
 zSparseMatrix._eval_inversec             C   s   |  dd S )Nc             S   s   t | S )N)r   )xr/   r/   r0   rY      s    z(SparseMatrix._eval_Abs.<locals>.<lambda>)	applyfunc)r&   r/   r/   r0   	_eval_Abs   s    zSparseMatrix._eval_Absc             C   s   t |ts| | | S i }| d}xNt | j |j D ]0}| j|||j|| }|dkrB|||< qBW | | j	| j
|S )zWIf `other` is a SparseMatrix, add efficiently. Otherwise,
        do standard addition.r   )r   r   rZ   r    setunionr   r!   r8   r   r   )r&   r4   smatZzeror+   sumr/   r/   r0   	_eval_add  s    

 zSparseMatrix._eval_addc             C   s   t |tst|}i }x<| j D ].\}}|\}}||krD||j7 }||||f< q"W x.|j D ] \}}|\}}||||| f< q`W | | j| j|j |S )N)r   r   r   itemsr   rZ   r   )r&   Zicolr4   new_smatr+   valrowcolr/   r/   r0   _eval_col_insert  s    

zSparseMatrix._eval_col_insertc             C   s&   dd | j  D }| | j| j|S )Nc             S   s   i | ]\}}|  |qS r/   )	conjugate)r^   r+   rs   r/   r/   r0   
<dictcomp>   s    z0SparseMatrix._eval_conjugate.<locals>.<dictcomp>)r   rq   rZ   r   r   )r&   rn   r/   r/   r0   _eval_conjugate  s    zSparseMatrix._eval_conjugatec             C   sz  t t|}t t|}i }t|t| t| jk r~xt|D ]8\}}x.t|D ]"\}}	| j||	fd|||f< qRW q@W nFxD| jD ]:\}
}|
|kr||kr| j|
|f |||
||f< qW | t|t||}t|t|kr&x8t|D ],\}}||}||kr|||	|}qW t|t|krvx<t|D ]0\}}	||	}||krB|
|||}qBW |S )Nr   )r=   r   r   r   	enumerater8   indexrZ   Z
row_insertrt   Z
col_insertru   )r&   ZrowsListZcolsListZurowZucolrn   r(   r-   r)   r.   ZrkZckrP   Z
i_previousr/   r/   r0   _eval_extract#  s,    $&


zSparseMatrix._eval_extractc             C   s&   dd t t||D }| |||S )Nc             S   s   i | ]}t j||fqS r/   )r   ZOne)r^   r(   r/   r/   r0   rx   D  s    z*SparseMatrix._eval_eye.<locals>.<dictcomp>)r	   minrZ   )r#   r   r   entriesr/   r/   r0   	_eval_eyeB  s    zSparseMatrix._eval_eyec                sD   t jj  }tjjj kr&d}t fddjD pB|S )NFc             3   s   | ]}| j   V  qd S )N)has)r^   r+   )patternsr&   r/   r0   	<genexpr>N  s    z)SparseMatrix._eval_has.<locals>.<genexpr>)r   r9   r   r   r   r   r   any)r&   r   Zzhasr/   )r   r&   r0   	_eval_hasG  s    zSparseMatrix._eval_hasc                s0   t  fddt jD s dS t j jkS )Nc             3   s   | ]} ||f d kV  qdS )r   Nr/   )r^   r(   )r&   r/   r0   r   Q  s    z1SparseMatrix._eval_is_Identity.<locals>.<genexpr>F)allr	   r   r   r   )r&   r/   )r&   r0   _eval_is_IdentityP  s    zSparseMatrix._eval_is_Identityc             C   s    | | j  |}t| dkS )Nr   )rL   rj   r   values)r&   ZsimpfuncZdiffr/   r/   r0   _eval_is_symmetricU  s    zSparseMatrix._eval_is_symmetricc                s   t |ts| | | S ttx&| j D ]\\}}}|| |< q,W ttx&|j D ]\\}}}|| |< q\W i }xn D ]bx\ D ]P t   t  @ }|rt	 fdd|D }|| f< qW qW | | j
|j|S )z:Fast multiplication exploiting the sparsity of the matrix.c             3   s&   | ]} |   |  V  qd S )Nr/   )r^   rX   )ru   
col_lookuprt   
row_lookupr/   r0   r   n  s    z0SparseMatrix._eval_matrix_mul.<locals>.<genexpr>)r   r   rZ   r   r   r   rq   r!   rl   ro   r   r   )r&   r4   r(   r)   rs   rn   r?   r/   )ru   r   rt   r   r0   _eval_matrix_mulY  s     
 zSparseMatrix._eval_matrix_mulc             C   s   t |tst|}i }x<| j D ].\}}|\}}||krD||j7 }||||f< q"W x.|j D ] \}}|\}}|||| |f< q`W | | j|j | j|S )N)r   r   r   rq   r   rZ   r   )r&   Zirowr4   rr   r+   rs   rt   ru   r/   r/   r0   _eval_row_insertr  s    

zSparseMatrix._eval_row_insertc                s   |   fddS )Nc                s   |   S )Nr/   )ri   )r4   r/   r0   rY     s    z/SparseMatrix._eval_scalar_mul.<locals>.<lambda>)rj   )r&   r4   r/   )r4   r0   _eval_scalar_mul  s    zSparseMatrix._eval_scalar_mulc                s   |   fddS )Nc                s    |  S )Nr/   )ri   )r4   r/   r0   rY     s    z0SparseMatrix._eval_scalar_rmul.<locals>.<lambda>)rj   )r&   r4   r/   )r4   r0   _eval_scalar_rmul  s    zSparseMatrix._eval_scalar_rmulc             C   s&   dd | j  D }| | j| j|S )aK  Returns the transposed SparseMatrix of this SparseMatrix.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> a = SparseMatrix(((1, 2), (3, 4)))
        >>> a
        Matrix([
        [1, 2],
        [3, 4]])
        >>> a.T
        Matrix([
        [1, 3],
        [2, 4]])
        c             S   s   i | ]\\}}}|||fqS r/   r/   )r^   r(   r)   rs   r/   r/   r0   rx     s    z0SparseMatrix._eval_transpose.<locals>.<dictcomp>)r   rq   rZ   r   r   )r&   rn   r/   r/   r0   _eval_transpose  s    zSparseMatrix._eval_transposec             C   s   dd | j  D S )Nc             S   s   g | ]\}}|j s|qS r/   )Zis_zero)r^   rX   r,   r/   r/   r0   ra     s    z-SparseMatrix._eval_values.<locals>.<listcomp>)r   rq   )r&   r/   r/   r0   _eval_values  s    zSparseMatrix._eval_valuesc             C   s   |  ||i S )N)rZ   )r#   r   r   r/   r/   r0   _eval_zeros  s    zSparseMatrix._eval_zerosc             C   s,   |   \}}||}||}|j|S )N)_LDL_sparserK   r[   rL   rM   )r&   rN   rD   DZrO   r/   r/   r0   re     s    

zSparseMatrix._LDL_solvec       
   	   C   s  |   }| | j}| | j| j}xbtt|D ]P}xH|| D ]:}||kr| ||f |||f< d}xj|| D ]^}||k rxP|| D ]@}||k r||kr||||f |||f  |||f  7 }qP qW qxP qxW |||f  |8  < |||f  |||f   < qF||krF| ||f |||f< d}x@|| D ]4}	|	|k rf||||	f d ||	|	f  7 }nP q6W |||f  |8  < qFW q4W ||fS )zLAlgorithm for numeric LDL factization, exploiting sparse structure.
        r   r   )rR   rd   r   rS   r   r	   r   )
r&   Z	LrowstrucrD   r   r(   r)   rU   rV   rW   rX   r/   r/   r0   r     s6    
*
"zSparseMatrix._LDL_sparsec          	   C   s   dd t | jD }x0|  D ]$\}}}||kr|| ||f qW | }xdt | jD ]V}x4|| D ](\}}||df  |||df  8  < qhW ||df  | ||f   < qZW | |S )zsFast algorithm for solving a lower-triangular system,
        exploiting the sparsity of the given matrix.
        c             S   s   g | ]}g qS r/   r/   )r^   r(   r/   r/   r0   ra     s    z8SparseMatrix._lower_triangular_solve.<locals>.<listcomp>r   )r	   r   row_listrA   copyrZ   )r&   rN   r   r(   r)   r,   Xr/   r/   r0   rK     s    $ z$SparseMatrix._lower_triangular_solvec             C   s   t | S )zsReturn a list of matrix elements.  Some routines
        in DenseMatrix use `_mat` directly to speed up operations.)r=   )r&   r/   r/   r0   _mat  s    zSparseMatrix._matc          	   C   s   dd t | jD }x0|  D ]$\}}}||k r|| ||f qW | }xxt | jd ddD ]b}||   x4|| D ](\}}||df  |||df  8  < q|W ||df  | ||f   < qbW | |S )ztFast algorithm for solving an upper-triangular system,
        exploiting the sparsity of the given matrix.
        c             S   s   g | ]}g qS r/   r/   )r^   r(   r/   r/   r0   ra     s    z8SparseMatrix._upper_triangular_solve.<locals>.<listcomp>r   r   )r	   r   r   rA   r   reverserZ   )r&   rN   r   r(   r)   r,   r   r/   r/   r0   rM     s    $ z$SparseMatrix._upper_triangular_solvec             C   sZ   t |std|  }x<| j D ].\}}||}|rD||j|< q$|j|d q$W |S )aa  Apply a function to each element of the matrix.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> m = SparseMatrix(2, 2, lambda i, j: i*2+j)
        >>> m
        Matrix([
        [0, 1],
        [2, 3]])
        >>> m.applyfunc(lambda i: 2*i)
        Matrix([
        [0, 2],
        [4, 6]])

        z`f` must be callable.N)callabler:   r   r   rq   pop)r&   foutrX   r,   fvr/   r/   r0   rj     s    zSparseMatrix.applyfuncc             C   s   ddl m} || S )z,Returns an Immutable version of this Matrix.r   )ImmutableSparseMatrix)Z	immutabler   )r&   r   r/   r/   r0   as_immutable  s    zSparseMatrix.as_immutablec             C   s   t | S )aC  Returns a mutable version of this matrix.

        Examples
        ========

        >>> from sympy import ImmutableMatrix
        >>> X = ImmutableMatrix([[1, 2], [3, 4]])
        >>> Y = X.as_mutable()
        >>> Y[1, 1] = 5 # Can set values in Y
        >>> Y
        Matrix([
        [1, 2],
        [3, 5]])
        )r2   )r&   r/   r/   r0   rc     s    zSparseMatrix.as_mutablec             C   sR   ddl m}m} |  s td|   }||s@||rHtd| |S )a  
        Returns the Cholesky decomposition L of a matrix A
        such that L * L.T = A

        A must be a square, symmetric, positive-definite
        and non-singular matrix

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> A = SparseMatrix(((25,15,-5),(15,18,0),(-5,0,11)))
        >>> A.cholesky()
        Matrix([
        [ 5, 0, 0],
        [ 3, 3, 0],
        [-1, 1, 3]])
        >>> A.cholesky() * A.cholesky().T == A
        True
        r   )nanooz:Cholesky decomposition applies only to symmetric matrices.zACholesky decomposition applies only to positive-definite matrices)	sympy.core.numbersr   r   rb   r"   rc   rJ   r   rZ   )r&   r   r   rf   r/   r/   r0   cholesky,  s    zSparseMatrix.choleskyc                s(    fddt t j dd dD S )a  Returns a column-sorted list of non-zero elements of the matrix.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> a=SparseMatrix(((1, 2), (3, 4)))
        >>> a
        Matrix([
        [1, 2],
        [3, 4]])
        >>> a.CL
        [(0, 0, 1), (1, 0, 3), (0, 1, 2), (1, 1, 4)]

        See Also
        ========
        col_op
        row_list
        c                s   g | ]}t | | f qS r/   )r7   )r^   rX   )r&   r/   r0   ra   `  s    z)SparseMatrix.col_list.<locals>.<listcomp>c             S   s   t t| S )N)r=   reversed)rX   r/   r/   r0   rY   `  s    z'SparseMatrix.col_list.<locals>.<lambda>)r+   )sortedr=   r   r!   )r&   r/   )r&   r0   col_listL  s    zSparseMatrix.col_listc             C   s   |  | j| j| jS )N)rZ   r   r   r   )r&   r/   r/   r0   r   b  s    zSparseMatrix.copyc             C   st   ddl m}m} |  s td|   \}}||sX||sX||sX||r`td| || |fS )a  
        Returns the LDL Decomposition (matrices ``L`` and ``D``) of matrix
        ``A``, such that ``L * D * L.T == A``. ``A`` must be a square,
        symmetric, positive-definite and non-singular.

        This method eliminates the use of square root and ensures that all
        the diagonal entries of L are 1.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> A = SparseMatrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11)))
        >>> L, D = A.LDLdecomposition()
        >>> L
        Matrix([
        [   1,   0, 0],
        [ 3/5,   1, 0],
        [-1/5, 1/3, 1]])
        >>> D
        Matrix([
        [25, 0, 0],
        [ 0, 9, 0],
        [ 0, 0, 9]])
        >>> L * D * L.T == A
        True

        r   )r   r   z5LDL decomposition applies only to symmetric matrices.z<LDL decomposition applies only to positive-definite matrices)	r   r   r   rb   r"   rc   r   r   rZ   )r&   r   r   rD   r   r/   r/   r0   LDLdecompositione  s    (zSparseMatrix.LDLdecompositionc       	      C   s   dd t | jD }x,|  D ] \}}}||kr|| | qW t|}|g| j }|g| j }xnt | jD ]`}xZ|| dd D ]F}x$|| |k r|| }|||< |}qW || |kr| ||< ||< qW qnW ||fS )a  Liu's algorithm, for pre-determination of the Elimination Tree of
        the given matrix, used in row-based symbolic Cholesky factorization.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> S = SparseMatrix([
        ... [1, 0, 3, 2],
        ... [0, 0, 1, 0],
        ... [4, 0, 0, 5],
        ... [0, 6, 7, 0]])
        >>> S.liupc()
        ([[0], [], [0], [1, 2]], [4, 3, 4, 4])

        References
        ==========

        Symbolic Sparse Cholesky Factorization using Elimination Trees,
        Jeroen Van Grondelle (1999)
        http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.39.7582
        c             S   s   g | ]}g qS r/   r/   )r^   r-   r/   r/   r0   ra     s    z&SparseMatrix.liupc.<locals>.<listcomp>Nr   )r	   r   r   rA   r   )	r&   Rr-   r.   _infparentZvirtualrg   r/   r/   r0   liupc  s     zSparseMatrix.liupcc             C   s
   t | jS )z2Returns the number of non-zero elements in Matrix.)r   r   )r&   r/   r/   r0   nnz  s    zSparseMatrix.nnzc                s(    fddt t j dd dD S )a  Returns a row-sorted list of non-zero elements of the matrix.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> a = SparseMatrix(((1, 2), (3, 4)))
        >>> a
        Matrix([
        [1, 2],
        [3, 4]])
        >>> a.RL
        [(0, 0, 1), (0, 1, 2), (1, 0, 3), (1, 1, 4)]

        See Also
        ========
        row_op
        col_list
        c                s   g | ]}t | | f qS r/   )r7   )r^   rX   )r&   r/   r0   ra     s    z)SparseMatrix.row_list.<locals>.<listcomp>c             S   s   t | S )N)r=   )rX   r/   r/   r0   rY     s    z'SparseMatrix.row_list.<locals>.<lambda>)r+   )r   r=   r   r!   )r&   r/   )r&   r0   r     s    
zSparseMatrix.row_listc             C   s   |   \}}t|}t|}xht| jD ]Z}x<|| D ]0}x*||krf||krf|| | || }q>W q8W ttt	|| ||< q*W |S )a  Symbolic cholesky factorization, for pre-determination of the
        non-zero structure of the Cholesky factororization.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> S = SparseMatrix([
        ... [1, 0, 3, 2],
        ... [0, 0, 1, 0],
        ... [4, 0, 0, 5],
        ... [0, 6, 7, 0]])
        >>> S.row_structure_symbolic_cholesky()
        [[0], [], [0], [1, 2]]

        References
        ==========

        Symbolic Sparse Cholesky Factorization using Elimination Trees,
        Jeroen Van Grondelle (1999)
        http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.39.7582
        )
r   r   r   deepcopyr	   r   rA   r=   r   rl   )r&   r   r   r   ZLrowrX   r)   r/   r/   r0   rR     s    
z,SparseMatrix.row_structure_symbolic_choleskyc             C   sP   | j | j }|rLx:| jD ]0}|| j|  }|r:||j|< q|j|d qW |S )z"Scalar element-wise multiplicationN)rS   r1   r   r   )r&   Zscalarrf   r(   r,   r/   r/   r0   scalar_multiply  s    zSparseMatrix.scalar_multiplyr]   c             C   s   | j }||  j|d| | S )a  Return the least-square fit to the data.

        By default the cholesky_solve routine is used (method='CH'); other
        methods of matrix inversion can be used. To find out which are
        available, see the docstring of the .inv() method.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix, Matrix, ones
        >>> A = Matrix([1, 2, 3])
        >>> B = Matrix([2, 3, 4])
        >>> S = SparseMatrix(A.row_join(B))
        >>> S
        Matrix([
        [1, 2],
        [2, 3],
        [3, 4]])

        If each line of S represent coefficients of Ax + By
        and x and y are [2, 3] then S*xy is:

        >>> r = S*Matrix([2, 3]); r
        Matrix([
        [ 8],
        [13],
        [18]])

        But let's add 1 to the middle value and then solve for the
        least-squares value of xy:

        >>> xy = S.solve_least_squares(Matrix([8, 14, 18])); xy
        Matrix([
        [ 5/3],
        [10/3]])

        The error is given by S*xy - r:

        >>> S*xy - r
        Matrix([
        [1/3],
        [1/3],
        [1/3]])
        >>> _.norm().n(2)
        0.58

        If a different xy is used, the norm will be higher:

        >>> xy += ones(2, 1)/10
        >>> (S*xy - r).norm().n(2)
        1.5

        )r\   )rL   inv)r&   rN   r\   rg   r/   r/   r0   solve_least_squares  s    6z SparseMatrix.solve_least_squaresc             C   sF   | j s2| j| jk rtdqB| j| jkrBtdn| j|d| S dS )zReturn solution to self*soln = rhs using given inversion method.

        For a list of possible inversion methods, see the .inv() docstring.
        zUnder-determined system.z]For over-determined system, M, having more rows than columns, try M.solve_least_squares(rhs).)r\   N)Z	is_squarer   r   r"   r   )r&   rN   r\   r/   r/   r0   r`   <  s    

zSparseMatrix.solveNzAlternate faster representation)r]   )r]   )3__name__
__module____qualname____doc__r   r5   rG   rI   rQ   rJ   r[   rh   rk   rp   rv   ry   r|   classmethodr   r   r   r   r   r   r   r   r   r   r   re   r   rK   propertyr   rM   rj   r   rc   r   r   r   r   r   r   r   rR   r   r   r`   ZRLZCLr/   r/   r/   r0   r      s\   3."4	$ (,#
9
r   c               @   s   e Zd Zedd Zdd Zdd Z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S ) r2   c             O   s   | | S )Nr/   )r#   r$   r%   r/   r/   r0   rZ   P  s    zMutableSparseMatrix._newc             C   sP   |  ||}|dk	rL|\}}}|r2|| j||f< n||f| jkrL| j||f= dS )a?  Assign value to position designated by key.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix, ones
        >>> M = SparseMatrix(2, 2, {})
        >>> M[1] = 1; M
        Matrix([
        [0, 1],
        [0, 0]])
        >>> M[1, 1] = 2; M
        Matrix([
        [0, 1],
        [0, 2]])
        >>> M = SparseMatrix(2, 2, {})
        >>> M[:, 1] = [1, 1]; M
        Matrix([
        [0, 1],
        [0, 1]])
        >>> M = SparseMatrix(2, 2, {})
        >>> M[1, :] = [[1, 1]]; M
        Matrix([
        [0, 0],
        [1, 1]])


        To replace row r you assign to position r*m where m
        is the number of columns:

        >>> M = SparseMatrix(4, 4, {})
        >>> m = M.cols
        >>> M[3*m] = ones(1, m)*2; M
        Matrix([
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [2, 2, 2, 2]])

        And to replace column c you can assign to position c:

        >>> M[2] = ones(m, 1)*4; M
        Matrix([
        [0, 0, 4, 0],
        [0, 0, 4, 0],
        [0, 0, 4, 0],
        [2, 2, 4, 2]])
        N)Z_setitemr   )r&   r+   r*   rP   r(   r)   r/   r/   r0   rI   T  s    1
zMutableSparseMatrix.__setitem__c             C   s   |   S )N)r   )r&   r/   r/   r0   rc     s    zMutableSparseMatrix.as_mutableNc             C   s   i }t || j}xV| jD ]L\}}||kr*q||krN| j||f |||d f< q| j||f |||f< qW || _|  jd8  _dS )a}  Delete the given column of the matrix.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> M = SparseMatrix([[0, 0], [0, 1]])
        >>> M
        Matrix([
        [0, 0],
        [0, 1]])
        >>> M.col_del(0)
        >>> M
        Matrix([
        [0],
        [1]])

        See Also
        ========

        row_del
        r   N)r   r   r   )r&   rX   newDr(   r)   r/   r/   r0   col_del  s    zMutableSparseMatrix.col_delc       	      C   s   | j dkr,| j|jkr,| d|jg |S | | }}|j|jksHt | }t|tsd}|j}xt	|j D ]@}x:t	|jD ],}|| }|r||j
||j  |f< |d7 }qW qpW n0x.|j
 D ] \\}}}||j
||j  |f< qW | j |j 7  _ |S )a,  Returns B augmented beneath A (row-wise joining)::

            [A]
            [B]

        Examples
        ========

        >>> from sympy import SparseMatrix, Matrix, ones
        >>> A = SparseMatrix(ones(3))
        >>> A
        Matrix([
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]])
        >>> B = SparseMatrix.eye(3)
        >>> B
        Matrix([
        [1, 0, 0],
        [0, 1, 0],
        [0, 0, 1]])
        >>> C = A.col_join(B); C
        Matrix([
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1],
        [1, 0, 0],
        [0, 1, 0],
        [0, 0, 1]])
        >>> C == A.col_join(Matrix(B))
        True

        Joining along columns is the same as appending rows at the end
        of the matrix:

        >>> C == A.row_insert(A.rows, Matrix(B))
        True
        r   r   )r   r   rZ   col_joinr   r   r   r   r   r	   r   rq   )	r&   r4   ABrX   br(   r)   r,   r/   r/   r0   r     s&    (

zMutableSparseMatrix.col_joinc             C   s^   xXt | jD ]J}| j||ftj}|||}|rB|| j||f< q|r| j||f qW dS )a  In-place operation on col j using two-arg functor whose args are
        interpreted as (self[i, j], i) for i in range(self.rows).

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> M = SparseMatrix.eye(3)*2
        >>> M[1, 0] = -1
        >>> M.col_op(1, lambda v, i: v + 2*M[i, 0]); M
        Matrix([
        [ 2, 4, 0],
        [-1, 0, 0],
        [ 0, 0, 2]])
        N)r	   r   r   r8   r   r9   r   )r&   r)   r   r(   r,   r   r/   r/   r0   col_op  s    
zMutableSparseMatrix.col_opc       	      C   s   ||kr|| }}|   }g }xl|D ]d\}}}||krV| j||f |||f q$||kr~| j||f || j||f< q$||kr$P q$W x|D ]\}}|| j||f< qW dS )a  Swap, in place, columns i and j.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> S = SparseMatrix.eye(3); S[2, 1] = 2
        >>> S.col_swap(1, 0); S
        Matrix([
        [0, 1, 0],
        [1, 0, 0],
        [2, 0, 1]])
        N)r   r   r   rA   )	r&   r(   r)   r   tempiijjr,   rX   r/   r/   r0   col_swap  s    
zMutableSparseMatrix.col_swapc             C   s$   t |std| |t| d S )Nz&`value` must be of type list or tuple.)r   r:   copyin_matrixr   )r&   r+   r*   r/   r/   r0   copyin_list)  s    zMutableSparseMatrix.copyin_listc             C   s  |  |\}}}}|j}|| ||  }}	|||	fkr>tdt|tsxBt|jD ]4}
x.t|jD ] }||
|f | |
| || f< qdW qTW n|| ||  t| k rxt||D ]*}
x$t||D ]}| j	
|
|fd  qW qW n^x\|  D ]P\}
}}||
  kr|k rn q||  kr&|k rn q| j	
|
|fd  qW x<|j	 D ].\}}|\}
}||
|f | |
| || f< qLW d S )NzXThe Matrix `value` doesn't have the same dimensions as the in sub-Matrix given by `key`.)Z
key2boundsr1   r   r   r   r	   r   r   r   r   r   r   rq   )r&   r+   r*   ZrloZrhiZcloZchir1   ZdrZdcr(   r)   r,   rX   r/   r/   r0   r   .  s(    
&4z!MutableSparseMatrix.copyin_matrixc                s:   |si  _ n* |t fddt jD  _ dS )a  Fill self with the given value.

        Notes
        =====

        Unless many values are going to be deleted (i.e. set to zero)
        this will create a matrix that is slower than a dense matrix in
        operations.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> M = SparseMatrix.zeros(3); M
        Matrix([
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]])
        >>> M.fill(1); M
        Matrix([
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]])
        c                s(   g | ] }t  jD ]}||ffqqS r/   )r	   r   )r^   r(   r)   )r&   r,   r/   r0   ra   e  s   z,MutableSparseMatrix.fill.<locals>.<listcomp>N)r   r    r   r	   r   )r&   r*   r/   )r&   r,   r0   fillH  s
    
zMutableSparseMatrix.fillc             C   s   i }t || j}xV| jD ]L\}}||kr*q||krN| j||f ||d |f< q| j||f |||f< qW || _|  jd8  _dS )ag  Delete the given row of the matrix.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> M = SparseMatrix([[0, 0], [0, 1]])
        >>> M
        Matrix([
        [0, 0],
        [0, 1]])
        >>> M.row_del(0)
        >>> M
        Matrix([[0, 1]])

        See Also
        ========

        col_del
        r   N)r   r   r   )r&   rX   r   r(   r)   r/   r/   r0   row_delh  s    zMutableSparseMatrix.row_delc       	      C   s   | j dkr,| j|jkr,| |jdg |S | | }}|j|jksHt | }t|tsd}|j}xt	|jD ]@}x:t	|j D ],}|| }|r||j
|||j  f< |d7 }qW qpW n0x.|j
 D ] \\}}}||j
|||j  f< qW | j |j 7  _ |S )a,  Returns B appended after A (column-wise augmenting)::

            [A B]

        Examples
        ========

        >>> from sympy import SparseMatrix, Matrix
        >>> A = SparseMatrix(((1, 0, 1), (0, 1, 0), (1, 1, 0)))
        >>> A
        Matrix([
        [1, 0, 1],
        [0, 1, 0],
        [1, 1, 0]])
        >>> B = SparseMatrix(((1, 0, 0), (0, 1, 0), (0, 0, 1)))
        >>> B
        Matrix([
        [1, 0, 0],
        [0, 1, 0],
        [0, 0, 1]])
        >>> C = A.row_join(B); C
        Matrix([
        [1, 0, 1, 1, 0, 0],
        [0, 1, 0, 0, 1, 0],
        [1, 1, 0, 0, 0, 1]])
        >>> C == A.row_join(Matrix(B))
        True

        Joining at row ends is the same as appending columns at the end
        of the matrix:

        >>> C == A.col_insert(A.cols, B)
        True
        r   r   )r   r   rZ   row_joinr   r   r   r   r   r	   r   rq   )	r&   r4   r   r   rX   r   r(   r)   r,   r/   r/   r0   r     s&    $

zMutableSparseMatrix.row_joinc             C   s^   xXt | jD ]J}| j||ftj}|||}|rB|| j||f< q|r| j||f qW dS )a  In-place operation on row ``i`` using two-arg functor whose args are
        interpreted as ``(self[i, j], j)``.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> M = SparseMatrix.eye(3)*2
        >>> M[0, 1] = -1
        >>> M.row_op(1, lambda v, j: v + 2*M[0, j]); M
        Matrix([
        [2, -1, 0],
        [4,  0, 0],
        [0,  0, 2]])

        See Also
        ========
        row
        zip_row_op
        col_op

        N)r	   r   r   r8   r   r9   r   )r&   r(   r   r)   r,   r   r/   r/   r0   row_op  s    
zMutableSparseMatrix.row_opc       	      C   s   ||kr|| }}|   }g }xl|D ]d\}}}||krV| j||f |||f q$||kr~| j||f || j||f< q$||kr$P q$W x|D ]\}}|| j||f< qW dS )a  Swap, in place, columns i and j.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> S = SparseMatrix.eye(3); S[2, 1] = 2
        >>> S.row_swap(1, 0); S
        Matrix([
        [0, 1, 0],
        [1, 0, 0],
        [0, 2, 1]])
        N)r   r   r   rA   )	r&   r(   r)   r   r   r   r   r,   rX   r/   r/   r0   row_swap  s    
zMutableSparseMatrix.row_swapc                s    | fdd dS )a  In-place operation on row ``i`` using two-arg functor whose args are
        interpreted as ``(self[i, j], self[k, j])``.

        Examples
        ========

        >>> from sympy.matrices import SparseMatrix
        >>> M = SparseMatrix.eye(3)*2
        >>> M[0, 1] = -1
        >>> M.zip_row_op(1, 0, lambda v, u: v + 2*u); M
        Matrix([
        [2, -1, 0],
        [4,  0, 0],
        [0,  0, 2]])

        See Also
        ========
        row
        row_op
        col_op

        c                s    | |f S )Nr/   )r,   r)   )r   rX   r&   r/   r0   rY     s    z0MutableSparseMatrix.zip_row_op.<locals>.<lambda>N)r   )r&   r(   rX   r   r/   )r   rX   r&   r0   
zip_row_op   s    zMutableSparseMatrix.zip_row_op)r   r   r   r   rZ   rI   rc   __hash__r   r   r   r   r   r   r   r   r   r   r   r   r/   r/   r/   r0   r2   O  s    9#> !:r2   )"Z
__future__r   r   r   collectionsr   Zsympy.core.containersr   Zsympy.core.exprr   Zsympy.core.compatibilityr   r   r	   r
   Zsympy.core.logicr   Zsympy.core.singletonr   Zsympy.functionsr   Z(sympy.functions.elementary.miscellaneousr   Zsympy.utilities.iterablesr   Zmatricesr   r   Zdenser   commonr   r   r2   r/   r/   r/   r0   <module>   s*         A