"Matrix" is the Latin word for womb. The origin of mathematical matrices has a long history. The term "matrix" in combinatorics was introduced in 1850 by the British mathematician James Joseph Sylvester (1814--1897), who also coined many mathematical terms or used them in "new or unusual ways" mathematically, such as graphs, discriminant, annihilators, canonical forms, minor, nullity, and many others.
Constructing Matrices
Sage offers several ways for constructing matrices.
Matrices are fundamental objects in linear algebra and in Sage, so
there are a variety of ways to construct a matrix in Sage.
Generally, you need to specify what types of entries the matrix
contains (more on that to come), the number of rows and columns,
and the entries themselves. First, let’s dissect an example:
Here QQ
is the set of all rational numbers (fractions with an integer numerator and
denominator),
2
is the number of rows,
3
is the number of columns. Sage understands
a list of items as delimited by brackets (
[,]) and the items in the list can again be lists themselves. So
[[1, 2, 3], [4, 5, 6]]
is a list of lists, and in this context
the inner lists are rows of the matrix.
There are various shortcuts you can employ when creating a matrix. For example,
Sage is able to infer the size of the matrix from the lists of entries.
Now, let's enter a matrix.
Or you can specify how many rows the matrix will have and provide one big grand
list of entries, which will get chopped up, row by row, if you prefer.
Matrices with symbolic entries:
The function matrix() or Matrix() is used to do this. For now the
first argument to the function should be "QQ", this means that the matrix will
contain either integers or rational numbers (fractions).
sage: C.parent() Full MatrixSpace of 2 by 3 dense matrices over Integer Ring sage: A = matrix(2, 3, [[1, cos(3.14), 3], [4, 5, 6]]) sage: A.parent() Full MatrixSpace of 2 by 3 dense matrices over Real Field with 53 bits of precision
Part: Part {2,2} of \( \begin{pmatrix} 1&2&3 \\ -1&3&0 \end{pmatrix}
\) does not exist.
There are two ways to avoid frozen matrices (from TraditionalForm or MatrixForm) that are kept by Mathematica in traditional form as a single unit (or image). The motivation for this is so that the matrix operations can be performed on the matrices we define. The first option is to define a matrix on one line of code and then display it in a convenient form on a completely separate line of code.
A ={{1,2,3},{-1,3,0}}
A // MatrixForm
Another option is to use one line for all code (matrix definition and use of MatrixForm or TraditionalForm) but define the entire matrix within parentheses.
There are several commands with which you can define diagonal
matrices. The basic command is of
course DiagonalMatrix[L]. When you have a list of
values, L, you can build a square diagonal matrix
with entries from L along its diagonal. All entries
outside the main diagonal are zeroes. Other "diagonals" of a rectangular or square matrix extend from upper left to lower right; the main diagonal starts in the upper left-hand corner.
The command Diagonal[M] gives the list of elements on the leading diagonal of matrix M.
The command Diagonal[M,k] gives the elements on the k-th
diagonal of matrix M.
Recall that using MatrixForm for the direct definition of matrix A will prohibit any operations with elements of the matrix. Therefore, we first define matrix A and only after that we visualize it with MatrixForm or TraditionalForm. For instance, you can determine a particular element of the matrix
As you see, Mathematica provides the main diagonal, starting at the upper left corner. Other diagonal elements are obtained by including a particular shift from the main diagonal:
Diagonal[A,1]
{2, -3, 34, 45}
Diagonal[A,2]
{3, -4, 35}
To shift down from the main diagonal, just type a negative integer:
Diagonal[A,-1]
{-1, 32, 43}
Mathematica allows us not only to check diagonal elements but also to construct the diagonal matrix. The following two examples are self-explanatory.
These introductory commands are very easy to use. The first two
command lines define the matrices, A
and M that we will be analyzing. The only thing
that is important to understand for this is that to create a matrix
with multiple rows, you need to separate each row and surround it
with {}, as shown in the example above.
The Dimensions command tells you the dimensions for each matrix.
Dimensions[A]
{2, 3} (* 2 is number of rows, 3 is number of columns *)
The commands A[[2,1]] and A[[1]] are used to have Mathematica output certain matrix elements.
A[[2,1]]
(*
entry in second row, first column *)
-1
A[[1]] (* first row of the matrix A *)
{1,2,3}
Now we define another matrix whose entries are functions:
The command
MatrixQ[matrix]
gives True if it is a matrix, otherwise -- False
MatrixQ[A] (* to check whether it is list of lists *)
True
Two m×n matrices \( {\bf A} = \left[ a_{i,j} \right] \) and \( {\bf B} = \left[ b_{i,j} \right] \) having the same dimensions can be added or subtracted
\[
{\bf A} \pm {\bf B} = \left[ a_{i,j} \pm b_{i,j} \right] , \qquad i = 1,2, \ldots , m , \quad j=1,2,\ldots , n ,
\]
by adding/subtracting the corresponding entries.
Mathematica uses the standard commands "+" and "-" to add or subtract two matrices of the same dimensions. Remember that you cannot add or subtract matrices of distinct dimensions, and Mathematica will not allow you to perform such operations. However, it is possible to enlarge the lowest size by appending zeroes and then add/subtract the matrices.
Transposition of Matrices
There is a special operation that transfers columns into rows and vice versa: it is called transposition. The transpose of a matrix was introduced in 1858
by the British mathematician Arthur Cayley (1821--1895). The transpose of a m × n matrix A is an n × m matrix
AT (also denoted as \( {\bf A}' \) or
\( {\bf A}^t \) ) created by any one of the following equivalent actions:
reflects A over its main diagonal (which runs from top-left to bottom-right);
writes the rows of A as the columns of \( {\bf A}^{\mathrm T} \)
Formally, the i-th row, j-th column element of AT is the j-th row, i-th column element of A:
A square matrix whose transpose is equal to its negative is called a skew-symmetric matrix; that is, A is skew-symmetric if
\[
{\bf A}^{\mathrm T} = - {\bf A} .
\]
Complex entries
Let A be a m × n matrix with real or complex entries (they could be numbers or functions or other
entities). Its complex conjugate, denoted by \( \overline{\bf A} , \) is again a m × n matrix,
which is formed by taking the complex conjugate of each entry. Mathematica has a specific command to calculate complex conjugate:
If we take a transpose of the complex conjugate of m
× n matrix A, we get the n
× m matrix,
called the adjoint matrix ofA,
which is denoted by
\( {\bf A}^{\ast} = \overline{{\bf A}^{\mathrm T}} = \left( \overline{\bf A} \right)^{\mathrm T} . \)
A square matrix A is called symmetric if \( {\bf A} = {\bf A}^{\mathrm T} . \) A square matrix A is called self-adjoint (or Hermitian) if it coincides with its transposed and complex conjugate:
where the conjugate transpose is denoted A* or AH, AT is the transpose matrix, and \( \overline{z} = a - {\bf j}b \) is complex conjugate of z = 𝑎 + jb.
An example of self-adjoint matrix gives the Pauli matrix, named after the Austrian (and later American / Swiss) physicist Wolfgang Ernst Pauli (1900-1958):
Adding an arbitrary real-valued 2×2 matrix to the Pauli matrix, we obtain another self-adjoint matrix.
A square complex matrix whose transpose is equal to the matrix with every entry replaced by its
complex conjugate (denoted here with an overline) is called a self-adjoint matrix or a
Hermitian matrix (equivalent to the matrix being equal to its
conjugate transpose); that is, A is self-adjoint or Hermitian if \( {\bf A} = {\bf A}^{\ast} . \)
Therefore, \( {\bf A} \ne {\bf A}^{\ast} , \) and matrix A is not self-adjoint.
Building zero or diagonal matrices
Mathematica makes no distinction between vectors
and matrices. For example, all n element column vectors are treated as
n×1 matrices. This means that we can create a composition of row vectors in a column vector or vice versa.
If you wish to avoid building your matrix from curly brackets, Mathematica allows you to specify the size of a matrix through its toolbar. Navigate to Insert on the toolbar. Then click Table/Matrix -> New. A window will now appear allowing you to specify the size of your matrix. Under Make select Matrix(List of lists). Then specify the number of rows and columns you wish to input and click ok. Your specified matrix will now appear on your notebook for you to input information.
Suppose we need to build a zero matrix or the identity matrix:
DiagonalMatrix[list] gives a matrix with the elements of the
list on the leading diagonal, and 0 elsewhere. Therefore, the identity matrix
of dimensions \( 3 \times 3 \)
can be defined also as
DiagonalMatrix[{1,1,1}]
To construct an \( n \times n \) zero square matrix, use the command Table[Table[0,{n}],{n}], where n specifies the dimension of the matrix.
For example,
Table[Table[0, {3}], {3}]
{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}
or
Table[0, {3}, {3}]
{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}
Adding distinct size matrices
According to definition, we can add (or subtract) two matrices only when they are of the same size by adding (or subtracting) corresponding entries. However, sometimes we need to add two matrices of distinct sizes. It is natural to extend matrices to the largest of dimensions and fill extra entries by zeroes. It turns out that Mathematica accommodates such an operation, but you need to write a special subroutine in Wolfram language,
To add two matrices (or sets of vectors) of different size by appending additional zeros to smallest vectors, we use the following script:
AddSets[A_?MatrixQ, B_?MatrixQ] := Module[{A1, B1, n, m}, A1 = A; B1 = B;
n = Length[A[[1]]]; m = Length[B[[1]]];
Which[n > m, B1 = Map[PadRight[#, n] &, B, 1], n < m,
A1 = Map[PadRight[#, m] &, A, 1], True,(*do nothing*)];
sum1 = Map[PadRight[#, Max[n, m] + 1] &,
Flatten[Table[A1[[i]] + B1[[j]], {i, 1, Length[A1]}, {j, 1, Length[B1]}],
1], 1]; Return[sum1[[All, 1 ;; Length[Part[sum1, 1]] - 1]]];]
Note: The inputs A_ and B_ represent the input
variables. However, we use A_?MatrixQ and B_?MatrixQ to
tell Mathematica to verify that these input variables are
matrices, not arbitrary inputs.
The same code but appending zero to the right of every vector.
AddSets0[A_?MatrixQ, B_?MatrixQ] :=
Module[{A1, B1, n, m },
A1 = A; B1 = B;
n = Length[A[[1]]];
m = Length[B[[1]]];
Which[n > m, B1 = Map[PadRight[#, n] &, B, 1],
n < m, A1 = Map[PadRight[#, m] &, A, 1],
True, (* do nothing *)];
sum1 = Map[PadRight[#, Max[n, m] + 1] &,
Flatten[Table[
A1[[i]] + B1[[j]], {i, 1, Length[A1]}, {j, 1, Length[B1]}], 1],
1];
Return[sum1];
]
For instance, to add two sets of vectors, we apply:
A = {{1, 2, 3}, {4, 5, 6}};
B = {{a, b}, {c, d}, {e, f}};
AddSets[A, B]
The matrix A is defined with two rows and three columns. Notice how the matrix
was specified row-by-row, with each row inside a pair of square brackets and all
three rows enclosed in another set of square brackets; commas are used to separate
matrix entries and rows.
Computer scientists and computer languages prefer to begin counting from zero,
while mathematicians and written mathematics prefer to begin counting at one.
Perhaps the most confusing thing about using Sage for matrix work is that rows and
columns are numbered starting at 0 rather than 1 as is usually done for matrices
in mathematical work. This means that the rows in M are numbered 0, 1, and 2
while the columns are numbered 0, 1, 2, and 3. For example, we can access the
first and second rows with:
Execute the following three cells in the Sage
notebook, and notice how the three matrices are constructed to have entries from the
integers, the rationals and the reals.
The norm of a matrix may be thought of as its size because it is a nonnegative number. Matrix norms are directly related to vector norms.
The definitions are summarized below for an \( n \times n \) matrix A.
which is simply the maximum absolute row sum of the matrix.
In the special case of p = 2 we get the Euclidean norm (which is equal to the largest singular value of a matrix)
Example. Evaluate the norms of the matrix
\( {\bf A} = \left[ \begin{array}{cc} 1 & -7 \\ -2 & -3 \end{array} \right] . \)
The absolute column sums of A are \( 1 + | -2 | =3 \) and \( |-7| + | -3 | =10 . \)
The larger of these is 10 and therefore \( \| {\bf A} \|_1 = 10 . \)
The absolute row sums of A are \( 1 + | -7 | =8 \) and
\( | -2 | + |-3| = 5 , \) therefore, \( \| {\bf A} \|_{\infty} = 8 . \)
This matrix \( {\bf A}\,{\bf A}^{\ast} \) has two eigenvalues
\( \frac{1}{2} \left( 63 \pm \sqrt{2813} \right) . \) Hence, the Euclidean norm of the matrix A is
\( \sqrt{\frac{1}{2} \left( 63 + \sqrt{2813} \right)} \approx 7.61701, \) and its Frobenius norm is
\( \sqrt{63} \approx 7.93725 . \)
sage: M=matrix(QQ,[[2,4,0,8],[-1,3,3,-2],[0,1,1,0]]); M
Our first example deals with economics. Let us consider two families Anderson (A) and Boichuck (B) that have expenses every month
such as: utilities, health, entertainment, food, etc... . Let us restrict ourselves to: food, utilities, and health.
How would one represent the data collected? Many ways are available but one of them has an advantage of combining the data so that it is easy to manipulate them.
Indeed, we will write the data as follows:
The size of the matrix, as a block, is defined by the number of Rows and the number of Columns.
In this case, the above matrix has 2 rows and 3 columns. In our case, we say that the matrix is a \( m \times n \) matrix (pronounce m-by-n matrix).
Keep in mind that the first entry (meaning m) is the number of rows while the second entry (n) is the number of columns. Our above matrix is a (\( 2\times 3 \) ) matrix.
Let us assume, for example, that the matrices for the months of July, August, and September are
respectively. The next question may sound easy to answer, but requires a new concept in the matrix context.
What is the matrix-expense for the two families for the summer? The idea is to add the three matrices above by adding the corresponding entries:
Therefore, to multiply by a scalar, one needs to multiply by this scalar every entry. What about subtracting two matrices?
It is easy, since subtraction is a combination of the two above rules. Indeed, if A and B are two matrices of the same size,
then we will write
The negative of a matrix M, denoted by \( -{\bf M} ,\) is a matrix with elements that are
the negatives of the elements in M. ■
Now we are going to introduce matrix multiplication that may at first seem rather
strange. We don't know exactly who or when the multiplication of matrices was invented. At least we know that the work of 1812 by Jacques Philippe Marie Binet
(1786--1856) contains the definition of the product of matrices.
If A is an \( m \times r \) matrix and B is \( r \times n \) matrix, then the product\( {\bf A}\,{\bf B} \) is the \( m \times n \) matrix whose entries are determined as follows.
To find the entry in row i and column j of \( {\bf A}\,{\bf B} \) , single out row i
from the matrix A and column j from the matrix B. Take the dot product of the corresponding vectors of size r
and put it into \( (i,j) \) spot of product \( {\bf A}\,{\bf B} .\)
Thus, \( {\bf A}\,{\bf B} \ne {\bf B}\,{\bf A} . \) Note that one of the products (\( {\bf A}\,{\bf B} \) or \( {\bf B}\,{\bf A} \) ) may exit, but another not. ■
The n ext important operation is transposition, which changes row into columns.
sage: M = matrix([[1,2,3],[4,5,6]]) sage: I = identity_matrix(3)
If a matrix A has complex entries, its complex conjugate is denoted by \( \overline{\bf A} .\)
The conjugate transpose of A, denoted by \( {\bf A}^{\ast} , \) is defined by
The matrix \( {\bf A}^{\ast} , \) is called adjoint to the matrix A. If \( {\bf A}^{\ast} = {\bf A}, \) then matrix A is called
self-adjoint or Hermitian. ■
where j is a unit vector on the complex plane in positive vertical direction (so \( {\bf j}^2 =- 1 \) ), is symmetric but not self-adjoint.
Its adjoint is
Sage has a matrix method,
.augment()
, that will join two matrices side-by-side
provided they both have the same number of rows. The same method will allow you
to augment a matrix with a column vector.
Some methods allow optional input, typically using keywords. Matrices can track
subdivisions, making breaks between rows and/or columns. When augmenting, you
can ask for the subdivision to be included. Evalute the compute cell above if you
have not already, so that
A and
b are defined, and then evaluate:
sage: M = A.augment(b, subdivide=True) sage: M [1-1 2|1] [2 1 1|8] [1 1 0|5]
sage: m = identity_matrix(3) sage: m[:,1] = vector([5,4,3]); m [1 5 0] [0 4 0] [0 3 1]
It is frequently necessary to deal separately with various groups of elements or blocks/submatrices within a larger matrix.
This situation can asire when the size of a matrix becomes too large for convenient handling, and it becomes imperative to work with only a portion of the matrix.
Also, there will be cases in which one part of a matrix will have a physical significance that is different from the remainder,
and it is instructive to isolate that portion and identify it by a special symbol.
Any matrix can be interpreted as having been broken into sections called blocks or submatrices.
A matrix interpreted as a block matrix can be visualized as the original matrix with inserting horizontal and vertical lines between selected rows and columns, which break it up, or partition it, into a collection of smaller matrices.
For example, the following are three possible partitions of a general \( 3 \times 4 \) matrix---the first
is a partition of A into four submatrices \( {\bf A}_{11}, \ {\bf A}_{12}, \ {\bf A}_{21} , \ \mbox{and} \ {\bf A}_{22} ; \)
the second is a partition of A into its row vectors \( {\bf r}_1, \ {\bf r}_2 , \ \mbox{and}\ {\bf r}_3 ; \) and
the third is a partition of A into its column vectors \( {\bf c}_1 , \ {\bf c}_2 , \ {\bf c}_3 , \ \mbox{and}\ {\bf c}_4 : \)
Partition has many uses, some of them are for finding particular rows or columns of a matrix product \( {\bf A}\,{\bf B} \)
without computing the entire product, or determing the inverse matrix. It is possible to use a block partitioned matrix product that involves only algebra on submatrices of the factors.
The partitioning of the factors is not arbitrary, however, and the dimensions of partition matrices
A and B should match up such that all submatrix products that will be used are defined. Given an
\( m \times n \) matrix A with q row partitions and s column partitions
that are compatible with the partitions of A, the matrix product
\[
{\bf C} = {\bf A}\,{\bf B}
\]
can be formed blockwise, yielding C as an \( m \times n \) matrix with
q row partitions and r column partitions. The matrices in the resulting matrix C are calculated
by multiplying:
Let us consider two matrices A and B, where A has m rows and B has n columns.
We assume that dimensions of these two matrices allow us to multiply them. Then we partition matrix A into row vectors and B into column vectors:
Theorem: If A is an \( m \times n \) matrix, and if \( {\bf x} =
\left[ x_1 , x_2 , \ldots , x_n \right]^{\mathrm T} \) is an \( n \times 1 \) column
vector, then the product \( {\bf A}\,{\bf x} \) can be expressed as a linear combination of the column vectors of A
in which the coefficients are the entries of x:
As a partial demonstration of manipulating subdivisions of matrices, we can reset
the subdivisions of M with the .subdivide()
method. We provide a list of rows to
subdivide before, then a list of columns to subdivide
before, where we remember that
counting begins at zero.
Sage will perform individual row operations on a matrix. This can get a bit tedious,
but it is better than doing the computations by hand, and it can
be useful when building up more complicated procedures for a matrix.
For each row operation, there are two similar methods. One changes the matrix
“in-place” while the other creates a new matrix that is a modified version of the
original. This is an important distinction that you should understand for every new
Sage command you learn that might change a matrix or vector.
Consider the first row operation, which swaps two rows. There are two matrix
methods to do this, a “with” version that will create a new, changed matrix, which
you will likely want to save, and a plain version that will change the
matrix it operates on “in-place.” The
copy()
function, which is a general-purpose command, is a way
to make a copy of a matrix before you make changes to it. Study the example below
carefully, and then read the explanation following. (Remember that
counting begins with zero.)