In linear algebra, understanding the matrix operations is essential for solving a linear system of equations, for obtaining the eigenvalues and eigenvectors, for finding the matrix decompositions and many other applications.
The matrix operations consist of the equality of matrices, the addition, and the subtraction of matrices, the multiplication of matrices and the power of matrices. These operations have numerous interesting properties. We can leverage these properties while performing combinations of these operations to simplify them.
In this article, we will go through these operations and their properties one by one and then we will learn to implement these operations using Python.
Table of Contents
Matrix Operations
The use of various techniques available in linear algebra is impossible without matrix operations. Let’s see what are these matrix operations and their properties in detail.
Equality of Matrices
The conditions for equality of two matrices \(A\) and \(B\) are:
- The matrices \(A\) and \(B\) should be of the same order, i.e., the number of rows (\(m\)) of \(A\) should be equal to that of \(B\), and the number of columns (\(n\)) of \(A\) should be equal to that of \(B\).
- All the elements of the matrix \(A\) should be equal to the corresponding elements of \(B\).
For example:
\begin{equation}
A= \begin{bmatrix}
a & b\\
c & d\\
e & f
\end{bmatrix} \hspace{2em}
B=
\begin{bmatrix}
a & b\\
c & d\\
e & f
\end{bmatrix}
\end{equation}
Here, the matrices \(A\) and \(B\) are equal.
Addition and Subtraction of Matrices
The order of two matrices should be the same to be able to perform the addition or subtraction operation.
The sum \(A\) + \(B\) is defined, such that each element in the matrix \(A\) adds to the corresponding element in the matrix \(B\).
$$
\begin{aligned}
A= \begin{bmatrix}
a & b\\
c & d\\
e & f
\end{bmatrix} \hspace{2em}
B=
\begin{bmatrix}
k & l\\
m & n\\
p & q
\end{bmatrix}\\[2em]
A+B=
\begin{bmatrix}
a+k & b+l\\
c+m & d+n\\
e+p & f+q
\end{bmatrix}
\hspace{1em}
\end{aligned}
$$
Similarly, we can subtract the matrix \(B\) from the matrix \(A\), by subtracting each element of \(B\) from the corresponding element of \(A\).
$$
\begin{aligned}
A-B=
\begin{bmatrix}
a-k & b-l\\
c-m & d-n\\
e-p & f-q
\end{bmatrix}
\end{aligned}
$$
Properties of Addition and Subtraction Operation
Following are the properties of addition and subtraction operation:
- The addition of matrices is commutative.$$\begin{aligned} A+B= B+A \end{aligned} $$
- The addition and subtraction of matrices is associative.$$ \begin{aligned} (A+B)-C= A+(B-C) \end{aligned}$$
- The Null Matrix (\(O\)) of the same order is an additive (and subtractive) identity, i.e. the matrix remains the same after addition or subtraction by the matrix \(O\).$$ \begin{aligned} A+O=A \hspace{1em}and\hspace{1em} A-O=A \end{aligned}$$
- The additive inverse of a matrix is a matrix, when added to the original matrix, results in the Null Matrix.It can be calculated by negating every element of the matrix, i.e., by changing the sign of the element. The additive inverse of the matrix \(A\) is denoted by \(-A\).$$ \begin{aligned}
A=
\begin{bmatrix}
a & b\\
c & d\\
e & f
\end{bmatrix} \hspace{2em}
-A=
\begin{bmatrix}
-a & -b\\
-c & -d\\
-e & -f
\end{bmatrix}\\[2em]
A+(-A) = O =
\begin{bmatrix}
0 & 0\\
0 & 0\\
0 & 0
\end{bmatrix}
\hspace{2em}
\end{aligned}$$
Matrix Multiplied by a Scalar
When the matrix multiplied by a scalar value, say \(p\), we obtain the resulting matrix by multiplying each element of the matrix by the scalar \(p\).
$$ \begin{aligned}
A&=
\begin{bmatrix}
a & b & c\\
d & e & f
\end{bmatrix} \\[1.5em]
pA &=
\begin{bmatrix}
pa & pb & pc\\
pd & pe & pf
\end{bmatrix}
\end{aligned}$$
Note: When determinant of a matrix is multiplied by a scalar value, then only one line (row or column) is multiplied by that value.
Properties of Scalar Multiplication Operation
The matrix multiplied by a scalar value is a distributive operation.
$$\begin{aligned} p(A+B)= pA+pB \end{aligned}$$
Multiplication of Matrices
We can multiply two matrices (the product \(AB\) is defined) only when they are conformable, i.e., the number of columns in the first matrix should be equal to the number of rows in the second.
$$\begin{aligned}
(m\times n)(n\times k)=(m\times k) \end{aligned}$$
The resulting matrix has the number of rows the same as the first matrix and the number of columns the same as the second matrix.
$$\begin{aligned}
A_{2\times3}&=
\begin{bmatrix}
a & b & c \\
d & e & f
\end{bmatrix} \hspace{2em}
B_{3\times2} =
\begin{bmatrix}
l & p \\
m & q \\
n & r
\end{bmatrix} \\[2em]
(AB)_{2\times2} &=
\begin{bmatrix}
al+bm+cn & ap+bq+cr\\
dl+em+fn & dp+eq+fr
\end{bmatrix} \\[0.5em]
\end{aligned}$$
In the matrix multiplication \(AB\), the matrix \(A\) is post-multiplied by the matrix \(B\) and in the multiplication \(BA\), the matrix \(A\) is pre-multiplied by the matrix \(B\).
$$\begin{aligned}
(BA)_{3\times3} =
\begin{bmatrix} la+pd & lb+pe & lc+pf\\
ma+qd & mb+qe & mc+qf\\
na+rd & nb+re & nc+rf \end{bmatrix} \\[0.5em] \end{aligned}$$
The matrix multiplication \(BA\) is defined only when the number of rows in matrix \(A\) (\(m\)) is equal to the number of columns in matrix \(B\) (\(k\)).
Let’s see one example:
$$
\begin{aligned}
A_{2\times3}&=
\begin{bmatrix}
1 & 2 & 3\\
4 & 5 & 6
\end{bmatrix} \hspace{2em}
B_{3\times2} =
\begin{bmatrix}
7 & 10 \\
8 & 11 \\
9 & 12
\end{bmatrix} \\[2em]
(AB)_{2\times2} &=
\begin{bmatrix}
1\times7+2\times8+3\times9 & 1\times10+2\times11+3\times12\\
4\times7+5\times8+6\times9 & 4\times10+5\times11+6\times12\\
\end{bmatrix} \\[0.5em]
&=
\begin{bmatrix}
7+16+27 & 10+22+36\\
28+40+54 & 40+55+72\\
\end{bmatrix} \\[0.5em]
&= \begin{bmatrix}
50 & 68\\
122 & 167\\
\end{bmatrix} \\[2em]
(BA)_{3\times3} &=
\begin{bmatrix}
7\times1+10\times4 & 7\times2+10\times5 &
7\times3+10\times6\\
8\times1+11\times4 & 8\times2+11\times5 &
8\times3+11\times6\\
9\times1+12\times4 & 9\times2+12\times5 &
9\times3+12\times6\\
\end{bmatrix} \\[0.5em]
&=
\begin{bmatrix}
7+40 & 14+50 & 21+60\\
8+44 & 16+55 & 24+66\\
9+48 & 18+60 & 27+72
\end{bmatrix} \\[0.5em]
&=
\begin{bmatrix}
47 & 64 & 81\\
52 & 71 & 90\\
57 & 78 & 99\\
\end{bmatrix}
\end{aligned}$$
In general, if \(A_{m\times n}\) and \(B_{n\times k}\) are two conformable matrices, then the matrix \((AB)_{m\times k}\) is defined as:
$$\begin{aligned}
A_{m\times n} =
\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} \hspace{2em} B_{n\times k} = \begin{bmatrix} b_{11} & b_{12} & \dots & b_{1k} \\ b_{21} & b_{22} & \dots & b_{2k} \\ \vdots & \vdots & \ddots & \vdots\\ b_{n1} & b_{n2} & \dots & b_{nk} \end{bmatrix}\\[3em] (AB)_{m\times k} = \begin{bmatrix} c_{11} & c_{12} & \dots & c_{1k} \\ c_{21} & c_{22} & \dots & c_{2k} \\ \vdots & \vdots & \ddots & \vdots\\ c_{m1} & c_{m2} & \dots & c_{mk} \end{bmatrix}\hspace{2.5cm} \end{aligned}$$
where the term \(c_{ij}\) is called the inner product of the \(i^{th}\) row of \(A\) and the \(j^{th}\) column of \(B\) and is obtained by summing the multiplication of the elements of the \(i^{th}\) row by the corresponding elements of the \(j^{th}\) column.
$$\begin{aligned}
c_{ij} =
a_{i1}b_{1j} + a_{i2}b_{2j} + a_{i3}b_{3j} + \dots + a_{in}b_{nj} \end{aligned}$$
Properties of Matrix Multiplication
Following are the properties of matrix multiplication operation:
- Multiplication of matrices is NOT commutative.$$\begin{aligned} AB\neq BA \end{aligned}$$provided \(BA\) is defined. Also, \(AB\) can be equal to \(BA\) for some cases of \(A\) and \(B\), but it is very rare.
- Matrix multiplication is associative.$$\begin{aligned} (AB)C = A(BC) \end{aligned}$$ where A, B and B, C should be conformable for the products AB and BC to be defined, respectively.
- Matrix multiplication is distributive.$$\begin{aligned}
A(B+C) &= AB+AC\\[0.5em] (A+B)C &= AC+BC \end{aligned}$$where the corresponding matrices should be conformable for the products to be defined.
- Transpose of the matrix multiplication is defined by taking the transpose of individual matrices and reversing their position.$$\begin{aligned}
(AB)^T &= B^TA^T
\end{aligned}$$Matrices remain conformable after taking the transpose and reversing the order.
- Associativity of the product by a scalar quantity of \(c\) with the matrix multiplication is defined as$$\begin{aligned}
(AB)c &= A(Bc)\\[0.5em]
c(AB) &= (cA)B
\end{aligned}$$provided, the matrix multiplication \(AB\) is defined, i.e., \(A\) and \(B\) are conformable.
- There exists a multiplicative identity \(I\), when multiplied with the matrix, results in the original matrix.$$\begin{aligned} I_mA = AI_n = A\\[0.5em] \end{aligned}$$where \(I\) is an Identity Matrix of the corresponding order, which makes both the matrices conformable.
Power of a Matrix
We can define the power of a matrix as the multiplication of two matrices. The square of matrix \(A\) can be defined as the product \(AA\) and the cube of matrix \(A\) is defined as the multiplication of \(A\) and \(A^2\).
$$
\begin{aligned}
A^2 &= AA \\[0.5em]
A^3 &= AA^2
\end{aligned}
$$
In general, the \(n^{th}\) power of matrix \(A\) is defined as:
$$
\begin{aligned}
A^n &= AA^{n-1}\\[0.5em]
&= A(AA^{n-2})
\end{aligned}
$$
Properties of Power Operation
- If the square of a matrix is an identity matrix, then that matrix is said to be an Involutory Matrix, i.e., \(A^2=I\).
- If the square of the matrix results in the same matrix, i.e., if \(A^2=A\), then matrix A is called an Idempotent Matrix
- If the square of the matrix results in the Null Matrix, i.e., if \(A^2=0\), then matrix A is called a Nilpotent Matrix
Matrix Operations Using Python
We will use the NumPy library to perform the matrix operations. This library has all the necessary functions for checking the matrix equality, the matrix multiplication, the power of a matrix, etc. predefined.
To install the Numpy library, we can use
pip install numpy
I suggest you to use Jupyter Notebook to follow the contents of this part of the article. Check my other article on setting up Python for scientific computing to get started.
Let’s import the NumPy library with an alias np using
import numpy as np
Now we are ready to get started with the implementation of matrix operations using Python.
Check for Equality of Matrices Using Python
The NumPy library of Python provides multiple ways to check the equality of two matrices. Let’s go through them one by one.
Few of the available functions check and output the element-wise equality of the matrices. The output is also a matrix of the same order as the given matrices containing boolean values (True or False). If all the element-wise checks are True, then the matrices are equal.
On the other hand, few functions check for the equality of matrices as a whole and output single boolean value (True or False) indicating the equality of matrices.
Element-wise Equality Check
The functions showing the element-wise comparison are:
- numpy.equal( )The numpy.equal( ) function checks if the elements of the given matrices are exactly equal.
A = np.array([[1,2,3],[4,5,6]]) B = np.array([[1,2,3],[4,5,6]]) C = np.array([[1.0000001,2,3],[4,5.00000001,6]]) print('Matrix A:') print(A) print('Matrix B:') print(B) print('Matrix C:') print(C) print('Check for the equality of Matrices A and B:') print(np.equal(A,B)) print('Check for the equality of Matrices A and C:') print(np.equal(A,C))
Output:
Matrix A: [[1 2 3] [4 5 6]] Matrix B: [[1 2 3] [4 5 6]] Matrix C: [[1.0000001 2. 3. ] [4. 5.00000001 6. ]] Check for the equality of Matrices A and B: [[ True True True] [ True True True]] Check for the equality of Matrices A and C: [[False True True] [ True False True]]
As we can observe that the elements of matrices \(A\) and \(C\) are almost equal, but the numpy.equal( ) function flags them as not-equal.
In that case, another function from the NumPy library comes in handy if we want to check if the elements of two matrices are within some acceptable tolerance.
- numpy.isclose( )Unlike the numpy.equal( ) function, the numpy.isclose( ) function allows us to set a tolerance limit within which the elements of the matrices are said to be equal.The formula used for checking the equality of corresponding elements of the two matrices is$$absolute(a – b) <= (atol + rtol * absolute(b))$$The default value of the absolute tolerance parameter is atol=1e-8 and that of the relative tolerance parameter is rtol=1e-5.
A = np.array([[1,2,3],[4,5,6]]) B = np.array([[1,2,3],[4,5,6]]) C = np.array([[1.0000001,2,3],[4,5.00000001,6]]) print('Matrix A:') print(A) print('Matrix B:') print(B) print('Matrix C:') print(C) print('Check for the equality of Matrices A and B:') print(np.isclose(A,B)) print('Check for the equality of Matrices A and C:') print(np.isclose(A,C))
Output:
Matrix A: [[1 2 3] [4 5 6]] Matrix B: [[1 2 3] [4 5 6]] Matrix C: [[1.0000001 2. 3. ] [4. 5.00000001 6. ]] Check for the equality of Matrices A and B: [[ True True True] [ True True True]] Check for the equality of Matrices A and C: [[ True True True] [ True True True]]
Notice that the \(1^{st}\) and \(5^{th}\) elements of the same matrices were indicated as not equal when we used the numpy.equal( ) function.
We can specify the value of the tolerance parameters according to our needs because the absolute tolerance parameter value atol=1e-8 might not be appropriate for some cases. For example, when the matrices have the values of the elements much smaller than one.
P = np.array([[1,2,3],[4,5,1e-5]]) Q = np.array([[1.0000001,2,3],[4,5.00000001,0.99e-5]]) print('Matrix P:') print(P) print('Matrix Q:') print(Q) print('Check for the equality of Matrices P and Q with lower tolerance:') print(np.isclose(P,Q,atol=1e-8))
Output:
Matrix P: [[1.e+00 2.e+00 3.e+00] [4.e+00 5.e+00 1.e-05]] Matrix Q: [[1.00000010e+00 2.00000000e+00 3.00000000e +00] [4.00000000e+00 5.00000001e+00 9. 90000000e-06]] Check for the equality of Matrices P and Q with lower tolerance: [[ True True True] [ True True False]]
Notice the last element of matrices \(P\) and \(Q\).
Equality Check with Matrix as a Whole
Contrary to the previous functions, few functions in the NumPy library offer a way to get a single boolean value as an output for comparison. Therefore, these functions have an added advantage that we can use them in conditional statements.
Following functions return True or False, when two matrices are entered as inputs:
- numpy.array_equal( )The numpy.array_equal( ) function returns True if the shapes of two matrices are the same and all the corresponding elements of the matrices are equal.This function can be thought of as matrix level equivalent of the previously discussed numpy.equal( ) function, i.e., when all the elements of the matrix returned by numpy.equal( ) are True, the numpy.array_equal( ) function will return single True value for the same set of input matrices.If any of the elements of the matrix returned by numpy.equal( ) are False, the numpy.array_equal( ) function will return False for the same set of input matrices.
A = np.array([[1,2,3],[4,5,6]]) B = np.array([[1,2,3],[4,5,6]]) C = np.array([[1.0000001,2,3],[4,5.00000001,6]]) print('Matrix A:') print(A) print('Matrix B:') print(B) print('Matrix C:') print(C) print('Check for the equality of Matrices A and B:') print(np.array_equal(A,B)) print('Check for the equality of Matrices A and C:') print(np.array_equal(A,C))
Output:
Matrix A: [[1 2 3] [4 5 6]] Matrix B: [[1 2 3] [4 5 6]] Matrix C: [[1.0000001 2. 3. ] [4. 5.00000001 6. ]] Check for the equality of Matrices A and B: True Check for the equality of Matrices A and C: False
- numpy.allclose( )We can consider this function as the matrix level equivalent of the numpy.isclose( ) function.The numpy.allclose( ) function uses the same formula as the numpy.isclose( ) function.$$absolute(a – b) <= (atol + rtol * absolute(b))$$For example:
A = np.array([[1,2,3],[4,5,6]]) B = np.array([[1,2,3],[4,5,6]]) C = np.array([[1.0000001,2,3],[4,5.00000001,6]]) print('Matrix A:') print(A) print('Matrix B:') print(B) print('Matrix C:') print(C) print('Check for the equality of Matrices A and B:') print(np.allclose(A,B)) print('Check for the equality of Matrices A and C:') print(np.allclose(A,C))
Output:
Matrix A: [[1 2 3] [4 5 6]] Matrix B: [[1 2 3] [4 5 6]] Matrix C: [[1.0000001 2. 3. ] [4. 5.00000001 6. ]] Check for the equality of Matrices A and B: True Check for the equality of Matrices A and C: True
We can change the tolerance parameters (atol and rtol) according to our requirements.
Check the article on Types of Matrices and the Github Repository to see the above two functions in action.
Addition and Subtraction of Matrices Using Python
The addition and subtraction of the matrices are the same as the scalar addition and subtraction operation. Therefore we can simply use the \(+\) and \(-\) operators to add and subtract two matrices.
$$
\begin{aligned}
A =
\begin{bmatrix}
1 & 3 & 5\\
7 & 9 & 11
\end{bmatrix}
\hspace{0.5cm}
&and
\hspace{0.5cm}
B =
\begin{bmatrix}
1 & 2 & 3\\
4 & 5 & 6
\end{bmatrix}\\[1em]
A+B =
\begin{bmatrix}
2 & 5 & 8\\
11 & 14 & 17
\end{bmatrix}
\hspace{0.5cm}
&and
\hspace{0.5cm}
A-B =
\begin{bmatrix}
0 & 1 & 2\\
3 & 4 & 5
\end{bmatrix}
\end{aligned}
$$
These are the element-wise operations in which the corresponding elements of the two matrices are added or subtracted to get the resulting matrices.
A = np.array([[1,3,5],[7,9,11]])
B = np.array([[1,2,3],[4,5,6]])
print('Matrix A:')
print(A)
print('Matrix B:')
print(B)
print('Matrix Addition:')
print(A+B)
print('Matrix Subtraction')
print(A-B)
Output:
Matrix A:
[[ 1 3 5]
[ 7 9 11]]
Matrix B:
[[1 2 3]
[4 5 6]]
Matrix Addition:
[[ 2 5 8]
[11 14 17]]
Matrix Subtraction
[[0 1 2]
[3 4 5]]
We can also use the numpy.add( ) and numpy.subtract( ) functions available in the NumPy library, if we want to have some added functionality.
These functions take two matrices to be added or subtracted as input.
A = np.array([[1,3,5],[7,9,11]])
B = np.array([[1,2,3],[4,5,6]])
print('Matrix A:')
print(A)
print('Matrix B:')
print(B)
print('Matrix Addition:')
print(np.add(A,B))
print('Matrix Subtraction')
print(np.subtract(A,B))
Output:
Matrix A:
[[ 1 3 5]
[ 7 9 11]]
Matrix B:
[[1 2 3]
[4 5 6]]
Matrix Addition:
[[ 2 5 8]
[11 14 17]]
Matrix Subtraction
[[0 1 2]
[3 4 5]]
Properties of Addition and Subtraction Operation Using Python
Now let’s extend our simple addition and subtraction program to check the validity of the properties stated previously.
- Matrix addition is commutative.
A = np.array([[1,3,5],[7,9,11]]) B = np.array([[1,2,3],[4,5,6]]) print('Matrix A:') print(A) print('Matrix B:') print(B) print('Matrix Addition (A + B):') print(A+B) print('Matrix Addition (B + A):') print(B+A)
Output:
Matrix A: [[ 1 3 5] [ 7 9 11]] Matrix B: [[1 2 3] [4 5 6]] Matrix Addition (A + B): [[ 2 5 8] [11 14 17]] Matrix Addition (B + A): [[ 2 5 8] [11 14 17]]
Hence proved!
- Addition and subtraction of matrices is associative
A = np.array([[1,3,5],[7,9,11]]) B = np.array([[1,2,3],[4,5,6]]) C = np.array([[2,1,3],[3,2,1]]) print('Matrix A:') print(A) print('Matrix B:') print(B) print('Matrix C:') print(C) print('Matrix Operation (A + B):') print((A + B)) print('Matrix Operation (A + B) - C:') print((A + B) - C) print('-------------------------') print('Matrix Operation (B - C):') print((B - C)) print('Matrix Operation A + (B - C):') print(A + (B - C))
Output:
Matrix A: [[ 1 3 5] [ 7 9 11]] Matrix B: [[1 2 3] [4 5 6]] Matrix C: [[2 1 3] [3 2 1]] Matrix Operation (A + B): [[ 2 5 8] [11 14 17]] Matrix Operation (A + B) - C: [[ 0 4 5] [ 8 12 16]] ------------------------- Matrix Operation (B - C): [[-1 1 0] [ 1 3 5]] Matrix Operation A + (B - C): [[ 0 4 5] [ 8 12 16]]
It is quite intuitive to understand this property.
- The Null Matrix (\(O\)) of the same order is an additive (and subtractive) identity.
A = np.array([[1,2,3],[4,5,6]]) O = np.zeros((2,3),dtype=int) print('Matrix A:') print(A) print('Matrix O:') print(O) print('Matrix Operation (A + O)') print(A + O) print('Matrix Operation (A - O)') print(A - O)
Output:
Matrix A: [[1 2 3] [4 5 6]] Matrix O: [[0 0 0] [0 0 0]] Matrix Operation (A + O) [[1 2 3] [4 5 6]] Matrix Operation (A - O) [[1 2 3] [4 5 6]]
- The additive inverse of a matrixWe can get the additive inverse by reversing the sign of each element.
A = np.array([[1,-2,3],[-4,5,-6]]) B = -1*A print('Matrix A:') print(A) print('Matrix (-A):') print(B) print('Matrix Operation A + (-A)') print(A+B)
Output:
Matrix A: [[ 1 -2 3] [-4 5 -6]] Matrix (-A): [[-1 2 -3] [ 4 -5 6]] Matrix Operation A + (-A) [[0 0 0] [0 0 0]]
Multiply a Matrix by a Scalar in Python
As per the definition of multiplying a matrix by a scalar quantity, we need to multiply each element of the matrix by that scalar.
We can achieve this in the Python using the broadcasting functionality of the NumPy library.
A = np.array([[1,2,3],[4,5,6]])
print('Matrix A:')
print(A)
print('Matrix A multiplied by scalar:')
print(3*A)
Output:
Matrix A:
[[1 2 3]
[4 5 6]]
Matrix A multiplied by scalar:
[[ 3 6 9]
[12 15 18]]
Now, let’s validate the distributive property of the scalar multiplication operation with one example.
A = np.array([[1,2,3],[4,5,6]])
B = np.array([[1,3,5],[7,9,11]])
k = 3
print('Matrix A:')
print(A)
print('Matrix B:')
print(B)
print('Resultant matrix of kA + kB:')
print(k*A+k*B)
print('Resultant matrix of k(A+B):')
print(k*(A+B))
Output:
Matrix A:
[[1 2 3]
[4 5 6]]
Matrix B:
[[ 1 3 5]
[ 7 9 11]]
Resultant matrix of kA + kB:
[[ 6 15 24]
[33 42 51]]
Resultant matrix of k(A+B):
[[ 6 15 24]
[33 42 51]]
As you can see, both the resulting matrices are the same validating the distributive property.
Matrix Multiplication Using Python
Matrix multiplication is probably one of the most important matrix operations in linear algebra. We need to use matrix multiplication (or matrix product) in the case of solving the linear system of equations, while calculating the eigenvalues and eigenvectors, while obtaining the matrix decompositions.
With the powerful NumPy library, we can multiply two matrices with a single line of code using the numpy.matmul( ) function.
If you are using the Python version 3.5+, then you can use the *@* operator for the matrix multiplication.
A = np.array([[1,2,3],[4,5,6]])
B = np.array([[7,10],[8,11],[9,12]])
print('Matrix A (2x3):')
print(A)
print('Matrix B (3x2):')
print(B)
print('Matrix multiplication AB (2x2):')
print(np.matmul(A,B))
print('Matrix multiplication BA (3x3):')
print(np.matmul(B,A))
print('-------------------------')
print('Matrix multiplication AB (2x2) using @ operator:')
print(A@B)
print('Matrix multiplication BA (3x3) using @ operator:')
print(B@A)
Output:
Matrix A (2x3):
[[1 2 3]
[4 5 6]]
Matrix B (3x2):
[[ 7 10]
[ 8 11]
[ 9 12]]
Matrix multiplication AB (2x2):
[[ 50 68]
[122 167]]
Matrix multiplication BA (3x3):
[[47 64 81]
[52 71 90]
[57 78 99]]
-------------------------
Matrix multiplication AB (2x2) using @ operator:
[[ 50 68]
[122 167]]
Matrix multiplication BA (3x3) using @ operator:
[[47 64 81]
[52 71 90]
[57 78 99]]
Properties of Matrix Multiplication Using Python
Matrix multiplication operation has many interesting properties.
- Matrix multiplication is NOT commutative.If any or both of the matrices are the Rectangular Matrices, then the product \(BA\) may or may not be defined, because the matrices might not be conformable.If both the matrices are the Square Matrices of the same order, then the product \(BA\) is always defined.Let’s see one example:
A = np.array([[1,2,3],[4,5,6],[7,8,9]]) B = np.array([[1,3,5],[7,9,11],[13,15,17]]) print('Matrix A:') print(A) print('Matrix B:') print(B) print('Matrix product AB:') print(np.matmul(A,B)) print('Matrix product BA:') print(np.matmul(B,A))
Output:
Matrix A: [[1 2 3] [4 5 6] [7 8 9]] Matrix B: [[ 1 3 5] [ 7 9 11] [13 15 17]] Matrix product AB: [[ 54 66 78] [117 147 177] [180 228 276]] Matrix product BA: [[ 48 57 66] [120 147 174] [192 237 282]]
As we can observe that the products \(AB\) and \(BA\) are not equal.
- Matrix multiplication is associative.The associativity of matrix multiplication is a very useful property.
A = np.array([[1,2,3],[4,5,6]]) B = np.array([[7,10],[8,11],[9,12]]) C = np.array([[13],[14]]) AB = np.matmul(A,B) BC = np.matmul(B,C) print('Matrix A (2x3):') print(A) print('Matrix B (3x2):') print(B) print('Matrix C (2x1):') print(C) print('Matrix Product (AB)C (2x1):') print(np.matmul(AB,C)) print('Matrix Product A(BC) (2x1):') print(np.matmul(A,BC))
Output:
Matrix A (2x3): [[1 2 3] [4 5 6]] Matrix B (3x2): [[ 7 10] [ 8 11] [ 9 12]] Matrix C (2x1): [[13] [14]] Matrix Product (AB)C (2x1): [[1602] [3924]] Matrix Product A(BC) (2x1): [[1602] [3924]]
- Matrix multiplication is distributive.To use this property, make sure that all the corresponding matrices are conformable.
A = np.array([1,2]) B = np.array([[3,4],[5,6]]) C = np.array([[7,8],[9,10]]) AB = np.matmul(A,B) AC = np.matmul(A,C) BC = np.matmul(B,C) print('Matrix A (1x2):') print(A) print('Matrix B (2x2):') print(B) print('Matrix C (2x2):') print(C) # Let's distribute the left multiplication print('--------------------------------') print('Distributing left multiplication') print('Matrix Product A*(B + C) (1x2):') print(np.matmul(A,B+C)) print('Matrix Product (AB + AC) (1x2):') print(AB+AC) # Similarly we can distribute the right multiplication print('--------------------------------') print('Distributing right multiplication') print('Matrix Product (A + B)*C (2x2):') print(np.matmul(A+B,C)) print('Matrix Product (AC + BC) (2x2):') print(AC+BC)
Output:
Matrix A (1x2): [1 2] Matrix B (2x2): [[3 4] [5 6]] Matrix C (2x2): [[ 7 8] [ 9 10]] -------------------------------- Distributing left multiplication Matrix Product A*(B + C) (1x2): [38 44] Matrix Product (AB + AC) (1x2): [38 44] -------------------------------- Distributing right multiplication Matrix Product (A + B)*C (2x2): [[ 82 92] [114 128]] Matrix Product (AC + BC) (2x2): [[ 82 92] [114 128]]
- Transpose of a matrix multiplicationIf \(AB\) is conformable then \(B^TA^T\) will also be conformable.
A = np.array([1,2,3]) B = np.array([[4,7],[5,8],[6,9]]) AB = np.matmul(A,B) print('Matrix A (1x3):') print(A) print('Matrix B (3x2):') print(B) print('Transpose of matrix product AB:') print(AB.T) print('Product of B transpose and A transpose:') print(np.matmul(B.T,A.T))
Output:
Matrix A (1x3): [1 2 3] Matrix B (3x2): [[4 7] [5 8] [6 9]] Transpose of matrix product AB: [32 50] Product of B transpose and A transpose: [32 50]
- Associativity of the product by a scalar quantity with the matrix multiplication
A = np.array([[1,2],[3,4]]) B = np.array([[5,6],[7,8]]) AB = np.matmul(A,B) c = 2 print('Matrix A:') print(A) print('Matrix B:') print(B) print('--------------------------------') print('Left associativity') print('Matrix operation c(AB):') print(c*AB) print('Matrix operation (cA)B:') print(np.matmul(c*A,B)) print('--------------------------------') print('Right associativity') print('Matrix operation (AB)c:') print(AB*c) print('Matrix operation A(Bc):') print(np.matmul(A,B*c))
Output:
Matrix A: [[1 2] [3 4]] Matrix B: [[5 6] [7 8]] -------------------------------- Left associativity Matrix operation c(AB): [[ 38 44] [ 86 100]] Matrix operation (cA)B: [[ 38 44] [ 86 100]] -------------------------------- Right associativity Matrix operation (AB)c: [[ 38 44] [ 86 100]] Matrix operation A(Bc): [[ 38 44] [ 86 100]]
As you can see, the resulting matrices are equal.
- The multiplicative identity \(I\), when multiplied with the matrix results in the original matrix.
A = np.array([[1,2,3],[4,5,6]]) (m,n) = np.shape(A) Im = np.eye(m,dtype=int) In = np.eye(n,dtype=int) print('Matrix A:') print(A) print('Matrix Im:') print(Im) print('Matrix In:') print(In) print('--------------------------------') print('Pre-multiplication by Im:') print(np.matmul(Im,A)) print('--------------------------------') print('Post-multiplication by In:') print(np.matmul(A,In))
Output:
Matrix A: [[1 2 3] [4 5 6]] Matrix Im: [[1 0] [0 1]] Matrix In: [[1 0 0] [0 1 0] [0 0 1]] -------------------------------- Pre-multiplication by Im: [[1 2 3] [4 5 6]] -------------------------------- Post-multiplication by In: [[1 2 3] [4 5 6]]
Here \(Im\) and \(In\) are Identity Matrices.
Raise a Matrix to a Power Using Python
The matrix should be a Square Matrix, i.e., the number of rows should be equal to the number of columns, to be able to calculate the power of the matrix.
We have two methods available to calculate the power of a matrix. The first method is to use the numpy.matmul( ) function.
A = np.array([[1,2,3],[4,5,6],[7,8,9]])
A_sq = np.matmul(A,A)
A_cube = np.matmul(A,A_sq)
print('Matrix A:')
print(A)
print('Square of Matrix A:')
print(A_sq)
print('Cube of Matrix A:')
print(A_cube)
Output:
Matrix A:
[[1 2 3]
[4 5 6]
[7 8 9]]
Square of Matrix A:
[[ 30 36 42]
[ 66 81 96]
[102 126 150]]
Cube of Matrix A:
[[ 468 576 684]
[1062 1305 1548]
[1656 2034 2412]]
But this method becomes repetitive and tedious if we want to raise the matrix to a higher power.
In this case, the second method is more elegant and efficient, which uses the numpy.linalg.matrix_power( ) from the NumPy library.
A = np.array([[1,2,3],[4,5,6],[7,8,9]])
print('Matrix A:')
print(A)
print('Square of Matrix A:')
print(np.linalg.matrix_power(A,2))
print('Cube of Matrix A:')
print(np.linalg.matrix_power(A,3))
print('Sixth power of Matrix A:')
print(np.linalg.matrix_power(A,6))
Output:
Matrix A:
[[1 2 3]
[4 5 6]
[7 8 9]]
Square of Matrix A:
[[ 30 36 42]
[ 66 81 96]
[102 126 150]]
Cube of Matrix A:
[[ 468 576 684]
[1062 1305 1548]
[1656 2034 2412]]
Sixth power of Matrix A:
[[ 1963440 2412504 2861568]
[ 4446414 5463369 6480324]
[ 6929388 8514234 10099080]]
Properties of the Power of a Matrix Using Python
All the properties of the power of the matrix are discussed in detail in the article on types of matrices.
Did you find this article useful? Please comment and share it with your friends. Please let me know, if there are any suggestions or queries regarding the content of this article.