You are currently viewing Types of Matrices | Linear Algebra Using Python

Types of Matrices | Linear Algebra Using Python

Matrices are categorized based on different criteria like number of rows and columns, type of elements, arrangement of elements, and so on. We will see the definition and examples of different types of matrices. We will then go through the ways to create these matrices and define the Python functions to check for these types of matrices.

List of Types of Matrices

Different types of matrices are-

You can get to the definition and examples of different matrix types by clicking the matrix type in the above list and click the title there, to jump to the Python implementation.

Types of Matrices

Any given matrix can have characteristics of more than one type of matrices. Let’s understand them one by one:

Singleton Matrix

The matrix with only one element is called a Singleton Matrix. In this matrix, the number of rows and the number of columns is one ( m = n = 1 ). e.g. \([-2]\), \([100]\), \([i]\), etc. are singleton matrices.

Row Matrix

A matrix is said to be a Row Matrix when it has only one row ( m = 1 ) of elements. The order of the row matrix is 1 X n .

Row Matrix

Row Matrices

For example-

\begin{equation*}
A = \begin{bmatrix}
4 & 7 & 2
\end{bmatrix}
\end{equation*}

\(A\) is a row matrix of order 1 X 3.

Column Matrix

As the name suggests, a Column Matrix has only one column of elements (n = 1). This type of matrix has the order m X 1 .

Column Matrix

Column Matrices

\begin{equation*}
B = \begin{bmatrix}
5 \\ 14 \\ 52 \\ -8
\end{bmatrix}
\end{equation*}

\(B\) is a column matrix of order 4 X 1.

Note: Vectors can be expressed as row or column matrices.

Rectangular Matrix

A matrix is said to be a Rectangular Matrix if the number of rows are not equal to the number of columns ( m ≠ n ). Number of rows can be greater than number of columns or vice versa ( m > n or m < n ).

Rectangular Matrix

Rectangular Matrices

\begin{equation*} P = \begin{bmatrix} 1 & 2 & 3 & 4\\ 5 & 6 & 7 & 8
\end{bmatrix} \, \, \, \, \, \, and \, \, \, \, \, \, \, \, Q =
\begin{bmatrix} 7 & 63 & -34\\ 12 & 57 & 83 \\ -75 & 8 & 49 \\ 38 & 45 & 11
\end{bmatrix} \end{equation*}

\(P\) is a matrix of order 2 X 4 and \(Q\) is a matrix of order 4 X 3.

Square Matrix

A matrix which has the number of rows equal to the number of columns (m = n) is called the Square Matrix. The square matrix is called m th order or n th order matrix based on the number of rows or columns.

Square Matrix

Square Matrices

\begin{equation*} A = \begin{bmatrix} 21 & 72 & 34\\ 94 & 55 & 67 \\ 37 & 83 &
9 \end{bmatrix} \end{equation*}

\(A\) is a 3 rd order square matrix.

Null or Zero Matrix

A matrix is said to be a Null or Zero Matrix if all the elements of the matrix are ‘zero’. Null matrix can be a row, column, rectangular or square matrix.

Zero or Null Matrix

Zero or Null Matrices

\begin{equation*} O = \begin{bmatrix} 0 & 0 & 0\\ 0 & 0 & 0 \\ 0 & 0 & 0
\end{bmatrix} \, \, \, \, \, \, or \, \, \, \, \, \, \, \, O = \begin{bmatrix}
0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix} \end{equation*}

The n th -order null matrix is denoted as \(O_n\).

Real Matrix

When all the elements of the matrix are real numbers, then the matrix is called a Real Matrix.

\begin{equation*} C = \begin{bmatrix} 2 & -7 & 4\\ 9 & 5 & -6 \\ 7 & -8 & 3
\end{bmatrix} \, \, \, \, \, \, and \, \, \, \, \, \, \, \, D =
\begin{bmatrix} 1.5 & 3.6 \\ 8.4 & 4.7 \\ 5.8 & 2.9 \end{bmatrix}
\end{equation*}

Note: All the previous examples of matrices are real matrices except the complex singleton matrix.

Complex Matrix

A matrix is said to be a Complex Matrix if at least one element of the matrix is a complex or pure imaginary number.

\begin{equation*} L = \begin{bmatrix} 3 & 8 & -5i\\ 1+2i & 0 & 11 \\ 4 & 26 &
7 \end{bmatrix} \, \, \, \, \, \, and \, \, \, \, \, \, \, \, K =
\begin{bmatrix} 2+7i & 5+3i & 8-4i & 5i\\ -3i & 0 & 7+9i & 8 \end{bmatrix}
\end{equation*}

Conjugate Matrix

A Conjugate Matrix is obtained by taking complex conjugate of each element of a Complex Matrix. \(\overline{K}\) is the conjuagte matrix of \(K\) matrix from previous example.

\begin{equation*} \overline{K} = \begin{bmatrix} 2-7i & 5-3i & 8+4i & -5i\\ 3i
& 0 & 7-9i & 8 \end{bmatrix} \end{equation*}

Transpose of a Matrix

Matrix obtained by interchanging the rows and columns of the given matrix is called the Transpose of a Matrix. Transpose of the matrix is denoted as \(A’\) or \(A ^ T\).

\begin{equation*} A = \begin{bmatrix} 1/4 & 1/2 & 3/4 & 1 \\ 5/4 & 3/2 & 7/4 &
2 \end{bmatrix} \, \, \, \, \, \, and \, \, \, \, \, \, \, \, A ^ T =
\begin{bmatrix} 1/4 & 5/4 \\ 1/2 & 3/2 \\ 3/4 & 7/4 \\ 1 & 2 \end{bmatrix}
\end{equation*}

Conjugate Transpose

A Conjugate Transpose of a complex matrix is obtained by taking a transpose of the conjugate matrix of the given matrix. The conjugate transpose is denoted as \(A ^ H\) where ‘H’ stands for Hermitian. Hence the definition can be written as \(A ^ H=[\overline{A}] ^ T\).

\begin{equation*} A = \begin{bmatrix} 3+2i & 5-7i & -8i \\ -2+5i & 12i & 7-4i
\end{bmatrix} \, \, \, \, \, \, and \, \, \, \, \, \, \, \, A ^ H =
\begin{bmatrix} 3-2i & -2-5i \\ 5+7i & -12i \\ 8i & 7+4i \end{bmatrix}
\end{equation*}

We can also perform the transpose operation first and then take the complex conjugate of the resulting matrix, i.e., \(A ^ H=[\overline{A}] ^ T=\overline{[A ^ T]}\).

The conjugate transpose is sometimes also denoted as \(A ^ *\) or \(A^\dagger\).

Diagonal Matrix

A square matrix is said to be a Diagonal Matrix if all the non-diagonal or off-diagonal elements(elements other than the principal diagonal of the matrix) are zero.

Diagonal Matrix

Diagonal Matrices

\begin{equation*} C = \begin{bmatrix} 4 & 0 & 0\\ 0 & 5 & 0 \\ 0 & 0 & -3
\end{bmatrix} \end{equation*}

Note: The diagonal of a square matrix starting from the top-left corner to the bottom-right corner is called the Principal Diagonal.

Every singleton matrix is a diagonal matrix.

Scalar Matrix

A diagonal matrix is said to be a Scalar Matrix if all the diagonal elements have same non-zero value.

\begin{equation*} A = \begin{bmatrix} -3 & 0 \\ 0 & -3 \end{bmatrix} \, \, \,
\, \, \, and \, \, \, \, \, \, \, \, B = \begin{bmatrix} 8 & 0 & 0\\ 0 & 8 &
0\\ 0 & 0 & 8 \end{bmatrix} \end{equation*}

Identity or Unit Matrix

If all the elements in the principal diagonal of a diagonal matrix are same and has a value ‘one’, then the matrix is called Identity or Unit Matrix. An identity matrix of order n is denoted as \(I_n\).

\begin{equation*} I_3 = \begin{bmatrix} 1 & 0 & 0\\ 0 & 1 & 0\\ 0 & 0 & 1
\end{bmatrix} \end{equation*}

The identity matrix is a special case of scalar matrix, and scalar matrix is a special case of a diagonal matrix.

That means every identity matrix is a scalar matrix, every scalar matrix is a diagonal matrix, and every diagonal matrix is a square matrix. The converse is not true.

Triangular Matrix

The matrix is said to be a Triangular Matrix if all the elements on one side of the diagonal of a square matrix are ‘zero’.

Upper Triangular Matrix

A square matrix with all the elements below the principal diagonal as zeros is called a Upper Triangular Matrix.

Upper Triangular Matrix

Upper Triangular Matrices

\begin{equation*} P = \begin{bmatrix} 5 & 2 & -4\\ 0 & -3 & 6\\ 0 & 0 & 8
\end{bmatrix} \end{equation*}

Lower Triangular Matrix

A square matrix with all the elements above the principal diagonal as zeros is called a Lower Triangular Matrix.

Lower Triangular Matrix

Lower Triangular Matrices

\begin{equation*} Q = \begin{bmatrix} 6 & 0 & 0\\ 11 & 2 & 0\\ -5 & 3 & 9
\end{bmatrix} \end{equation*}

Note: To avoid confusion, remember the name by observing the side on which the non-zero elements are present.

Strictly Triangular Matrix

A square matrix is said to be a Strictly Triangular Matrix if all the principal diagonal elements are ‘zero’.

Strictly Triangular Matrix

Strictly Triangular Matrices

\begin{equation*} A = \begin{bmatrix} 0 & 5 & -1\\ 8 & 0 & 7\\ 2 & 12 & 0
\end{bmatrix} \end{equation*}

Symmetric Matrix

A square matrix is said to be a Symmetric Matrix if the transpose of a matrix is equal to the original matrix, i.e. it satisfies the condition \(A ^ T=A\).

\begin{equation*} A = \begin{bmatrix} 2 & -5 & 8\\ -5 & 3 & 6\\ 8 & 6 & 1
\end{bmatrix} \end{equation*}

A symmetric matrix is always a square matrix. The elements are symmetric about the principal diagonal.

Skew-symmetric Matrix

When the transpose of a square matrix is equal to the negative of the original matrix, then the matrix is called Skew-symmetric Matrix. It satisfies the condition \(A ^ T=-A\).

The principal diagonal elements of the skew-symmetric matrix are zeros, i.e. a skew-symmetric matrix is always a strictly triagular matrix.

\begin{equation*} A = \begin{bmatrix} 0 & -2 & 11\\ 2 & 0 & 5\\ -11 & -5 & 0
\end{bmatrix} \end{equation*}

Similar to the symmetric matrix, only a square matrix can be skew-symmetric.

Involutory Matrix

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\).

\begin{equation*} A = \begin{bmatrix} 1 & 0\\ 0 & -1 \end{bmatrix} \, \, \, \,
\, \, and \, \, \, \, \, \, \, \, B = \begin{bmatrix} -5 & -8 & 0\\ 3 & 5 &
0\\ 1 & 2 & -1\\\end{bmatrix} \end{equation*}

Identity matrices are also involutory matrices(\(I ^ 2=I\)).

Idempotent Matrix

When a multiple of a square matrix gives the original matrix, then that matrix is called an Idempotent Matrix, i.e. \(A ^ 2=A\).

\begin{equation*} A = \begin{bmatrix} 3 & -6\\ 1 & -2 \end{bmatrix} \, \, \,
\, \, \, and \, \, \, \, \, \, \, \, B = \begin{bmatrix} 2 & -2 & -4\\ -1 & 3
& 4\\ 1 & -2 & -3\\\end{bmatrix} \end{equation*}

Identity matrices are also the idempotent matrices(\(I ^ 2=I\)).

Nilpotent Matrix

A square matrix \(N\) is a Nilpotent matrix when there exists a multiple of matrix for which the result is null or zero matrix , i.e. \(A^k = 0\), where k is called the index of nilpotent matrix.

\begin{equation*} N = \begin{bmatrix} 2 & -1\\ 4 & -2 \end{bmatrix} \, \, \,
\, \, \, and \, \, \, \, \, \, \, \, N = \begin{bmatrix} 5 & -3 & 2\\ 15 & -9
& 6\\ 10 & -6 & 4\\\end{bmatrix} \end{equation*}

Both examples have the index of nilpotence 2.

Orthogonal Matrix

A square matrix is said to be an Orthogonal Matrix if the matrix multiplied by the transpose results in the an identity matrix , i.e. \(PP^T = P^{T}P = I\).

\begin{equation*} P = \begin{bmatrix} -1 & 0\\ 0 & -1 \end{bmatrix} \, \, \,
\, \, \, and \, \, \, \, \, \, \, \, Q = \begin{bmatrix} 0 & -1 & 0\\ 1 & 0 &
0\\ 0 & 0 & -1 \end{bmatrix} \end{equation*}

Rows and columns of the orthogonal matrix are orthogonal unit vectors (also called orthonormal vectors).

Unitary Matrix

A square complex matrix is said to be an Unitary matrix if the matrix multiplied by its conjugate transpose results in an identity matrix , \(UU^H = U^{H}U = I\).

\begin{equation*} U1 = \begin{bmatrix} cosh(\alpha) & -i\, sinh(\alpha)\\ i\,
sinh(\alpha) & cosh(\alpha) \end{bmatrix} \, \, \, \, \, \, and \, \, \, \, \,
\, \, \, U2 = \frac{1}{2} \begin{bmatrix} 1+i & 1-i \\ 1-i & 1+i \end{bmatrix}
\end{equation*}

A real-valued orthogonal matrix is analogous to the unitary matrix.

Types of Matrices using Python

As you are now familiar with different types of matrices, let’s see how we can create these matrices using the NumPy array and different functions available in the NumPy library. We will also create functions to check whether the given matrix is of a particular type.

Before we start, you need to have the Python and the NumPy library installed on your computer.

Installing NumPy

The best way to get the NumPy library is to use the Anaconda distribution of Python. This distribution comes with most of the libraries required for scientific computing pre-installed, including NumPy.

If you have python already installed, you can use the Python package installer called pip .

pip install numpy

Check the article on setting up Python for scientific computing for more details.

I will recommend you to use Jupyter Notebook for this tutorial. Copy and paste the code in Jupyter notebook cell and press ctrl+Enter for Windows or cmd(⌘)+Enter for mac to run the code.

Creating a Matrix

To use the NumPy library, we first need to import it along with the linear algebra module using:

import numpy as np

Here np is called alias of NumPy. Aliasing is used to avoid typing numpy every time we use the function from the NumPy library.

There are multiple ways to initialize a NumPy array. The most straightforward way is to use the array function from the NumPy library. This function takes a list or a tuple as an input to create a NumPy array or a matrix.

To create a 2-dimensional array or matrix, we need to provide a list of lists, also called as nested lists. Here, each nested list represents the elements of each row of a matrix. For example

A = np.array([[5, 3, 58], [-4, 23, 11], [34, 2, -67]])
print(A)

Output:

[[5 358]
[-42311]
[34 2 - 67]]

We can use numpy.shape() function to get the dimension or order of a matrix. It returns a tuple containing the number of rows(m) and the number of columns(n) of a matrix.

np.shape(A)

Output:

(3, 3)

Let’s use Python’s unpacking functionality to save the number of rows and columns in different variables.

(m, n) = np.shape(A)
print(f'Number of rows in matrix A: {m}')
print(f'Number of columns in matrix A: {n}')

Output:

Number of rows in matrix A: 3
Number of columns in matrix A: 3

numpy.size() function gives us the total number of elements in the array. The number of elements can also be calculated by multiplying the number of rows with the number of columns.

Additionally, to know whether the array is 1-dimensional, 2-dimensional or n-dimensional, we can use numpy.ndim() function.

s = np.size(A)
print(f'Number of elements in the matrix: {s}')
d = np.ndim(A)# First method
d = A.ndim# Second method
print(f'The matrix is {d}-dimensional')

Output:

Number of elements in the matrix: 9
The matrix is 2-dimensional

Let’s first define a function to print whether the given matrix is of a certain type. This function will come in handy as we start creating functions for checking if a given matrix is of certian type.

def print_matrix_type(func, matrix, matrix_type):
if func(matrix):
print(matrix_type)
else:
print("--")

Don’t wory if it doesn’t make sense right now, we will see the use of this printing function soon.

Singleton Matrix

We input a list containing a single element to create the Singleton Matrix. One thing to note here is Python uses j to represent the complex number instead of i .

a = np.array([-2])
b = np.array([100])
c = np.array([1j])
print(a, b, c)

Output:

[-2][100][0.+1.j]

Now, let’s define a function to check if the matrix is a singleton matrix. This check can be performed by finding out whether the number of elements in the matrix is equal to one.

def is_singleton(A):
return np.size(A) == 1
print_matrix_type(is_singleton, a, "Singleton Matrix")
print_matrix_type(is_singleton, A, "Singleton Matrix")

Output:

Singleton Matrix
--

Notice, here we are using the print_matrix_type() function for printing whether the matrix is a singleton matrix or not.

Row Matrix

We can create the row matrix by using a 1-dimensional list or tuple as an input to numpy.array() function. Another way is to use the numpy.arange(start, stop, step) function, where the start is 0 and the step is 1 by default if you don’t specify.

A1 = np.array([4, 7, 2]) # Using list
A2 = np.array((4, 7, 2))# Using tuple
A3 = np.arange(1, 10, 3)# Using arange function
print('Matrix A1: ')
print(A1)
print('Matrix A3: ')
print(A3)
print('Shape of Matrix A1: ')
print(np.shape(A1))

Output:

Matrix A1:
[4 7 2]
Matrix A3:
[1 4 7]
Shape of Matrix A1:
(3,)

Function for testing whether the matrix is a row matrix, can be defined by checking if the number of elements in the tuple returned from the numpy.shape() function is one and the size of the matrix is greater than one.

def is_row(A):
m = np.shape(A)[0]
p = np.size(np.shape(A))
s = np.size(A)
return (p == 1 or m == 1) and s > 1
print_matrix_type(is_row, A1, "Row Matrix")
A = np.array([[5, 3, 58], [-4, 23, 11], [34, 2, -67]])
print_matrix_type(is_row, A, "Row Matrix")

Output:

Row Matrix
--

Technically a singleton matrix is also of a type row, column, square matrix, but we will not consider this case to avoid confusion.

Column Matrix

There are two ways we can create a column matrix. The first way is to create a list with nested lists containing only one element or the second way is to change the shape of a row matrix to create a column matrix.

B1 = np.array([[5], [14], [52], [-8]])
B2 = np.array([5, 14, 52, -8])
B2.shape = (4, 1)
B3 = np.reshape([5, 14, 52, -8], (4, 1))
print('Matrix B1: ')
print(B1)

Output:

Matrix B1:
[[5]
 [14]
 [52]
 [-8]]

The test function for the column matrix can be defined by finding if the number of rows is greater than one (m >1) and the number of columns is equal to one(n=1).

def is_column(A):
(m, n) = np.shape(A)
return m > 1 and n == 1
print_matrix_type(is_column, B1, "Column Matrix")
A = np.array([[5, 3, 58], [-4, 23, 11], [34, 2, -67]])
print_matrix_type(is_column, A, "Column Matrix")

Output:

Column Matrix
--

Row and column matrices are also called row and column vectors and 1-dimensional matrices.

Rectangular Matrix

A Rectangular Matrix can be created using numpy.array() function, same as previous examples.

P = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
Q = np.array([[7, 63, -34], [12, 57, 83], [-75, 8, 49], [38, 45, 11]])
print('Matrix P:')
print(P)
print('Matrix Q:')
print(Q)

Output:

Matrix P:
[[1 2 3 4]
 [5 6 7 8]]
Matrix Q:
[[763 - 34]
 [125783]
 [-75 849]
 [384511]]

Now, let’s define the test function by checking if the number of rows is equal to the number of columns(m ≠ n).

def is_rect(A):
(m, n) = np.shape(A)
return not m == n
print_matrix_type(is_rect, P, "Rectangular Matrix")
print_matrix_type(is_rect, Q, "Rectangular Matrix")
A = np.array([[5, 3, 58], [-4, 23, 11], [34, 2, -67]])
print_matrix_type(is_rect, A, "Rectangular Matrix")

Output:

Rectangular Matrix
Rectangular Matrix
--

Square Matrix

We can create a Square Matrix by our usual method. There are additional methods to create special types of square matrices. Let’s go through them one by one.

A = np.array([[21, 72, 34], [94, 55, 67], [37, 83, 9]])
B = np.ones((3, 3))
C = np.full((2, 2), 3)
D = np.random.random((3, 3))
print('Matrix A:')
print(A)
print('Matrix B:')
print(B)
print('Matrix C:')
print(C)
print('Matrix D:')
print(D)

Output:

Matrix A:
[[21 72 34]
 [94 55 67]
 [37 839]]
Matrix B:
[[1. 1. 1.]
 [1. 1. 1.]
 [1. 1. 1.]]
Matrix C:
[[3 3]
 [3 3]]
Matrix D:
[[0.72740069 0.16242261 0.66304855]
 [0.19086942 0.87600172 0.80589997]
 [0.51849749 0.83038955 0.86511938]]

Matrix B is matrix of ones all the elements of the matrix C have the same value while the matrix D is a random matrix with values varying from 0 to 1.

The condition for the test function is whether the number of rows equal to the number of columns, i.e., m = n.

def is_square(A):
(m, n) = np.shape(A)
return m == n
print_matrix_type(is_square, B, "Square Matrix")
is_square(B)
P = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
print_matrix_type(is_square, P, "Square Matrix")

Output:

 Square Matrix 
--

Technically, the square matrix is a special case of a rectangular matrix, but we will treat them as individual types.

Null Matrix

numpy.zeros() function makes it very easy to create a null matrix. Null matrix can be of a type row, column, rectangular or square matrix.

O1 = np.zeros(5)
O2 = np.zeros((2, 3))
O3 = np.zeros((3, 3))
print('Matrix O1:')
print(O1)
print('Matrix O2:')
print(O2)
print('Matrix O3:')
print(O3)

Output:

Matrix O1:
[0. 0. 0. 0. 0.]
Matrix O2:
[[0. 0. 0.]
 [0. 0. 0.]]
Matrix O3:
[[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]]

Now let’s check for the null matrix using the numpy.any() function. This function checks if there are any non-zero elements and returns false for a null matrix.

def is_null(A):
return not np.any(A)
print_matrix_type(is_null, O1, "Null Matrix")
A = np.array([[5, 3, 58], [-4, 23, 11], [34, 2, -67]])
print_matrix_type(is_null, A, "Null Matrix")

Output:

Null Matrix
--

Make sure you understand the use of not in the above function.

Real Matrix

All the previously created matrices except the singleton matrix \([0.+1.j]\) are real matrices. So let’s directly jump to our function.

There are two NumPy functions, one is numpy.isreal() and other is numpy.isrealobj() . The first one returns an array of the same dimensions as the original matrix containing only True and False values, representing whether each element is real or not.

The isrealobj() function returns only single boolean value ( True or False ) based on whether the matrix as a whole is a real matrix.

A = np.array([[1, 2.+1.j, 3], [4, 5, 6]])
print(np.isreal(A))
print('Matrix A is real:')
print(np.isrealobj(A))
B = np.array([1, 2, 3, 4])
print('Matrix B is real:')
print(np.isrealobj(B))

Output:

[[True FalseTrue]
[TrueTrueTrue]]
Matrix A is real:
False
Matrix B is real:
True

We will use numpy.isrealobj() for our test function.

def is_real(A):
return np.isrealobj(A)
L = np.array([[1.5, 3.6], [8.4, .7], [5.8, 2.9]])
print_matrix_type(is_real, L, "Real Matrix")
print_matrix_type(is_real, np.array([1j]), "Real Matrix")

Output:

Real Matrix
--

Complex Matrix

We can either create a Complex Matrix by using the list of complex numbers as an input to numpy.array function, or we can change the real-valued matrix to be a complex matrix.

K = np.array([[2-7j, 5-3j, 8+4j, -5j], [3j, 0, 7-9j, 8]])
M = np.array([[1, 2, 3], [4, 5, 6]], dtype=complex)
N = np.array([[5.6, 2.3], [7.4, 8.8]])
N = N.astype('complex128')
print('Matrix K:')
print(K)
print('Matrix M:')
print(M)
print('Matrix N:')
print(N)

Output:

Matrix K:
[[2.-7.j5.-3.j8.+4.j - 0.-5.j]
 [0.+3.j0.+0.j7.-9.j8.+0.j]]
Matrix M:
[[1.+0.j 2.+0.j 3.+0.j]
 [4.+0.j 5.+0.j 6.+0.j]]
Matrix N:
[[5.6+0.j 2.3+0.j]
 [7.4+0.j 8.8+0.j]]

Similar to the real matrix case, we have the numpy.iscomplexobj() function, which returns True if any of the matrix elements is a complex number.

def is_complex(A):
return np.iscomplexobj(A)
print_matrix_type(is_complex, K, "Complex Matrix")
A = np.array([[5, 3, 58], [-4, 23, 11], [34, 2, -67]])
print_matrix_type(is_complex, A, "Complex Matrix")

Output:

Complex Matrix
--

Conjugate Matrix

We can use the numpy.conjugate() function or a short alias, the numpy.conj() function to get the Conjugate Matrix of a given complex matrix.

K = np.array([[2-7j, 5-3j, 8+4j, -5j], [3j, 0, 7-9j, 8]])
K_bar = np.conj(K)
print('Complex Matrix:')
print(K)
print('Conjugate Matrix:')
print(K_bar)

Output:

Complex Matrix:
[[2.-7.j5.-3.j8.+4.j - 0.-5.j]
 [0.+3.j0.+0.j7.-9.j8.+0.j]]
Conjugate Matrix:
[[2.+7.j5.+3.j8.-4.j - 0.+5.j]
 [0.-3.j0.-0.j7.+9.j8.-0.j]]

As a conjugate matrix is defined for a particular complex matrix, we will not write a generalized function for this type of matrix.

Transpose of a Matrix

The numpy.transpose() function allows us to take the transpose of a matrix in three different ways.

A = np.array([[0.25, 0.5, 0.75, 1], [1.25, 1.5, 1.75, 2]])
A_T1 = np.transpose(A) # First Method
A_T2 = A.transpose() # Second Method
A_T3 = A.T # Shortcut Method
print('Matrix A')
print(A)
print('Transpose of A')
print(A_T1)

Output:

Matrix A:
[[0.25 0.50.75 1.]
 [1.25 1.51.75 2.]]
Transpose of A:
[[0.25 1.25]
 [0.51.5]
 [0.75 1.75]
 [1. 2.]]

Conjugate Transpose

To obtain the Conjugate Transpose of a given complex matrix, we have to perform two operations. We get the conjugate matrix by using the numpy.conj() function and take the transpose of the resulting matrix.

As mentioned before, we can change the sequence of these operations.

A = np.array([[3+2j, 5-7j, -8j], [-2+5j, 12j, 7-4j]])
A_H1 = np.conj(A.T) # First transpose, then conjugate
A_H2 = np.conj(A).T # First conjugate, then transpose
print('Matrix A:')
print(A)
print('Conjugate Transpose of A:')
print(A_H1)
print('Conjugate Transpose of A:')
print(A_H2)

Output:

Matrix A:
[[3. + 2.j5. - 7.j - 0. - 8.j]
 [-2. + 5.j0.+12.j7. - 4.j]]
Conjugate Transpose of A:
[[3. - 2.j - 2. - 5.j]
 [5. + 7.j0.-12.j]
 [-0. + 8.j7. + 4.j]]
Conjugate Transpose of A:
[[3. - 2.j - 2. - 5.j]
 [5. + 7.j0.-12.j]
 [-0. + 8.j7. + 4.j]]

Diagonal Matrix

There are multiple ways to create a Diagonal Matrix. One is to define the matrix using the usual numpy.array function. However, NumPy provides a special function to create a diagonal matrix, np.diag() , which takes a list of only the diagonal elements as an input.

C1 = np.array([[4, 0, 0], [0, 5, 0], [0, 0, -3]])
C2 = np.diag([4, 5, -3])
print('Matrix C1:')
print(C1)
print('Matrix C2:')
print(C2)

Output:

Matrix C1:
[[400]
 [050]
 [00 - 3]]
Matrix C2:
[[400]
 [050]
 [00 - 3]]

There is one more function available in the NumPy library i.e., numpy.diagonal() . This function returns the diagonal elements of a given matrix. Don’t confuse this with the numpy.diag() function.

A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print('Diagonal elements of matrix A: ')
print(np.diagonal(A)) # or print(A.diagonal())

Output:

Diagonal elements of matrix A:
[1 5 9]

We will use both these functions in our test function. We will see if the diagonal matrix created from the diagonal elements of the original matrix is equal to the original matrix. This is true only in the case of a diagonal matrix.

def is_diag(A):
return np.allclose(A, np.diag(np.diagonal(A)))
print_matrix_type(is_diag, C1, "Diagonal Matrix")
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print_matrix_type(is_diag, A, "Diagonal Matrix")

Output:

Diagonal Matrix
--

Scalar Matrix

As in the case of other types of matrices, there are multiple ways to create a Scalar Matrix. We can use the numpy.diag() function used previously, or we can fill the diagonal elements of a square null matrix with the same value using numpy.fill_diagonal() function.

S1 = np.diag([5, 5, 5])
S2 = np.zeros([3, 3], dtype='int32')
np.fill_diagonal(S2, 4)
print('Scalar Matrix S1: ')
print(S1)
print('Scalar Matrix S2: ')
print(S2)

Output:

Scalar Matrix S1:
[[5 0 0]
 [0 5 0]
 [0 0 5]]
Scalar Matrix S2:
[[4 0 0]
 [0 4 0]
 [0 0 4]]

As the scalar matrix is a special case of a diagonal matrix, we will first check if the matrix is diagonal and then check if all the diagonal elements are the same.

def is_scalar(A):
return np.allclose(A, np.diag(np.diagonal(A))) and \
 (len(np.unique(np.diagonal(A))) == 1)
print_matrix_type(is_scalar, S1, "Scalar Matrix")
C2 = np.diag([4, 5, -3])
print_matrix_type(is_scalar, C2, "Scalar Matrix")

Output:

Scalar Matrix
--

Identity or Unit Matrix

Next up is an Identity or Unit Matrix(\(I\)), which is a special case of scalar matrix with all the diagonal elements as one.

The identity matrix is analogous to a number 1 in the case of numerical operations. As any number multiplied by 1 gives the same number, a matrix remains the same after it is multiplied by an identity matrix.

Apart from the ways mentioned before to create a scalar and diagonal matrix, the NumPy library provides two special functions to create the identity matrix. One is numpy.identity() and other is numpy.eye() where the later provides additional options to create a matrix with ones at the offset diagonal elements.

I3 = np.identity(3)
I4 = np.eye(4) # Similar to MATLAB
print('3rd order Identity Matrix')
print(I3)
print('4th order Identity Matrix')
print(I4)

Output:

3rd order Identity Matrix
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
4th order Identity Matrix
[[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 1. 0.]
 [0. 0. 0. 1.]]

Now, let’s use the same check as the scalar matrix and additionally see if the unique diagonal element is ‘one’ to determine whether the given matrix is an identity matrix.

def is_identity(A):
m = np.shape(A)[0]
return np.allclose(A, np.diag(np.diagonal(A))) and \
 (len(np.unique(np.diagonal(A))) == 1) and \
A[0, 0] == 1
print_matrix_type(is_identity, I3, "Identity Matrix")
S1 = np.diag([5, 5, 5])
print_matrix_type(is_identity, S1, "Identity Matrix")

Output:

Identity Matrix
--

I’m sure there are multiple ways to perform this check, but we will follow the above method as it builds upon the previous understanding from diagonal and scalar matrix types.

Triangular Matrix

The NumPy functions numpy.triu() and numpy.tril() can be used to extract the upper and lower triangular matrices from a given matrix, respectively.

A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
UT = np.triu(A)# Extract Upper Triangular Matrix
LT = np.tril(A)# Extract Lower Triangular Matrix
print('Upper Triangular Matrix: ')
print(UT)
print('Lower Triangular Matrix: ')
print(LT)

Output:

Upper Triangular Matrix:
[[1 2 3]
 [0 5 6]
 [0 0 9]]
Lower Triangular Matrix:
[[1 0 0]
 [4 5 0]
 [7 8 9]]

Let’s check whether the given matrix is triangular and if it is, then check for upper or lower triangular case.

def is_tri(A):
if np.allclose(A, np.triu(A)):
return is_upper_tri(A) or is_lower_tri
def is_upper_tri(A):
return np.allclose(A, np.triu(A))
def is_lower_tri(A):
return np.allclose(A, np.tril(A))
print_matrix_type(is_upper_tri, UT, "Upper Trianglular Matrix")
print_matrix_type(is_lowtri, LT, "Lower Trianglular Matrix")
print_matrix_type(is_tri, LT, "Trianglular Matrix")
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print_matrix_type(is_tri, A, "Trianglular Matrix")

Output:

Upper Triangular Matrix
Lower Triangular Matrix
--

Strictly Triangular Matrix

We can convert any square matrix to a Strictly Triangular Matrix using the numpy.fill_diagonal() function with zero as a second argument.

ST = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
np.fill_diagonal(ST, 0)
print('Strictly Triangular Matrix')
print(ST)

Output:

Strictly Triangular Matrix
[[0 2 3]
 [4 0 6]
 [7 8 0]]

Checking for strict triangularity is similar to the triangular case. Let’s see if the strictly triangular matrix of a given matrix equal to that matrix.

As the numpy.fill_diagonal() function directly operates on the array, we need to create a copy of the original matrix for comparison.

def is_strict_tri(A):
B = np.copy(A)
np.fill_diagonal(B, 0)
return np.allclose(A, B)
print_matrix_type(is_strict_tri, ST, "Strictly Trianglular Matrix")
P = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print_matrix_type(is_strict_tri, P, "Strictly Trianglular Matrix")

Output:

Strictly Triangular Matrix
--

Symmetric Matrix

Symmetric Matrix has to be a square matrix and has a symmetry about the principal diagonal of the matrix.

SM = np.array([[2, -5, 8], [-5, 3, 6], [8, 6, 1]])
print('Matrix SM: ')
print(SM)

Output:

Matrix SM:
[[2 - 58]
 [-536]
 [861]]

Symmetry of a matrix can be found by checking the equality of the matrix and the transpose of that matrix.

def is_symmetric(A):
return np.allclose(A, A.T)
print_matrix_type(is_symmetric, SM, "Symmetric Matrix")
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print_matrix_type(is_symmetric, A, "Symmetric Matrix")

Output:

Symmetric Matrix
--

Skew-symmetric Matrix

Similar to the symmetric matrix, only a square matrix can be Skew-symmetric. Elements on one side of the principal diagonal are equal in value, having opposite signs with respect to the elements on the other side.

SSM = np.array([[0, -2, 11], [2, 0, 5], [-11, -5, 0]])
print('Matrix SSM: ')
print(SSM)

Output:

Matrix SSM:
[[0 - 211]
 [2 0 5]
 [-11 - 5 0]]

Let’s define the test function by checking the equality of the negative of a matrix and its transpose.

def is_skew_symc(A):
return np.allclose(-A, A.T)
print_matrix_type(is_skew_symc, SSM, "Skew-symmetric Matrix")
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print_matrix_type(is_skew_symc, A, "Skew-symmetric Matrix")

Output:

Skew-symmetric Matrix
--

Involutory Matrix

It is a special type of matrix. We can use the matrix multiplication function numpy.matmul() or the matrix multiplication operator @ to get the square of a matrix. Also, we can use the matrix power function numpy.linalg.matrix_power() from the linalg module of NumPy library.

B = np.array([[-5, -8, 0], [3, 5, 0], [1, 2, -1]])
B_sq1 = np.matmul(B, B)
B_sq2 = np.linalg.matrix_power(B, 2)
print('Matrix B:')
print(B)
print('Matrix B_sq1:')
print(B_sq1)

Output:

Matrix B:
[[-5 - 80]
 [350]
 [12 - 1]]
Matrix B_sq1:
[[1 0 0]
 [0 1 0]
 [0 0 1]]

The test function can be defined by checking if the square of a matrix is an identity matrix of the same order. The identity matrix is created using the numpy.eye() function.

def is_involutory(A):
(m, n) = np.shape(A)
A_sq = A @ A
return np.allclose(A_sq, np.eye(m))
print_matrix_type(is_involutory, B, "Involutory Matrix")
P = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print_matrix_type(is_involutory,P, "Involutory Matrix")

Output:

Involutory Matrix
--

We can also say that all the involutory matrices are square roots of the identity matrices of the same order.

Idempotent Matrix

We will get the square of a matrix by using the numpy.matmul() function as it is faster than the power function.

B = np.array([[2, -2, -4], [-1, 3, 4], [1, -2, -3]])
B_sq = np.matmul(B, B)
print('Matrix B:')
print(B)
print('Square of Matrix B:')
print(B_sq)

Output:

Matrix B:
[[2 - 2 - 4]
 [-134]
 [1 - 2 - 3]]
Square of Matrix B:
[[2 - 2 - 4]
 [-134]
 [1 - 2 - 3]]

The test function checks if the square of a matrix is equal to the original matrix. We can use the matrix multiplication function numpy.matmul() or the matrix multiplication operator @ to get the square of a matrix. Also, we can use the matrix power function numpy.linalg.matrix_power() from the linalg module of NumPy library.

def is_idempotent(A):
A_sq = A @ A
return np.allclose(A, A_sq)
print_matrix_type(is_idempotent, B, "Idempotent Matrix")
P = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print_matrix_type(is_idempotent, P, "Idempotent Matrix")

Output:

Idempotent Matrix
--

Only a square matrix can be an idempotent matrix.

Nilpotent Matrix

Only a square matrix can be a Nilpotent Matrix. We will get the power of a matrix using numpy.linalg.matrix_power() function. The power of a matrix for which the result is a null or zero matrix is called the index of a Nilpotent Matrix denoted by k .

N1 = np.array([[2, -1], [4, -2]])
N1_k = np.linalg.matrix_power(N1, 2)
N2 = np.array([[5, -3, 2], [15, -9, 6], [10, -6, 4]])
N2_k = np.linalg.matrix_power(N2, 2)
print('Matrix N2:')
print(N2)
print('Square of Matrix N2:')
print(N2_k)

Output:

Matrix N2:
[[5 - 32]
 [15 - 96]
 [10 - 64]]
Square of Matrix N2:
[[0 0 0]
 [0 0 0]
 [0 0 0]]

A nilpotent matrix must have an index less than or equal to the number of rows (order of matrix). The test function checks for the equality of matrix power with the null matrix of the same order.

def is_nilpotent(A):
m = np.shape(A)[0]
Om = np.zeros([m, m])
A_pow = A
for power in range(1, m+1):
if np.allclose(Om, A_pow):
return True
A_pow = A_pow @ A
return False

def nilpotence_index(A):
m = np.shape(A)[0]
O = np.zeros([m,m])
A_pow = A
for power in range(1,m+1):
if np.allclose(O,A_pow):
return power
A_pow = A_pow @ A
print('Input is not a Nilpotent Matrix')
print_matrix_type(is_nilpotent, N2, "Nilpotent Matrix")
print('Nilpotence Index: ' + str(nilpotence_index(N2)))
N3 = np.array([[0, 1, 0], [0, 0, 1], [0, 0, 0]])
print_matrix_type(is_nilpotent, N3, "Nilpotent Matrix")
print('Nilpotence Index: ' + str(nilpotence_index(N3)))
P = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print_matrix_type(is_nilpotent, P, "Nilpotent Matrix")

Output:

Nilpotent Matrix
Nilpotence Index: 2
Nilpotent Matrix
Nilpotence Index: 3
--

Orthogonal Matrix

The condition for Orthogonal Matrix can also be presented as a square matrix for which the transpose of a matrix is equal to its inverse(\(A ^ T=A{-1}\)).

The test function checks whether the multiplication of a matrix and its transpose results in an identity matrix of the same order.

def is_orthogonal(A):
m = np.shape(A)[0]
return np.allclose(A @ A.T, np.eye(m))
Q = np.array([[0, -1, 0], [1, 0, 0], [0, 0, -1]])
print('Matrix Q:')
print(Q)
print_matrix_type(is_orthogonal, Q, "Orthogonal Matrix")
B = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print_matrix_type(is_orthogonal, B, "Orthogonal Matrix")

Output:

Matrix Q:
[[0 - 10]
 [100]
 [00 - 1]]
Orthogonal Matrix
--

The identity matrix is also an orthogonal matrix.

Unitary Matrix

We can obtain the conjugate transpose of a matrix by taking the complex conjugate of the transpose of a complex matrix using numpy.conj() .

def is_unitary(A):
m = np.shape(A)[0]
return np.allclose(A @ np.conj(A.T),np.eye(m))
U = np.array([[0.5+0.5j, 0.5-0.5j], [0.5-0.5j, 0.5+0.5j]])
print('Matrix U:')
print(U)
print_matrix_type(is_unitary, U, "Unitary Matrix")
K = np.array([[2-7j, 5-3j, 8+4j, -5j], [3j, 0, 7-9j, 8]])
print_matrix_type(is_unitary, K, "Unitary Matrix")

Output:

Matrix U:
[[0.5+0.5j 0.5-0.5j]
 [0.5-0.5j 0.5+0.5j]]
Unitary Matrix
--

Now let’s combine all the functions we have defined previously to create a program that will print a report of all the types of matrices the given matrix satisfies.

We can create a module containing all these functions and import them when required.

import numpy as np

def check_matrix_type(A):
    if A.ndim == 0:
        print('You have entered a scalar value (a zero-dimensional matrix).')
    elif np.shape(A)[0] == 0:
        print('Empty Matrix')
    else:
        d = A.ndim
        if is_real(A):
            print('Real Matrix')
        if is_complex(A):
            print('Complex Matrix')

        if is_null(A):
            print('Zero or Null Matrix')
        if is_row(A):
            print('Row Matrix')

        if is_singleton(A):
            print('Singleton Matrix')
        elif d == 2 and np.shape(A)[0] != 1:
            if is_column(A):
                print('Column Matrix')
            else:
                if is_rect(A):
                    print('Rectangular Matrix')
                # Many types require the matrix to be a Square Matrix
                if is_square(A) and np.any(A):
                    print('Square Matrix')
                    if is_diag(A):
                        print('Diagonal Matrix')
                        if is_scalar(A):
                            print('Scalar Matrix')
                            if is_identity(A):
                                m = np.shape(A)[0]
                                print(f'Identity Matrix of order {m}')
                    else:
                        if is_upper_tri(A):
                            print('Upper Triangular Matrix')
                        if is_lower_tri(A):
                            print('Lower Triangular Matrix')
                        if is_strict_tri(A):
                            print('Strictly Triangular Matrix')

                    if is_symmetric(A):
                        print('Symmetric Matrix')
                    elif is_skew_symc(A):
                        print('Skew-symmetric Matrix')

                    if is_involutory(A):
                        print('Involutory Matrix')
                    if is_idempotent(A):
                        print('Idempotent Matrix')
                    if is_nilpotent(A):
                        k = nilpotence_index(A)
                        print(f'Nilpotent Matrix with index {k}')
                    if is_orthogonal(A):
                        print('Orthogonal Matrix')
                    if is_complex(A):
                        if is_unitary(A):
                            print('Unitary Matrix')

# Functions for individual types of matrices
def is_singleton(A):
    return np.size(A) == 1

def is_row(A):
    return (np.size(np.shape(A)) == 1 or np.shape(A)[0] == 1) and np.size(A) > 1

def is_column(A):
    return np.shape(A)[0] > 1 and np.shape(A)[1] == 1

def is_rect(A):
    return not np.shape(A)[0] == np.shape(A)[1]

def is_square(A):
    return np.shape(A)[0] == np.shape(A)[1]

def is_null(A):
    return not np.any(A)

def is_real(A):
    return np.isrealobj(A)

def is_complex(A):
    return np.iscomplexobj(A)

def is_diag(A):
    return np.allclose(A, np.diag(np.diagonal(A)))

def is_scalar(A):
    return np.allclose(A, np.diag(np.diagonal(A))) and \
        len(np.unique(np.diagonal(A))) == 1

def is_identity(A):
    return np.allclose(A, np.diag(np.diagonal(A))) and \
        len(np.unique(np.diagonal(A))) == 1 and \
        A[0, 0] == 1

def is_upper_tri(A):
    return np.allclose(A, np.triu(A))

def is_lower_tri(A):
    return np.allclose(A, np.tril(A))

def is_strict_tri(A):
    B = np.copy(A)
    np.fill_diagonal(B, 0)
    return np.allclose(A, B)

def is_symmetric(A):
    return np.allclose(A, A.T)

def is_skew_symc(A):
    return np.allclose(-A, A.T)

def is_involutory(A):
    m = np.shape(A)[0]
    A_sq = A @ A
    return np.allclose(A_sq, np.eye(m))

def is_idempotent(A):
    A_sq = A @ A
    return np.allclose(A, A_sq)

def is_nilpotent(A):
    m = np.shape(A)[0]
    O = np.zeros([m, m])
    A_pow = A
    for power in range(1, m+1):
        if np.allclose(O, A_pow):
            return True
        A_pow = A_pow @ A
    return False

def nilpotence_index(A):
    m = np.shape(A)[0]
    O = np.zeros([m, m])
    A_pow = A
    for power in range(1, m+1):
        if np.allclose(O, A_pow):
            return power
        A_pow = A_pow @ A
    print('Input is not a Nilpotent Matrix')

def is_orthogonal(A):
    m = np.shape(A)[0]
    return np.allclose(A @ A.T, np.eye(m))

def is_unitary(A):
    m = np.shape(A)[0]
    return np.allclose(A @ np.conj(A.T), np.eye(m))

Copy and save this code in a Python file, preferably named matrix_types.py . This is our module, which we can import and use.

Open your command prompt or terminal and navigate to the location where the above file is saved. Now type Python in terminal to start the Python REPL(Read-Evaluate-Print-Loop) in terminal window. (You will see ‘>>>’ at the terminal if Python is installed correctly and the path is added to the ‘Environment variables’.)

We can import the module and use the functions as follows:

import matrix_types as mt
X = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
mt.check_matrix_type(X)

Output:

Real Matrix
Square Matrix
Diagonal Matrix
Identity Matrix of order 3
Scalar Matrix
Symmetric Matrix
Involutory Matrix
Idempotent Matrix
Orthogonal Matrix

We can also use individual functions to check if the given matrix is of a particular type.

mt.is_identity(X)

Output:


True

Did you find this article useful? Please comment and share it with your friends. Which types of matrices are missing from the above list?

Leave a Reply