How to do QR Decomposition in Python with Numpy

QR decomposition, also known as QR factorization, is a method for decomposing a matrix into the product of an orthogonal matrix and an upper-triangular matrix. It is a useful tool for solving systems of linear equations, computing the inverse of a matrix, and computing the singular value decomposition (SVD) of a matrix.

In this blog post, we will learn how to perform QR decomposition using the NumPy library in Python. We will start with by introducing the basic concept of QR decomposition and its applications, and then show how to use Numpy’s linaalg.qr() function factorize/decompse with an example.

What is QR decomposition?

Given a matrix A, the QR decomposition is a way of decomposing or factorizing the matrix A into the product of two matrices Q and R such that:

A = QR

Here Q is an orthogonal matrix and R is an upper-triangular matrix.

An orthogonal matrix is a matrix whose columns and rows are orthonormal, which means that they are unit vectors (vectors with a length of 1) that are perpendicular to each other. An upper-triangular matrix is a matrix that has all of its elements below the main diagonal equal to zero.

QR decomposition has several important properties that make it a useful tool for various matrix operations. For example, Q is an invertible matrix, which means that it has a well-defined inverse. This property makes QR decomposition useful for solving systems of linear equations.

NumPy’s linalg module provides a function called qr() that can be used to perform QR decomposition on a given matrix.

Here is an example of how to use the linalg.qr() function to decompose a matrix A into Q and R:

import numpy as np

Here is the basic syntax of linalg.qr() function in Numpy. In addition to the input matrix, linalg.qr() function takes the argument mode. The mode argument determines what information will be returned by the function and by default it is set to “reduced”.

linalg.qr(a, mode='reduced')

Decomposing a 3×3 matrix with QR decomposition in Python

Let us consider an example matrix to decompose using QR factorization method.

A = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])

We will is Numpy’s linalg.qr() function to decompose the matrix A into the matrices Q and R. The qr() function returns the matrices Q and R as a tuple, so we can unpack them into separate variables using tuple unpacking.

The Q matrix returned by the qr() function is an orthogonal matrix, and the R matrix is an upper-triangular matrix. We can verify this by printing the matrices and checking that the rows of Q are orthonormal and that the R matrix has all of its elements below the main diagonal equal to zero.

# QR decomposition in Python
Q, R = np.linalg.qr(A)
print(Q)

[[-0.12309149  0.90453403  0.40824829]
 [-0.49236596  0.30151134 -0.81649658]
 [-0.86164044 -0.30151134  0.40824829]]

Verifying Q’s orthogonal property

The matrix Q is an orthogonal matrix. An orthogonal matrix has a number of special properties. Here we check one such property, i.e. dot product of an orthogonal matrix and its transpose give us identity matrix with ones along the diagonal and zeros everywhere else.

np.dot(Q, Q.T)

array([[1.00000000e+00, 1.70541764e-16, 1.71911902e-16],
       [1.70541764e-16, 1.00000000e+00, 8.19505222e-17],
       [1.71911902e-16, 8.19505222e-17, 1.00000000e+00]])
print(R)

[[-8.12403840e+00 -9.60113630e+00 -1.10782342e+01]
 [ 0.00000000e+00  9.04534034e-01  1.80906807e+00]
 [ 0.00000000e+00  0.00000000e+00 -8.88178420e-16]]

And we can also verify the product of Q and R give us the original matrix A.

np.dot(Q,R)

array([[1., 2., 3.],
       [4., 5., 6.],
       [7., 8., 9.]])