# Introducing the domainmatrix of the poly module#

This page introduces the idea behind domainmatrix which is used in SymPy’s sympy.polys module. This is a relatively advanced topic so for a better understanding it is recommended to read about Domain and DDM along with sympy.matrices module.

## What is domainmatrix?#

It is way of associating Matrix with Domain.

A domainmatrix represents a matrix with elements that are in a particular Domain. Each domainmatrix internally wraps a DDM which is used for the lower-level operations. The idea is that the domainmatrix class provides the convenience routines for converting between Expr and the poly domains as well as unifying matrices with different domains.

In general, we represent a matrix without concerning about the Domain as:
>>> from sympy import Matrix
>>> from sympy.polys.matrices import DomainMatrix
>>> A = Matrix([
... [1, 2],
... [3, 4]])
>>> A
Matrix([
[1, 2],
[3, 4]])

class sympy.polys.matrices.domainmatrix.DomainMatrix(rows, shape, domain, *, fmt=None)[source]#

Associate Matrix with Domain

Explanation

DomainMatrix uses Domain for its internal representation which makes it faster than the SymPy Matrix class (currently) for many common operations, but this advantage makes it not entirely compatible with Matrix. DomainMatrix are analogous to numpy arrays with “dtype”. In the DomainMatrix, each element has a domain such as ZZ or QQ<a>.

Examples

Creating a DomainMatrix from the existing Matrix class:

>>> from sympy import Matrix
>>> from sympy.polys.matrices import DomainMatrix
>>> Matrix1 = Matrix([
...    [1, 2],
...    [3, 4]])
>>> A = DomainMatrix.from_Matrix(Matrix1)
>>> A
DomainMatrix({0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}}, (2, 2), ZZ)


Directly forming a DomainMatrix:

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [ZZ(1), ZZ(2)],
...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)
>>> A
DomainMatrix([[1, 2], [3, 4]], (2, 2), ZZ)


Adds two DomainMatrix matrices of the same Domain

Parameters:

A, B: DomainMatrix

Returns:

DomainMatrix

Raises:

DMShapeError

If the dimensions of the two DomainMatrix are not equal

ValueError

If the domain of the two DomainMatrix are not same

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [ZZ(1), ZZ(2)],
...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)
>>> B = DomainMatrix([
...    [ZZ(4), ZZ(3)],
...    [ZZ(2), ZZ(1)]], (2, 2), ZZ)

>>> A.add(B)
DomainMatrix([[5, 5], [5, 5]], (2, 2), ZZ)


charpoly()[source]#

Returns the coefficients of the characteristic polynomial of the DomainMatrix. These elements will be domain elements. The domain of the elements will be same as domain of the DomainMatrix.

Returns:

list

coefficients of the characteristic polynomial

Raises:

DMNonSquareMatrixError

If the DomainMatrix is not a not Square DomainMatrix

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [ZZ(1), ZZ(2)],
...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)

>>> A.charpoly()
[1, -5, -2]

columnspace()[source]#

Returns the columnspace for the DomainMatrix

Returns:

DomainMatrix

The columns of this matrix form a basis for the columnspace.

Examples

>>> from sympy import QQ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [QQ(1), QQ(-1)],
...    [QQ(2), QQ(-2)]], (2, 2), QQ)
>>> A.columnspace()
DomainMatrix([, ], (2, 1), QQ)

convert_to(K)[source]#

Change the domain of DomainMatrix to desired domain or field

Parameters:

K : Represents the desired domain or field.

Alternatively, None may be passed, in which case this method just returns a copy of this DomainMatrix.

Returns:

DomainMatrix

DomainMatrix with the desired domain or field

Examples

>>> from sympy import ZZ, ZZ_I
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [ZZ(1), ZZ(2)],
...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)

>>> A.convert_to(ZZ_I)
DomainMatrix([[1, 2], [3, 4]], (2, 2), ZZ_I)

det()[source]#

Returns the determinant of a Square DomainMatrix

Returns:

S.Complexes

determinant of Square DomainMatrix

Raises:

ValueError

If the domain of DomainMatrix not a Field

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [ZZ(1), ZZ(2)],
...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)

>>> A.det()
-2

classmethod diag(diagonal, domain, shape=None)[source]#

Return diagonal matrix with entries from diagonal.

Examples

>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy import ZZ
>>> DomainMatrix.diag([ZZ(5), ZZ(6)], ZZ)
DomainMatrix({0: {0: 5}, 1: {1: 6}}, (2, 2), ZZ)

classmethod eye(shape, domain)[source]#

Return identity matrix of size n

Examples

>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy import QQ
>>> DomainMatrix.eye(3, QQ)
DomainMatrix({0: {0: 1}, 1: {1: 1}, 2: {2: 1}}, (3, 3), QQ)

classmethod from_Matrix(M, fmt='sparse', **kwargs)[source]#

Convert Matrix to DomainMatrix

Parameters:

M: Matrix

Returns:

Returns DomainMatrix with identical elements as M

Examples

>>> from sympy import Matrix
>>> from sympy.polys.matrices import DomainMatrix
>>> M = Matrix([
...    [1.0, 3.4],
...    [2.4, 1]])
>>> A = DomainMatrix.from_Matrix(M)
>>> A
DomainMatrix({0: {0: 1.0, 1: 3.4}, 1: {0: 2.4, 1: 1.0}}, (2, 2), RR)


We can keep internal representation as ddm using fmt=’dense’ >>> from sympy import Matrix, QQ >>> from sympy.polys.matrices import DomainMatrix >>> A = DomainMatrix.from_Matrix(Matrix([[QQ(1, 2), QQ(3, 4)], [QQ(0, 1), QQ(0, 1)]]), fmt=’dense’) >>> A.rep [[1/2, 3/4], [0, 0]]

classmethod from_dict_sympy(nrows, ncols, elemsdict, **kwargs)[source]#
Parameters:

nrows: number of rows

ncols: number of cols

elemsdict: dict of dicts containing non-zero elements of the DomainMatrix

Returns:

DomainMatrix containing elements of elemsdict

Examples

>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy.abc import x,y,z
>>> elemsdict = {0: {0:x}, 1:{1: y}, 2: {2: z}}
>>> A = DomainMatrix.from_dict_sympy(3, 3, elemsdict)
>>> A
DomainMatrix({0: {0: x}, 1: {1: y}, 2: {2: z}}, (3, 3), ZZ[x,y,z])

classmethod from_list(rows, domain)[source]#

Convert a list of lists into a DomainMatrix

Parameters:

rows: list of lists

Each element of the inner lists should be either the single arg, or tuple of args, that would be passed to the domain constructor in order to form an element of the domain. See examples.

Returns:

DomainMatrix containing elements defined in rows

Examples

>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy import FF, QQ, ZZ
>>> A = DomainMatrix.from_list([[1, 0, 1], [0, 0, 1]], ZZ)
>>> A
DomainMatrix([[1, 0, 1], [0, 0, 1]], (2, 3), ZZ)
>>> B = DomainMatrix.from_list([[1, 0, 1], [0, 0, 1]], FF(7))
>>> B
DomainMatrix([[1 mod 7, 0 mod 7, 1 mod 7], [0 mod 7, 0 mod 7, 1 mod 7]], (2, 3), GF(7))
>>> C = DomainMatrix.from_list([[(1, 2), (3, 1)], [(1, 4), (5, 1)]], QQ)
>>> C
DomainMatrix([[1/2, 3], [1/4, 5]], (2, 2), QQ)

classmethod from_list_sympy(nrows, ncols, rows, **kwargs)[source]#

Convert a list of lists of Expr into a DomainMatrix using construct_domain

Parameters:

nrows: number of rows

ncols: number of columns

rows: list of lists

Returns:

DomainMatrix containing elements of rows

Examples

>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy.abc import x, y, z
>>> A = DomainMatrix.from_list_sympy(1, 3, [[x, y, z]])
>>> A
DomainMatrix([[x, y, z]], (1, 3), ZZ[x,y,z])

classmethod from_rep(rep)[source]#

Create a new DomainMatrix efficiently from DDM/SDM.

Parameters:

rep: SDM or DDM

The internal sparse or dense representation of the matrix.

Returns:

DomainMatrix

Examples

Create a DomainMatrix with an dense internal representation as DDM:

>>> from sympy.polys.domains import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy.polys.matrices.ddm import DDM
>>> drep = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
>>> dM = DomainMatrix.from_rep(drep)
>>> dM
DomainMatrix([[1, 2], [3, 4]], (2, 2), ZZ)


Create a DomainMatrix with a sparse internal representation as SDM:

>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import ZZ
>>> drep = SDM({0:{1:ZZ(1)},1:{0:ZZ(2)}}, (2, 2), ZZ)
>>> dM = DomainMatrix.from_rep(drep)
>>> dM
DomainMatrix({0: {1: 1}, 1: {0: 2}}, (2, 2), ZZ)


Notes

This takes ownership of rep as its internal representation. If rep is being mutated elsewhere then a copy should be provided to from_rep. Only minimal verification or checking is done on rep as this is supposed to be an efficient internal routine.

hstack(*B)[source]#

Horizontally stack the given matrices.

Parameters:

B: DomainMatrix

Matrices to stack horizontally.

Returns:

DomainMatrix

DomainMatrix by stacking horizontally.

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix

>>> A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
>>> B = DomainMatrix([[ZZ(5), ZZ(6)], [ZZ(7), ZZ(8)]], (2, 2), ZZ)
>>> A.hstack(B)
DomainMatrix([[1, 2, 5, 6], [3, 4, 7, 8]], (2, 4), ZZ)

>>> C = DomainMatrix([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ)
>>> A.hstack(B, C)
DomainMatrix([[1, 2, 5, 6, 9, 10], [3, 4, 7, 8, 11, 12]], (2, 6), ZZ)

inv()[source]#

Finds the inverse of the DomainMatrix if exists

Returns:

DomainMatrix

DomainMatrix after inverse

Raises:

ValueError

If the domain of DomainMatrix not a Field

DMNonSquareMatrixError

If the DomainMatrix is not a not Square DomainMatrix

Examples

>>> from sympy import QQ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...     [QQ(2), QQ(-1), QQ(0)],
...     [QQ(-1), QQ(2), QQ(-1)],
...     [QQ(0), QQ(0), QQ(2)]], (3, 3), QQ)
>>> A.inv()
DomainMatrix([[2/3, 1/3, 1/6], [1/3, 2/3, 1/3], [0, 0, 1/2]], (3, 3), QQ)

property is_lower#

Says whether this matrix is lower-triangular. True can be returned even if the matrix is not square.

property is_upper#

Says whether this matrix is upper-triangular. True can be returned even if the matrix is not square.

lll(delta=MPQ(3, 4))[source]#

Performs the Lenstra–Lenstra–Lovász (LLL) basis reduction algorithm. See [R713] and [R714].

Parameters:

delta : QQ, optional

The Lovász parameter. Must be in the interval (0.25, 1), with larger values producing a more reduced basis. The default is 0.75 for historical reasons.

Returns:

The reduced basis as a DomainMatrix over ZZ.

Throws

DMValueError: if delta is not in the range (0.25, 1) DMShapeError: if the matrix is not of shape (m, n) with m <= n DMDomainError: if the matrix domain is not ZZ DMRankError: if the matrix contains linearly dependent rows

Examples

>>> from sympy.polys.domains import ZZ, QQ
>>> from sympy.polys.matrices import DM
>>> x = DM([[1, 0, 0, 0, -20160],
...         [0, 1, 0, 0, 33768],
...         [0, 0, 1, 0, 39578],
...         [0, 0, 0, 1, 47757]], ZZ)
>>> y = DM([[10, -3, -2, 8, -4],
...         [3, -9, 8, 1, -11],
...         [-3, 13, -9, -3, -9],
...         [-12, -7, -11, 9, -1]], ZZ)
>>> assert x.lll(delta=QQ(5, 6)) == y


Notes

The implementation is derived from the Maple code given in Figures 4.3 and 4.4 of [R715] (pp.68-69). It uses the efficient method of only calculating state updates as they are required.

References

[R713] (1,2)

https://en.wikipedia.org/wiki/Lenstra–Lenstra–Lovász_lattice_basis_reduction_algorithm

[R715] (1,2)

Murray R. Bremner, “Lattice Basis Reduction: An Introduction to the LLL Algorithm and Its Applications”

lll_transform(delta=MPQ(3, 4))[source]#

Performs the Lenstra–Lenstra–Lovász (LLL) basis reduction algorithm and returns the reduced basis and transformation matrix.

Explanation

Parameters, algorithm and basis are the same as for lll() except that the return value is a tuple $$(B, T)$$ with $$B$$ the reduced basis and $$T$$ a transformation matrix. The original basis $$A$$ is transformed to $$B$$ with $$T*A == B$$. If only $$B$$ is needed then lll() should be used as it is a little faster.

Examples

>>> from sympy.polys.domains import ZZ, QQ
>>> from sympy.polys.matrices import DM
>>> X = DM([[1, 0, 0, 0, -20160],
...         [0, 1, 0, 0, 33768],
...         [0, 0, 1, 0, 39578],
...         [0, 0, 0, 1, 47757]], ZZ)
>>> B, T = X.lll_transform(delta=QQ(5, 6))
>>> T * X == B
True

lu()[source]#

Returns Lower and Upper decomposition of the DomainMatrix

Returns:

(L, U, exchange)

L, U are Lower and Upper decomposition of the DomainMatrix, exchange is the list of indices of rows exchanged in the decomposition.

Raises:

ValueError

If the domain of DomainMatrix not a Field

Examples

>>> from sympy import QQ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [QQ(1), QQ(-1)],
...    [QQ(2), QQ(-2)]], (2, 2), QQ)
>>> A.lu()
(DomainMatrix([[1, 0], [2, 1]], (2, 2), QQ), DomainMatrix([[1, -1], [0, 0]], (2, 2), QQ), [])

lu_solve(rhs)[source]#

Solver for DomainMatrix x in the A*x = B

Parameters:

rhs : DomainMatrix B

Returns:

DomainMatrix

x in A*x = B

Raises:

DMShapeError

If the DomainMatrix A and rhs have different number of rows

ValueError

If the domain of DomainMatrix A not a Field

Examples

>>> from sympy import QQ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [QQ(1), QQ(2)],
...    [QQ(3), QQ(4)]], (2, 2), QQ)
>>> B = DomainMatrix([
...    [QQ(1), QQ(1)],
...    [QQ(0), QQ(1)]], (2, 2), QQ)

>>> A.lu_solve(B)
DomainMatrix([[-2, -1], [3/2, 1]], (2, 2), QQ)


lu

matmul(B)[source]#

Performs matrix multiplication of two DomainMatrix matrices

Parameters:

A, B: DomainMatrix

to multiply

Returns:

DomainMatrix

DomainMatrix after multiplication

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [ZZ(1), ZZ(2)],
...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)
>>> B = DomainMatrix([
...    [ZZ(1), ZZ(1)],
...    [ZZ(0), ZZ(1)]], (2, 2), ZZ)

>>> A.matmul(B)
DomainMatrix([[1, 3], [3, 7]], (2, 2), ZZ)


mul(b)[source]#

Performs term by term multiplication for the second DomainMatrix w.r.t first DomainMatrix. Returns a DomainMatrix whose rows are list of DomainMatrix matrices created after term by term multiplication.

Parameters:

A, B: DomainMatrix

matrices to multiply term-wise

Returns:

DomainMatrix

DomainMatrix after term by term multiplication

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [ZZ(1), ZZ(2)],
...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)
>>> B = DomainMatrix([
...    [ZZ(1), ZZ(1)],
...    [ZZ(0), ZZ(1)]], (2, 2), ZZ)

>>> A.mul(B)
DomainMatrix([[DomainMatrix([[1, 1], [0, 1]], (2, 2), ZZ),
DomainMatrix([[2, 2], [0, 2]], (2, 2), ZZ)],
[DomainMatrix([[3, 3], [0, 3]], (2, 2), ZZ),
DomainMatrix([[4, 4], [0, 4]], (2, 2), ZZ)]], (2, 2), ZZ)

neg()[source]#

Returns the negative of DomainMatrix

Parameters:

A : Represents a DomainMatrix

Returns:

DomainMatrix

DomainMatrix after Negation

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [ZZ(1), ZZ(2)],
...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)

>>> A.neg()
DomainMatrix([[-1, -2], [-3, -4]], (2, 2), ZZ)

nullspace()[source]#

Returns the nullspace for the DomainMatrix

Returns:

DomainMatrix

The rows of this matrix form a basis for the nullspace.

Examples

>>> from sympy import QQ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [QQ(1), QQ(-1)],
...    [QQ(2), QQ(-2)]], (2, 2), QQ)
>>> A.nullspace()
DomainMatrix([[1, 1]], (1, 2), QQ)

classmethod ones(shape, domain)[source]#

Returns a DomainMatrix of 1s, of size shape, belonging to the specified domain

Examples

>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy import QQ
>>> DomainMatrix.ones((2,3), QQ)
DomainMatrix([[1, 1, 1], [1, 1, 1]], (2, 3), QQ)

pow(n)[source]#

Computes A**n

Parameters:

A : DomainMatrix

n : exponent for A

Returns:

DomainMatrix

DomainMatrix on computing A**n

Raises:

NotImplementedError

if n is negative.

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [ZZ(1), ZZ(1)],
...    [ZZ(0), ZZ(1)]], (2, 2), ZZ)

>>> A.pow(2)
DomainMatrix([[1, 2], [0, 1]], (2, 2), ZZ)

rowspace()[source]#

Returns the rowspace for the DomainMatrix

Returns:

DomainMatrix

The rows of this matrix form a basis for the rowspace.

Examples

>>> from sympy import QQ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [QQ(1), QQ(-1)],
...    [QQ(2), QQ(-2)]], (2, 2), QQ)
>>> A.rowspace()
DomainMatrix([[1, -1]], (1, 2), QQ)

rref()[source]#

Returns reduced-row echelon form and list of pivots for the DomainMatrix

Returns:

(DomainMatrix, list)

reduced-row echelon form and list of pivots for the DomainMatrix

Raises:

ValueError

If the domain of DomainMatrix not a Field

Examples

>>> from sympy import QQ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...     [QQ(2), QQ(-1), QQ(0)],
...     [QQ(-1), QQ(2), QQ(-1)],
...     [QQ(0), QQ(0), QQ(2)]], (3, 3), QQ)

>>> rref_matrix, rref_pivots = A.rref()
>>> rref_matrix
DomainMatrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]], (3, 3), QQ)
>>> rref_pivots
(0, 1, 2)


scc()[source]#

Compute the strongly connected components of a DomainMatrix

Returns:

List of lists of integers

Each list represents a strongly connected component.

Explanation

A square matrix can be considered as the adjacency matrix for a directed graph where the row and column indices are the vertices. In this graph if there is an edge from vertex i to vertex j if M[i, j] is nonzero. This routine computes the strongly connected components of that graph which are subsets of the rows and columns that are connected by some nonzero element of the matrix. The strongly connected components are useful because many operations such as the determinant can be computed by working with the submatrices corresponding to each component.

Examples

Find the strongly connected components of a matrix:

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> M = DomainMatrix([[ZZ(1), ZZ(0), ZZ(2)],
...                   [ZZ(0), ZZ(3), ZZ(0)],
...                   [ZZ(4), ZZ(6), ZZ(5)]], (3, 3), ZZ)
>>> M.scc()
[, [0, 2]]


Compute the determinant from the components:

>>> MM = M.to_Matrix()
>>> MM
Matrix([
[1, 0, 2],
[0, 3, 0],
[4, 6, 5]])
>>> MM[, ]
Matrix([])
>>> MM[[0, 2], [0, 2]]
Matrix([
[1, 2],
[4, 5]])
>>> MM.det()
-9
>>> MM[, ].det() * MM[[0, 2], [0, 2]].det()
-9


The components are given in reverse topological order and represent a permutation of the rows and columns that will bring the matrix into block lower-triangular form:

>>> MM[[1, 0, 2], [1, 0, 2]]
Matrix([
[3, 0, 0],
[0, 1, 2],
[6, 4, 5]])

sub(B)[source]#

Subtracts two DomainMatrix matrices of the same Domain

Parameters:

A, B: DomainMatrix

matrices to subtract

Returns:

DomainMatrix

DomainMatrix after Subtraction

Raises:

DMShapeError

If the dimensions of the two DomainMatrix are not equal

ValueError

If the domain of the two DomainMatrix are not same

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [ZZ(1), ZZ(2)],
...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)
>>> B = DomainMatrix([
...    [ZZ(4), ZZ(3)],
...    [ZZ(2), ZZ(1)]], (2, 2), ZZ)

>>> A.sub(B)
DomainMatrix([[-3, -1], [1, 3]], (2, 2), ZZ)


to_Matrix()[source]#

Convert DomainMatrix to Matrix

Returns:

Matrix

MutableDenseMatrix for the DomainMatrix

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [ZZ(1), ZZ(2)],
...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)

>>> A.to_Matrix()
Matrix([
[1, 2],
[3, 4]])

to_dense()[source]#

Return a dense DomainMatrix representation of self.

Examples

>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy import QQ
>>> A = DomainMatrix({0: {0: 1}, 1: {1: 2}}, (2, 2), QQ)
>>> A.rep
{0: {0: 1}, 1: {1: 2}}
>>> B = A.to_dense()
>>> B.rep
[[1, 0], [0, 2]]

to_field()[source]#

Returns a DomainMatrix with the appropriate field

Returns:

DomainMatrix

DomainMatrix with the appropriate field

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([
...    [ZZ(1), ZZ(2)],
...    [ZZ(3), ZZ(4)]], (2, 2), ZZ)

>>> A.to_field()
DomainMatrix([[1, 2], [3, 4]], (2, 2), QQ)

to_sparse()[source]#

Return a sparse DomainMatrix representation of self.

Examples

>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy import QQ
>>> A = DomainMatrix([[1, 0],[0, 2]], (2, 2), QQ)
>>> A.rep
[[1, 0], [0, 2]]
>>> B = A.to_sparse()
>>> B.rep
{0: {0: 1}, 1: {1: 2}}

transpose()[source]#

Matrix transpose of self

unify(*others, fmt=None)[source]#

Unifies the domains and the format of self and other matrices.

Parameters:

others : DomainMatrix

fmt: string ‘dense’, ‘sparse’ or None (default)

The preferred format to convert to if self and other are not already in the same format. If $$None$$ or not specified then no conversion if performed.

Returns:

Tuple[DomainMatrix]

Matrices with unified domain and format

Examples

Unify the domain of DomainMatrix that have different domains:

>>> from sympy import ZZ, QQ
>>> from sympy.polys.matrices import DomainMatrix
>>> A = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ)
>>> B = DomainMatrix([[QQ(1, 2), QQ(2)]], (1, 2), QQ)
>>> Aq, Bq = A.unify(B)
>>> Aq
DomainMatrix([[1, 2]], (1, 2), QQ)
>>> Bq
DomainMatrix([[1/2, 2]], (1, 2), QQ)


Unify the format (dense or sparse):

>>> A = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ)
>>> B = DomainMatrix({0:{0: ZZ(1)}}, (2, 2), ZZ)
>>> B.rep
{0: {0: 1}}

>>> A2, B2 = A.unify(B, fmt='dense')
>>> B2.rep
[[1, 0], [0, 0]]

vstack(*B)[source]#

Vertically stack the given matrices.

Parameters:

B: DomainMatrix

Matrices to stack vertically.

Returns:

DomainMatrix

DomainMatrix by stacking vertically.

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix

>>> A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
>>> B = DomainMatrix([[ZZ(5), ZZ(6)], [ZZ(7), ZZ(8)]], (2, 2), ZZ)
>>> A.vstack(B)
DomainMatrix([[1, 2], [3, 4], [5, 6], [7, 8]], (4, 2), ZZ)

>>> C = DomainMatrix([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ)
>>> A.vstack(B, C)
DomainMatrix([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]], (6, 2), ZZ)

classmethod zeros(shape, domain, *, fmt='sparse')[source]#

Returns a zero DomainMatrix of size shape, belonging to the specified domain

Examples

>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy import QQ
>>> DomainMatrix.zeros((2, 3), QQ)
DomainMatrix({}, (2, 3), QQ)

class sympy.polys.matrices.ddm.DDM(rowslist, shape, domain)[source]#

Dense matrix based on polys domain elements

This is a list subclass and is a wrapper for a list of lists that supports basic matrix arithmetic +, -, , *.

a + b

charpoly()[source]#

Coefficients of characteristic polynomial of a

det()[source]#

Determinant of a

hstack(*B)[source]#

Horizontally stacks DDM matrices.

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import DDM

>>> A = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
>>> B = DDM([[ZZ(5), ZZ(6)], [ZZ(7), ZZ(8)]], (2, 2), ZZ)
>>> A.hstack(B)
[[1, 2, 5, 6], [3, 4, 7, 8]]

>>> C = DDM([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ)
>>> A.hstack(B, C)
[[1, 2, 5, 6, 9, 10], [3, 4, 7, 8, 11, 12]]

inv()[source]#

Inverse of a

is_lower()[source]#

Says whether this matrix is lower-triangular. True can be returned even if the matrix is not square.

is_upper()[source]#

Says whether this matrix is upper-triangular. True can be returned even if the matrix is not square.

is_zero_matrix()[source]#

Says whether this matrix has all zero entries.

lu()[source]#

L, U decomposition of a

lu_solve(b)[source]#

x where a*x = b

matmul(b)[source]#

a @ b (matrix product)

neg()[source]#

-a

rref()[source]#

Reduced-row echelon form of a and list of pivots

scc()[source]#

Strongly connected components of a square matrix a.

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import DDM
>>> A = DDM([[ZZ(1), ZZ(0)], [ZZ(0), ZZ(1)]], (2, 2), ZZ)
>>> A.scc()
[, ]

sub(b)[source]#

a - b

vstack(*B)[source]#

Vertically stacks DDM matrices.

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import DDM

>>> A = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ)
>>> B = DDM([[ZZ(5), ZZ(6)], [ZZ(7), ZZ(8)]], (2, 2), ZZ)
>>> A.vstack(B)
[[1, 2], [3, 4], [5, 6], [7, 8]]

>>> C = DDM([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ)
>>> A.vstack(B, C)
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]]

class sympy.polys.matrices.sdm.SDM(elemsdict, shape, domain)[source]#

Sparse matrix based on polys domain elements

This is a dict subclass and is a wrapper for a dict of dicts that supports basic matrix arithmetic +, -, , *.

In order to create a new SDM, a dict of dicts mapping non-zero elements to their corresponding row and column in the matrix is needed.

We also need to specify the shape and Domain of our SDM object.

We declare a 2x2 SDM matrix belonging to QQ domain as shown below. The 2x2 Matrix in the example is

$\begin{split}A = \left[\begin{array}{ccc} 0 & \frac{1}{2} \\ 0 & 0 \end{array} \right]\end{split}$
>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> elemsdict = {0:{1:QQ(1, 2)}}
>>> A = SDM(elemsdict, (2, 2), QQ)
>>> A
{0: {1: 1/2}}


We can manipulate SDM the same way as a Matrix class

>>> from sympy import ZZ
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> B  = SDM({0:{0: ZZ(3)}, 1:{1:ZZ(4)}}, (2, 2), ZZ)
>>> A + B
{0: {0: 3, 1: 2}, 1: {0: 1, 1: 4}}


Multiplication

>>> A*B
{0: {1: 8}, 1: {0: 3}}
>>> A*ZZ(2)
{0: {1: 4}, 1: {0: 2}}


Adds two SDM matrices

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> B = SDM({0:{0: ZZ(3)}, 1:{1:ZZ(4)}}, (2, 2), ZZ)
{0: {0: 3, 1: 2}, 1: {0: 1, 1: 4}}

charpoly()[source]#

Returns the coefficients of the characteristic polynomial of the SDM matrix. These elements will be domain elements. The domain of the elements will be same as domain of the SDM.

Examples

>>> from sympy import QQ, Symbol
>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy.polys import Poly
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
>>> A.charpoly()
[1, -5, -2]


We can create a polynomial using the coefficients using Poly

>>> x = Symbol('x')
>>> p = Poly(A.charpoly(), x, domain=A.domain)
>>> p
Poly(x**2 - 5*x - 2, x, domain='QQ')

convert_to(K)[source]#

Converts the Domain of a SDM matrix to K

Examples

>>> from sympy import ZZ, QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> A.convert_to(QQ)
{0: {1: 2}, 1: {0: 1}}

copy()[source]#

Returns the copy of a SDM object

Examples

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> elemsdict = {0:{1:QQ(2)}, 1:{}}
>>> A = SDM(elemsdict, (2, 2), QQ)
>>> B = A.copy()
>>> B
{0: {1: 2}, 1: {}}

det()[source]#

Returns determinant of A

Examples

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
>>> A.det()
-2

classmethod eye(shape, domain)[source]#

Returns a identity SDM matrix of dimensions size x size, belonging to the specified domain

Examples

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> I = SDM.eye((2, 2), QQ)
>>> I
{0: {0: 1}, 1: {1: 1}}

classmethod from_ddm(ddm)[source]#

converts object of DDM to SDM

Examples

>>> from sympy.polys.matrices.ddm import DDM
>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> ddm = DDM( [[QQ(1, 2), 0], [0, QQ(3, 4)]], (2, 2), QQ)
>>> A = SDM.from_ddm(ddm)
>>> A
{0: {0: 1/2}, 1: {1: 3/4}}

classmethod from_list(ddm, shape, domain)[source]#
Parameters:

ddm:

list of lists containing domain elements

shape:

Dimensions of SDM matrix

domain:

Returns:

SDM containing elements of ddm

Examples

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> ddm = [[QQ(1, 2), QQ(0)], [QQ(0), QQ(3, 4)]]
>>> A = SDM.from_list(ddm, (2, 2), QQ)
>>> A
{0: {0: 1/2}, 1: {1: 3/4}}

hstack(*B)[source]#

Horizontally stacks SDM matrices.

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM

>>> A = SDM({0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3), 1: ZZ(4)}}, (2, 2), ZZ)
>>> B = SDM({0: {0: ZZ(5), 1: ZZ(6)}, 1: {0: ZZ(7), 1: ZZ(8)}}, (2, 2), ZZ)
>>> A.hstack(B)
{0: {0: 1, 1: 2, 2: 5, 3: 6}, 1: {0: 3, 1: 4, 2: 7, 3: 8}}

>>> C = SDM({0: {0: ZZ(9), 1: ZZ(10)}, 1: {0: ZZ(11), 1: ZZ(12)}}, (2, 2), ZZ)
>>> A.hstack(B, C)
{0: {0: 1, 1: 2, 2: 5, 3: 6, 4: 9, 5: 10}, 1: {0: 3, 1: 4, 2: 7, 3: 8, 4: 11, 5: 12}}

inv()[source]#

Returns inverse of a matrix A

Examples

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
>>> A.inv()
{0: {0: -2, 1: 1}, 1: {0: 3/2, 1: -1/2}}

is_lower()[source]#

Says whether this matrix is lower-triangular. True can be returned even if the matrix is not square.

is_upper()[source]#

Says whether this matrix is upper-triangular. True can be returned even if the matrix is not square.

is_zero_matrix()[source]#

Says whether this matrix has all zero entries.

lu()[source]#

Returns LU decomposition for a matrix A

Examples

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
>>> A.lu()
({0: {0: 1}, 1: {0: 3, 1: 1}}, {0: {0: 1, 1: 2}, 1: {1: -2}}, [])

lu_solve(b)[source]#

Uses LU decomposition to solve Ax = b,

Examples

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
>>> b = SDM({0:{0:QQ(1)}, 1:{0:QQ(2)}}, (2, 1), QQ)
>>> A.lu_solve(b)
{1: {0: 1/2}}

matmul(B)[source]#

Performs matrix multiplication of two SDM matrices

Parameters:

A, B: SDM to multiply

Returns:

SDM

SDM after multiplication

Raises:

DomainError

If domain of A does not match with that of B

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> B = SDM({0:{0:ZZ(2), 1:ZZ(3)}, 1:{0:ZZ(4)}}, (2, 2), ZZ)
>>> A.matmul(B)
{0: {0: 8}, 1: {0: 2, 1: 3}}

mul(b)[source]#

Multiplies each element of A with a scalar b

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> A.mul(ZZ(3))
{0: {1: 6}, 1: {0: 3}}

neg()[source]#

Returns the negative of a SDM matrix

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> A.neg()
{0: {1: -2}, 1: {0: -1}}

classmethod new(sdm, shape, domain)[source]#
Parameters:

sdm: A dict of dicts for non-zero elements in SDM

shape: tuple representing dimension of SDM

domain: Represents :py:class:~.Domain of SDM

Returns:

An SDM object

Examples

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> elemsdict = {0:{1: QQ(2)}}
>>> A = SDM.new(elemsdict, (2, 2), QQ)
>>> A
{0: {1: 2}}

nullspace()[source]#

Returns nullspace for a SDM matrix A

Examples

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0: QQ(2), 1: QQ(4)}}, (2, 2), QQ)
>>> A.nullspace()
({0: {0: -2, 1: 1}}, )

rref()[source]#

Returns reduced-row echelon form and list of pivots for the SDM

Examples

>>> from sympy import QQ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(2), 1:QQ(4)}}, (2, 2), QQ)
>>> A.rref()
({0: {0: 1, 1: 2}}, )

scc()[source]#

Strongly connected components of a square matrix A.

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{0: ZZ(2)}, 1:{1:ZZ(1)}}, (2, 2), ZZ)
>>> A.scc()
[, ]

sub(B)[source]#

Subtracts two SDM matrices

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM
>>> A = SDM({0:{1: ZZ(2)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
>>> B  = SDM({0:{0: ZZ(3)}, 1:{1:ZZ(4)}}, (2, 2), ZZ)
>>> A.sub(B)
{0: {0: -3, 1: 2}, 1: {0: 1, 1: -4}}

to_ddm()[source]#

Convert a SDM object to a DDM object

Examples

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM({0:{1:QQ(2)}, 1:{}}, (2, 2), QQ)
>>> A.to_ddm()
[[0, 2], [0, 0]]

to_list()[source]#

Converts a SDM object to a list

Examples

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> elemsdict = {0:{1:QQ(2)}, 1:{}}
>>> A = SDM(elemsdict, (2, 2), QQ)
>>> A.to_list()
[[0, 2], [0, 0]]

transpose()[source]#

Returns the transpose of a SDM matrix

Examples

>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM({0:{1:QQ(2)}, 1:{}}, (2, 2), QQ)
>>> A.transpose()
{1: {0: 2}}

vstack(*B)[source]#

Vertically stacks SDM matrices.

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices.sdm import SDM

>>> A = SDM({0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3), 1: ZZ(4)}}, (2, 2), ZZ)
>>> B = SDM({0: {0: ZZ(5), 1: ZZ(6)}, 1: {0: ZZ(7), 1: ZZ(8)}}, (2, 2), ZZ)
>>> A.vstack(B)
{0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}, 2: {0: 5, 1: 6}, 3: {0: 7, 1: 8}}

>>> C = SDM({0: {0: ZZ(9), 1: ZZ(10)}, 1: {0: ZZ(11), 1: ZZ(12)}}, (2, 2), ZZ)
>>> A.vstack(B, C)
{0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}, 2: {0: 5, 1: 6}, 3: {0: 7, 1: 8}, 4: {0: 9, 1: 10}, 5: {0: 11, 1: 12}}

classmethod zeros(shape, domain)[source]#

Returns a SDM of size shape, belonging to the specified domain

In the example below we declare a matrix A where,

$\begin{split}A := \left[\begin{array}{ccc} 0 & 0 & 0 \\ 0 & 0 & 0 \end{array} \right]\end{split}$
>>> from sympy.polys.matrices.sdm import SDM
>>> from sympy import QQ
>>> A = SDM.zeros((2, 3), QQ)
>>> A
{}

sympy.polys.matrices.normalforms.smith_normal_form(m)[source]#

Return the Smith Normal Form of a matrix $$m$$ over the ring $$domain$$. This will only work if the ring is a principal ideal domain.

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy.polys.matrices.normalforms import smith_normal_form
>>> m = DomainMatrix([[ZZ(12), ZZ(6), ZZ(4)],
...                   [ZZ(3), ZZ(9), ZZ(6)],
...                   [ZZ(2), ZZ(16), ZZ(14)]], (3, 3), ZZ)
>>> print(smith_normal_form(m).to_Matrix())
Matrix([[1, 0, 0], [0, 10, 0], [0, 0, -30]])

sympy.polys.matrices.normalforms.hermite_normal_form(A, *, D=None, check_rank=False)[source]#

Compute the Hermite Normal Form of DomainMatrix A over ZZ.

Parameters:

A : $$m \times n$$ DomainMatrix over ZZ.

D : ZZ, optional

Let $$W$$ be the HNF of A. If known in advance, a positive integer D being any multiple of $$\det(W)$$ may be provided. In this case, if A also has rank $$m$$, then we may use an alternative algorithm that works mod D in order to prevent coefficient explosion.

check_rank : boolean, optional (default=False)

The basic assumption is that, if you pass a value for D, then you already believe that A has rank $$m$$, so we do not waste time checking it for you. If you do want this to be checked (and the ordinary, non-modulo D algorithm to be used if the check fails), then set check_rank to True.

Returns:

DomainMatrix

The HNF of matrix A.

Raises:

DMDomainError

If the domain of the matrix is not ZZ, or if D is given but is not in ZZ.

DMShapeError

If the mod D algorithm is used but the matrix has more rows than columns.

Examples

>>> from sympy import ZZ
>>> from sympy.polys.matrices import DomainMatrix
>>> from sympy.polys.matrices.normalforms import hermite_normal_form
>>> m = DomainMatrix([[ZZ(12), ZZ(6), ZZ(4)],
...                   [ZZ(3), ZZ(9), ZZ(6)],
...                   [ZZ(2), ZZ(16), ZZ(14)]], (3, 3), ZZ)
>>> print(hermite_normal_form(m).to_Matrix())
Matrix([[10, 0, 2], [0, 15, 3], [0, 0, 2]])


References

[R716]

Cohen, H. A Course in Computational Algebraic Number Theory. (See Algorithms 2.4.5 and 2.4.8.)