Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" 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 """
op(self._sympify(i), self._sympify(j))) # manual copy, copy.deepcopy() doesn't work raise ValueError( 'List length (%s) != rows*columns (%s)' % (len(args[2]), self.rows*self.cols)) else: # handle full matrix forms with _handle_creation_inputs
# XXX remove list() when PY2 support is dropped else: raise IndexError('Row index out of bounds') # XXX remove list() when PY2 support is dropped else:
# check for single arg, like M[:] or M[3]
raise NotImplementedError()
def is_Identity(self):
"""Convert this sparse matrix into a list of nested Python lists.
Examples ========
>>> from sympy.matrices import SparseMatrix, ones >>> a = SparseMatrix(((1, 2), (3, 4))) >>> a.tolist() [[1, 2], [3, 4]]
When there are no rows then it will not be possible to tell how many columns were in the original matrix:
>>> SparseMatrix(ones(0, 3)).tolist() []
""" return [] return [[] for i in range(self.rows)]
"""Returns column i from self as a row vector.
Examples ========
>>> from sympy.matrices import SparseMatrix >>> a = SparseMatrix(((1, 2), (3, 4))) >>> a.row(0) Matrix([[1, 2]])
See Also ======== col row_list """
"""Returns column j from self as a column vector.
Examples ========
>>> from sympy.matrices import SparseMatrix >>> a = SparseMatrix(((1, 2), (3, 4))) >>> a.col(0) Matrix([ [1], [3]])
See Also ======== row col_list """
"""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 """ sorted(list(self._smat.keys()), key=lambda k: list(k))]
"""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 """
"""Calculate the trace of a square matrix.
Examples ========
>>> from sympy.matrices import eye >>> eye(3).trace() 3
"""
"""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]]) """
"""Return the by-element conjugation.
Examples ========
>>> from sympy.matrices import SparseMatrix >>> from sympy import I >>> a = SparseMatrix(((1, 2 + I), (3, 4), (I, -I))) >>> a Matrix([ [1, 2 + I], [3, 4], [I, -I]]) >>> a.C Matrix([ [ 1, 2 - I], [ 3, 4], [-I, I]])
See Also ========
transpose: Matrix transposition H: Hermite conjugation D: Dirac conjugation """
"""Fast multiplication exploiting the sparsity of the matrix.
Examples ========
>>> from sympy.matrices import SparseMatrix, ones >>> A, B = SparseMatrix(ones(4, 3)), SparseMatrix(ones(3, 4)) >>> A.multiply(B) == 3*ones(4) True
See Also ========
add """ # sort B's row_list into list of rows
"Scalar element-wise multiplication" else: M._smat.pop(i, None)
"""Multiply self and other, watching for non-matrix entities.
When multiplying be a non-sparse matrix, the result is no longer sparse.
Examples ========
>>> from sympy.matrices import SparseMatrix, eye, zeros >>> I = SparseMatrix(eye(3)) >>> I*I == I True >>> Z = zeros(3) >>> I*Z Matrix([ [0, 0, 0], [0, 0, 0], [0, 0, 0]]) >>> I*2 == 2*I True """
"""Return product the same type as other (if a Matrix).
When multiplying be a non-sparse matrix, the result is no longer sparse.
Examples ========
>>> from sympy.matrices import Matrix, SparseMatrix >>> A = Matrix(2, 2, range(1, 5)) >>> S = SparseMatrix(2, 2, range(2, 6)) >>> A*S == S*A False >>> (isinstance(A*S, SparseMatrix) == ... isinstance(S*A, SparseMatrix) == False) True """ return other*other._new(self)
"""Add other to self, efficiently if possible.
When adding a non-sparse matrix, the result is no longer sparse.
Examples ========
>>> from sympy.matrices import SparseMatrix, eye >>> A = SparseMatrix(eye(3)) + SparseMatrix(eye(3)) >>> B = SparseMatrix(eye(3)) + eye(3) >>> A Matrix([ [2, 0, 0], [0, 2, 0], [0, 0, 2]]) >>> A == B True >>> isinstance(A, SparseMatrix) and isinstance(B, SparseMatrix) False
""" else: raise NotImplementedError( "Cannot add %s to %s" % tuple([c.__class__.__name__ for c in (other, self)]))
"""Negate all elements of self.
Examples ========
>>> from sympy.matrices import SparseMatrix, eye >>> -SparseMatrix(eye(3)) Matrix([ [-1, 0, 0], [ 0, -1, 0], [ 0, 0, -1]])
"""
"""Add two sparse matrices with dictionary representation.
Examples ========
>>> from sympy.matrices import SparseMatrix, eye, ones >>> SparseMatrix(eye(3)).add(SparseMatrix(ones(3))) Matrix([ [2, 1, 1], [1, 2, 1], [1, 1, 2]]) >>> SparseMatrix(eye(3)).add(-SparseMatrix(eye(3))) Matrix([ [0, 0, 0], [0, 0, 0], [0, 0, 0]])
Only the non-zero elements are stored, so the resulting dictionary that is used to represent the sparse matrix is empty:
>>> _._smat {}
See Also ========
multiply """ raise ValueError('only use add with %s, not %s' % tuple([c.__class__.__name__ for c in (self, other)])) else:
# there are fewer elements requested than there are elements in the matrix else: # most of the request will be zeros so check all of self's entries, # keeping only the ones that are desired
# rv is nominally correct but there might be rows/cols # which require duplication
def is_hermitian(self): """Checks if the matrix is Hermitian.
In a Hermitian matrix element i,j is the complex conjugate of element j,i.
Examples ========
>>> from sympy.matrices import SparseMatrix >>> from sympy import I >>> from sympy.abc import x >>> a = SparseMatrix([[1, I], [-I, 1]]) >>> a Matrix([ [ 1, I], [-I, 1]]) >>> a.is_hermitian True >>> a[0, 0] = 2*I >>> a.is_hermitian False >>> a[0, 0] = x >>> a.is_hermitian >>> a[0, 1] = a[1, 0]*I >>> a.is_hermitian False """ d[i, i].is_real for i, j in d if i == j) else: d[i, i].is_real for i in range(self.rows) if (i, i) in d) ((self[i, j] - self[j, i].conjugate()).is_zero if (j, i) in d else False) for (i, j) in d)
"""Return True if self is symmetric.
Examples ========
>>> from sympy.matrices import SparseMatrix, eye >>> M = SparseMatrix(eye(3)) >>> M.is_symmetric() True >>> M[0, 2] = 1 >>> M.is_symmetric() False """ not (self[k] - self[(k[1], k[0])]).simplify() for k in self._smat) else: self[k] == self[(k[1], k[0])] for k in self._smat)
"""Test whether any subexpression matches any of the patterns.
Examples ========
>>> from sympy import SparseMatrix, Float >>> from sympy.abc import x, y >>> A = SparseMatrix(((1, x), (0.2, 3))) >>> A.has(x) True >>> A.has(y) False >>> A.has(Float) True """
"""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]])
""" raise TypeError("`f` must be callable.")
else:
"""Reshape matrix while retaining original size.
Examples ========
>>> from sympy.matrices import SparseMatrix >>> S = SparseMatrix(4, 2, range(8)) >>> S.reshape(2, 4) Matrix([ [0, 1, 2, 3], [4, 5, 6, 7]])
""" raise ValueError("Invalid reshape parameters %d %d" % (rows, cols))
"""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 """ # Algorithm 2.4, p 17 of reference
# get the indices of the elements that are non-zero on or below diag
"""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 """
"""Algorithm for numeric Cholesky factorization of a sparse matrix.""" else: else: break else: else:
"""Algorithm for numeric LDL factization, exploiting sparse structure. """
else: else: else:
"""Fast algorithm for solving a lower-triangular system, exploiting the sparsity of the given matrix. """
"""Fast algorithm for solving an upper-triangular system, exploiting the sparsity of the given matrix. """
"Diagonal solve."
# for speed reasons, this is not uncommented, but if you are # having difficulties, try uncommenting to make sure that the # input matrix is symmetric
#assert self.is_symmetric()
# for speed reasons, this is not uncommented, but if you are # having difficulties, try uncommenting to make sure that the # input matrix is symmetric
#assert self.is_symmetric()
""" 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 """
raise ValueError('Cholesky decomposition applies only to ' 'symmetric matrices.') raise ValueError('Cholesky decomposition applies only to ' 'positive-definite matrices')
""" 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
""" raise ValueError('LDL decomposition applies only to ' 'symmetric matrices.') raise ValueError('LDL decomposition applies only to ' 'positive-definite matrices')
"""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
"""
"""Return solution to self*soln = rhs using given inversion method.
For a list of possible inversion methods, see the .inv() docstring. """ if self.rows < self.cols: raise ValueError('Under-determined system.') elif self.rows > self.cols: raise ValueError('For over-determined system, M, having ' 'more rows than columns, try M.solve_least_squares(rhs).') else:
"""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]])
""" else: raise NotImplementedError( 'Method may be "CH" or "LDL", not %s.' % method)
return False except AttributeError: return False
"""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]]) """
"""Returns an Immutable version of this Matrix."""
"""Returns the number of non-zero elements in Matrix."""
"""Return an r x c matrix of zeros, square if c is omitted."""
def eye(cls, n): """Return an n x n identity matrix."""
def _new(cls, *args, **kwargs):
"""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]]) """
"""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 """ else:
"""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 """ else:
"""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]]) """
"""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]]) """
"""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 """ raise ShapeError() k = 0 b = B._mat for i in range(B.rows): for j in range(B.cols): v = b[k] if v: A._smat[(i, j + A.cols)] = v k += 1 else:
"""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 """ raise ShapeError() k = 0 b = B._mat for i in range(B.rows): for j in range(B.cols): v = b[k] if v: A._smat[(i + A.rows, j)] = v k += 1 else:
# include this here because it's not part of BaseMatrix raise ShapeError( "The Matrix `value` doesn't have the same dimensions " "as the in sub-Matrix given by `key`.") else: else:
"""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
"""
"""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
"""
"""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]]) """ for i in range(self.rows): v = self._smat.get((i, j), S.Zero) fv = f(v, i) if fv: self._smat[(i, j)] = fv elif v: self._smat.pop((i, j))
"""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]]) """ if not value: self._smat = {} else: v = self._sympify(value) self._smat = dict([((i, j), v) for i in range(self.rows) for j in range(self.cols)]) |