Skip to main content

Linear Algebra with SageMath Learn math with open-source software

Section 2.2 Matrices

In this section, we will see how to define matrices, and perform basic operations on them. A matrix is an \(m \times n\) rectangular array of numbers:
\begin{equation*} \begin{bmatrix} a_{11} & a_{12} & \dots & a_{1n} \\ a_{21} & a_{22} & \dots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \dots & a_{mn} \end{bmatrix} \end{equation*}
where \(m\) is the number of rows and \(n\) is the number of columns. Each entry \(a_{ij}, i=1\dots m, j=1\dots n,\) corresponds to the value at the intersection of the \(i\)-th row and \(j\)-th column.
Just like vectors, Sage does come with built-in support for matrices. There are many ways to define a matrix in Sage using the command matrix, passing for instance each of the rows of the matrix as a list of numbers.
Or as a list of vectors.
Alternatively, we can create a matrix by passing the entries as a list, and the dimensions as arguments to the matrix command. Here is an example of a \(2 \times 3\) matrix.
Note that in Sage, you can create a list consisting of repeated copies of the same element using the repetition operator *. For example, [1] * 6 produces a list with six 1s, which is convenient when filling a matrix with identical entries like in the following example.
We do not need to specify both dimensions of a matrix. Sage can infer the missing dimension from the number of entries in the list. Here is an example of a \(5 \times 20\) matrix containing the first \(100\) integers, where only the number of rows is specified.
The entries of the matrix can also be defined programmatically a list comprehension.
Sage also allows for constructing a larger matrix by combining smaller submatrices using the block_matrix() function (or matrix.block()). Submatrices can be arranged in rows and columns to form a single, larger matrix. Each row is entered as a list.
Matrices of different dimensions can be used with the command block_matrix as long as the dimensions of the submatrices allow for their concatenation. In the following example, we create a \(5 \times 5\) matrix from four submatrices of different dimensions.
We will use the following matrix \(M\) to show how Sage can identify its different parts.
The individual entries of a matrix can be accessed using the row and column indices. Since indices in Sage start at 0, to retrieve the entry \(a_{ij}\) in a matrix \(M\text{,}\) we type M[i-1, j-1]. Here is, for instance, how we can retrieve the entry at the second row and third column of the matrix \(M\text{.}\)
Sage provides dedicated methods to retrieve all rows of the matrix, or all its columns. It also support the retrieval of the diagonal elements of a matrix, or extracting a specific row or a specific column of a given matrix.
The rows method returns all rows of the matrix (as a list of tuples).
In the same way, the columns method returns all the columns of the matrix (as a list of tuples).
The M.row(i-1) returns the \(i\)-th row of the matrix.
The M.column(j-1) returns the \(j\)-th column of the matrix.
The M.diagonal() returns the main diagonal of the matrix.
Similarly, Sage offers more methods to help us iterate over the rows or the columns of a matrix. For instance, the method nrows() returns the number of rows of a matrix.
Sage method ncols() returns the number of rows of the matrix.
Alternatively, the method dimensions returns the dimension of the matrix as a pair (nrows, ncols).
Sage defines the method is_square() that returns True if the matrix is square. In this case, it returns False because matrix \(M\) is a \(2 \times 3\) matrix.
To extract a submatrix from a matrix given the range of rows and columns to include, Sage command matrix_from_rows_and_columns() takes two lists: the first for row indices, and the second for column indices as in the following example.
The resulting submatrix from the previous command contains the entries at the intersection of the indexed rows (i.e. first and second rows) and the indexed columns (i.e. the second and third columns).
Note that the order of the indices in the lists matters and will affect the order of the rows and columns in the resulting submatrix. In the following example, the order of the columns in the resulting submatrix is different from the previous example.
An alternative, and perhaps more straightforward way to achieve the same result is to use Python-like slicing and explicitly listing the range of interest as in the following example.
The syntax A[i:j, k:l] extracts the submatrix from rows \(i\) to \(j-1\) and columns \(k\) to \(l-1\) (lower bound inclusive but not the upper bound of the range).
Sage also offers the method submatrix() that takes the starting row and column indices, and the number of rows and columns to include in the resulting submatrix. The following example shows how to extract a submatrix starting from the first row and first column, and including two rows and two columns.
Another indirect way to extract a submatrix is to use the methods delete_rows() and delete_columns(). For instance, to extract the same top-left \(2 \times 2\) submatrix of the previous example, we can use the following command.
Note that a matrix with a single list of values creates a vector-like object, but it is NOT a vector. Here is a vector in Sage.
Compare that to this single-row matrix. Observe the square brackets in matrices in lieu of the parenthesis.
Type assertion is a useful tool to check if two objects are identical and are of the same type. For instance, comparing the types of \(v\) and \(m\) yields False because they are NOT of the same type.
Just like vectors, matrices in Sage can also be created in different Base Rings, inferred from the datatype passed to the matrix command, or explicitly when instantiating the matrix.
The method base_ring returns the base ring of the matrix.
Once again, if the ring is omitted, Sage will simply infer the ring from the datatype of the matrix entries. Sage matrices supports the same rings as vectors (\(ZZ, QQ, RR, CC\)).