To make a matrix in Diofant, use the ~diofant.matrices.Matrix
object. A matrix is constructed by providing a list of row vectors that make up the matrix.
>>> Matrix([[1, -1], [3, 4], [0, 2]]) ⎡1 -1⎤ ⎢ ⎥ ⎢3 4 ⎥ ⎢ ⎥ ⎣0 2 ⎦
A list of elements is considered to be a column vector.
>>> Matrix([1, 2, 3]) ⎡1⎤ ⎢ ⎥ ⎢2⎥ ⎢ ⎥ ⎣3⎦
One important thing to note about Diofant matrices is that, unlike every other object in Diofant, they are mutable. This means that they can be modified in place, as we will see below. Use ~diofant.matrices.immutable.ImmutableMatrix
in places that require immutability, such as inside other Diofant expressions or as keys to dictionaries.
Diofant matrices support subscription of matrix elements with pair of integers or slice
instances. In last case, new ~diofant.matrices.Matrix
instances will be returned.
>>> M = Matrix([[1, 2, 3], [4, 5, 6]]) >>> M[0, 1] 2 >>> M[1, 1] 5 >>> M[:, 1] ⎡2⎤ ⎢ ⎥ ⎣5⎦ >>> M[1, :-1] [4 5] >>> M[0, :] [1 2 3] >>> M[:, -1] ⎡3⎤ ⎢ ⎥ ⎣6⎦
It's possible to modify matrix elements.
>>> M[0, 0] = 0 >>> M ⎡0 2 3⎤ ⎢ ⎥ ⎣4 5 6⎦ >>> M[1, 1:] = Matrix([[0, 0]]) >>> M ⎡0 2 3⎤ ⎢ ⎥ ⎣4 0 0⎦
To get the shape of a matrix use ~diofant.matrices.matrices.MatrixBase.shape
property
>>> M = Matrix([[1, 2, 3], [-2, 0, 4]]) >>> M ⎡1 2 3⎤ ⎢ ⎥ ⎣-2 0 4⎦ >>> M.shape (2, 3)
To delete a row or column, use del
>>> del M[:, 0] >>> M ⎡2 3⎤ ⎢ ⎥ ⎣0 4⎦ >>> del M[1, :] >>> M [2 3]
To insert rows or columns, use methods ~diofant.matrices.matrices.MatrixBase.row_insert
or ~diofant.matrices.matrices.MatrixBase.col_insert
.
>>> M [2 3] >>> M = M.row_insert(1, Matrix([[0, 4]])) >>> M ⎡2 3⎤ ⎢ ⎥ ⎣0 4⎦ >>> M = M.col_insert(0, Matrix([1, -2])) >>> M ⎡1 2 3⎤ ⎢ ⎥ ⎣-2 0 4⎦
Note
You can see, that these methods will modify the Matrix in place. In general, as a rule, such methods will return None
.
To swap two given rows or columns, use methods ~diofant.matrices.dense.MutableDenseMatrix.row_swap
or ~diofant.matrices.dense.MutableDenseMatrix.col_swap
.
>>> M.row_swap(0, 1) >>> M ⎡-2 0 4⎤ ⎢ ⎥ ⎣1 2 3⎦ >>> M.col_swap(1, 2) >>> M ⎡-2 4 0⎤ ⎢ ⎥ ⎣1 3 2⎦
To take the transpose of a Matrix, use ~diofant.matrices.matrices.MatrixBase.T
property.
>>> M.T ⎡-2 1⎤ ⎢ ⎥ ⎢4 3⎥ ⎢ ⎥ ⎣0 2⎦
Simple operations like addition and multiplication are done just by using +
, *
, and **
. To find the inverse of a matrix, just raise it to the -1
power.
>>> M, N = Matrix([[1, 3], [-2, 3]]), Matrix([[0, 3], [0, 7]]) >>> M + N ⎡1 6 ⎤ ⎢ ⎥ ⎣-2 10⎦ >>> M*N ⎡0 24⎤ ⎢ ⎥ ⎣0 15⎦ >>> 3*M ⎡3 9⎤ ⎢ ⎥ ⎣-6 9⎦ >>> M*2 ⎡-5 12⎤ ⎢ ⎥ ⎣-8 3 ⎦ >>> M-1 ⎡1/3 -1/3⎤ ⎢ ⎥ ⎣2/9 1/9 ⎦ >>> N*-1 Traceback (most recent call last): ... ValueError: Matrix det == 0; not invertible.
Several constructors exist for creating common matrices. To create an identity matrix, use ~diofant.matrices.dense.eye
function.
>>> eye(3) ⎡1 0 0⎤ ⎢ ⎥ ⎢0 1 0⎥ ⎢ ⎥ ⎣0 0 1⎦ >>> eye(4) ⎡1 0 0 0⎤ ⎢ ⎥ ⎢0 1 0 0⎥ ⎢ ⎥ ⎢0 0 1 0⎥ ⎢ ⎥ ⎣0 0 0 1⎦
To create a matrix of all zeros, use ~diofant.matrices.dense.zeros
function.
>>> zeros(2, 3) ⎡0 0 0⎤ ⎢ ⎥ ⎣0 0 0⎦
Similarly, function ~diofant.matrices.dense.ones
creates a matrix of ones.
>>> ones(3, 2) ⎡1 1⎤ ⎢ ⎥ ⎢1 1⎥ ⎢ ⎥ ⎣1 1⎦
To create diagonal matrices, use function ~diofant.matrices.dense.diag
. Its arguments can be either numbers or matrices. A number is interpreted as a 1times 1 matrix. The matrices are stacked diagonally.
>>> diag(1, 2, 3) ⎡1 0 0⎤ ⎢ ⎥ ⎢0 2 0⎥ ⎢ ⎥ ⎣0 0 3⎦ >>> diag(-1, ones(2, 2), Matrix([5, 7, 5])) ⎡-1 0 0 0⎤ ⎢ ⎥ ⎢0 1 1 0⎥ ⎢ ⎥ ⎢0 1 1 0⎥ ⎢ ⎥ ⎢0 0 0 5⎥ ⎢ ⎥ ⎢0 0 0 7⎥ ⎢ ⎥ ⎣0 0 0 5⎦
To compute the determinant of a matrix, use ~diofant.matrices.matrices.MatrixBase.det
method.
>>> Matrix([[1, 0, 1], [2, -1, 3], [4, 3, 2]]) ⎡1 0 1⎤ ⎢ ⎥ ⎢2 -1 3⎥ ⎢ ⎥ ⎣4 3 2⎦ >>> _.det() -1
To put a matrix into reduced row echelon form, use method ~diofant.matrices.matrices.MatrixBase.rref
. It returns a tuple of two elements. The first is the reduced row echelon form, and the second is a list of indices of the pivot columns.
>>> Matrix([[1, 0, 1, 3], [2, 3, 4, 7], [-1, -3, -3, -4]]) ⎡1 0 1 3 ⎤ ⎢ ⎥ ⎢2 3 4 7 ⎥ ⎢ ⎥ ⎣-1 -3 -3 -4⎦ >>> _.rref() ⎛⎡1 0 1 3 ⎤ ⎞ ⎜⎢ ⎥ ⎟ ⎜⎢0 1 2/3 1/3⎥, [0, 1]⎟ ⎜⎢ ⎥ ⎟ ⎝⎣0 0 0 0 ⎦ ⎠
To find the nullspace of a matrix, use method ~diofant.matrices.matrices.MatrixBase.nullspace
. It returns a list of column vectors that span the nullspace of the matrix.
>>> Matrix([[1, 2, 3, 0, 0], [4, 10, 0, 0, 1]]) ⎡1 2 3 0 0⎤ ⎢ ⎥ ⎣4 10 0 0 1⎦ >>> _.nullspace() ⎡⎡-15⎤ ⎡0⎤ ⎡ 1 ⎤⎤ ⎢⎢ ⎥ ⎢ ⎥ ⎢ ⎥⎥ ⎢⎢ 6 ⎥ ⎢0⎥ ⎢-1/2⎥⎥ ⎢⎢ ⎥ ⎢ ⎥ ⎢ ⎥⎥ ⎢⎢ 1 ⎥, ⎢0⎥, ⎢ 0 ⎥⎥ ⎢⎢ ⎥ ⎢ ⎥ ⎢ ⎥⎥ ⎢⎢ 0 ⎥ ⎢1⎥ ⎢ 0 ⎥⎥ ⎢⎢ ⎥ ⎢ ⎥ ⎢ ⎥⎥ ⎣⎣ 0 ⎦ ⎣0⎦ ⎣ 1 ⎦⎦
To find the eigenvalues of a matrix, use method ~diofant.matrices.matrices.MatrixBase.eigenvals
. It returns a dictionary of roots including its multiplicity (similar to the output of ~diofant.polys.polyroots.roots
function).
>>> M = Matrix([[3, -2, 4, -2], [5, +3, -3, -2], ... [5, -2, 2, -2], [5, -2, -3, +3]]) >>> M ⎡3 -2 4 -2⎤ ⎢ ⎥ ⎢5 3 -3 -2⎥ ⎢ ⎥ ⎢5 -2 2 -2⎥ ⎢ ⎥ ⎣5 -2 -3 3 ⎦ >>> M.eigenvals() {-2: 1, 3: 1, 5: 2}
This means that M
has eigenvalues -2, 3, and 5, and that the eigenvalues -2 and 3 have algebraic multiplicity 1 and that the eigenvalue 5 has algebraic multiplicity 2.
Matrices can have symbolic elements.
>>> Matrix([[x, x + y], [y, x]]) ⎡x x + y⎤ ⎢ ⎥ ⎣y x ⎦ >>> _.eigenvals() ⎧ ___________ ___________ ⎫ ⎨x - ╲╱ y⋅(x + y) : 1, x + ╲╱ y⋅(x + y) : 1⎬ ⎩ ⎭
To find the eigenvectors of a matrix, use method ~diofant.matrices.matrices.MatrixBase.eigenvects
.
>>> M.eigenvects() ⎡⎛ ⎡⎡0⎤⎤⎞ ⎛ ⎡⎡1⎤⎤⎞ ⎛ ⎡⎡1⎤ ⎡0 ⎤⎤⎞⎤ ⎢⎜ ⎢⎢ ⎥⎥⎟ ⎜ ⎢⎢ ⎥⎥⎟ ⎜ ⎢⎢ ⎥ ⎢ ⎥⎥⎟⎥ ⎢⎜ ⎢⎢1⎥⎥⎟ ⎜ ⎢⎢1⎥⎥⎟ ⎜ ⎢⎢1⎥ ⎢-1⎥⎥⎟⎥ ⎢⎜-2, 1, ⎢⎢ ⎥⎥⎟, ⎜3, 1, ⎢⎢ ⎥⎥⎟, ⎜5, 2, ⎢⎢ ⎥, ⎢ ⎥⎥⎟⎥ ⎢⎜ ⎢⎢1⎥⎥⎟ ⎜ ⎢⎢1⎥⎥⎟ ⎜ ⎢⎢1⎥ ⎢0 ⎥⎥⎟⎥ ⎢⎜ ⎢⎢ ⎥⎥⎟ ⎜ ⎢⎢ ⎥⎥⎟ ⎜ ⎢⎢ ⎥ ⎢ ⎥⎥⎟⎥ ⎣⎝ ⎣⎣1⎦⎦⎠ ⎝ ⎣⎣1⎦⎦⎠ ⎝ ⎣⎣0⎦ ⎣1 ⎦⎦⎠⎦
This shows us that, for example, the eigenvalue 5 also has geometric multiplicity 2, because it has two eigenvectors. Because the algebraic and geometric multiplicities are the same for all the eigenvalues, M
is diagonalizable.
To diagonalize a matrix, use method ~diofant.matrices.matrices.MatrixBase.diagonalize
. It returns a tuple (P, D), where D is diagonal and M = PDP^{-1}.
>>> M.diagonalize() ⎛⎡0 1 1 0 ⎤ ⎡-2 0 0 0⎤⎞ ⎜⎢ ⎥ ⎢ ⎥⎟ ⎜⎢1 1 1 -1⎥ ⎢0 3 0 0⎥⎟ ⎜⎢ ⎥, ⎢ ⎥⎟ ⎜⎢1 1 1 0 ⎥ ⎢0 0 5 0⎥⎟ ⎜⎢ ⎥ ⎢ ⎥⎟ ⎝⎣1 1 0 1 ⎦ ⎣0 0 0 5⎦⎠ >>> _[0]_[1]_[0]**-1 == M True
If all you want is the characteristic polynomial, use method ~diofant.matrices.matrices.MatrixBase.charpoly
. This is more efficient than ~diofant.matrices.matrices.MatrixBase.eigenvals
method, because sometimes symbolic roots can be expensive to calculate.
>>> M.charpoly(x) PurePoly(x*4 - 11x*3 + 29x*2 + 35x - 150, x, domain='ZZ') >>> factor(_) 2 (x - 5) ⋅(x - 3)⋅(x + 2)
To compute Jordan canonical form J for matrix M and its similarity transformation P (i.e. such that J = P M P^{-1}), use method ~diofant.matrices.matrices.MatrixBase.jordan_form
.
>>> Matrix([[-2, 4], [1, 3]]).jordan_form() ⎛⎡ ____ ⎤ ⎡ -4 -4 ⎤⎞ ⎜⎢1 ╲╱ 41 ⎥ ⎢──────────── ────────────⎥⎟ ⎜⎢─ + ────── 0 ⎥ ⎢ ____ ____⎥⎟ ⎜⎢2 2 ⎥ ⎢ ╲╱ 41 5 5 ╲╱ 41 ⎥⎟ ⎜⎢ ⎥, ⎢- ────── - ─ - ─ + ──────⎥⎟ ⎜⎢ ____ ⎥ ⎢ 2 2 2 2 ⎥⎟ ⎜⎢ ╲╱ 41 1⎥ ⎢ ⎥⎟ ⎜⎢ 0 - ────── + ─⎥ ⎣ 1 1 ⎦⎟ ⎝⎣ 2 2⎦ ⎠