Matrices
To make a matrix in Diofant, use the
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
ImmutableMatrix
in places that
require immutability, such as inside other Diofant expressions or as
keys to dictionaries.
Indexing
Diofant matrices support subscription of matrix elements with pair of
integers or slice
instances. In last case, new
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⎦
Reshape and Rearrange
To get the shape of a matrix use
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
row_insert()
or
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
row_swap()
or
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
T
property.
>>> M.T
⎡-2 1⎤
⎢ ⎥
⎢4 3⎥
⎢ ⎥
⎣0 2⎦
Algebraic Operations
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.
Special Matrices
Several constructors exist for creating common matrices. To create an
identity matrix, use 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
zeros()
function.
>>> zeros(2, 3)
⎡0 0 0⎤
⎢ ⎥
⎣0 0 0⎦
Similarly, function ones()
creates a
matrix of ones.
>>> ones(3, 2)
⎡1 1⎤
⎢ ⎥
⎢1 1⎥
⎢ ⎥
⎣1 1⎦
To create diagonal matrices, use function
diag()
. Its arguments can be either
numbers or matrices. A number is interpreted as a \(1\times 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⎦
Advanced Methods
To compute the determinant of a matrix, use
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
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
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
eigenvals()
. It returns a
dictionary of roots including its multiplicity (similar to the output
of 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
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
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
charpoly()
. This is more
efficient than eigenvals()
method, because sometimes symbolic roots can be expensive to
calculate.
>>> M.charpoly(x)
PurePoly(x**4 - 11*x**3 + 29*x**2 + 35*x - 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
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⎦ ⎠