Detailed Explanation of QR Decomposition by Givens Rotation

Anthony Kwok
7 min readMar 20, 2023

--

Source: Image by the author.

Episode 1: QR Decomposition by Classical Gram-Schmidt (CGS)and modified Gram-Schmidt (MGS)

Episode 2: QR Decomposition by Householder Transformation

Episode 3: QR Decomposition by Givens Rotation

In this episode (episode 3), we will go through the Givens Rotation method to compute QR decomposition. Givens rotations are named after Wallace Givens.

If you are unfamiliar with QR decomposition, these are some key points you need to know before we start.

Q” in QR decomposition represents an orthogonal matrix, which means:

Matrix Q: Orthogonal Matrix. Source: Image by the author.

Remarks: for an orthogonal matrix, the dot product of any 2 column vectors in orthogonal matrix must be equal to 0

R” in QR decomposition represents right (upper) triangular matrix, which means:

Matrix R: Right (Upper) Triangular Matrix. Source: Image by the author.

Therefore, QR decomposition is sometimes called QU decomposition.

Some Characteristics of QR Decomposition

  1. QR Decomposition always exists, but may not be unique
  2. If the determinant of matrix A is not 0 and all diagonal entries of R > 0, then this QR decomposition is unique.
  3. There are two types of QR decomposition:
    a. Full QR Decomposition
    b. Reduced QR Decomposition

For simplicity, we will only include full QR decomposition for square matrix here, whereas matrix A is full rank (i.e. All columns are linearly independent).

QR decomposition is also applicable for m x n (m-by-n) matrixes, where mn.
In that case, Q will be a m x m (m-by-m) matrix and R will be m x n (m-by-n) matrix.

4 Methods to perform QR decomposition

  1. (Classical) Gram-Schmidt Process (CGS)
  2. Modified Gram-Schmidt Process (MGS)
  3. Household Transformation
  4. Givens Rotation

In this article, we will cover Givens Rotation.

Set-Up

Like the last two episodes, we will go through the steps of QR decomposition and implementation of QR decomposition by Givens Rotation with Python code.

We create a Python class called Matrix, which will be used in our example. First, we create a 3-by-3 Matrix A for our QR decomposition example.

# main.py
# Create the matrix A
A = Matrix(
n_row=3,
n_col=3,
two_d_array=[[2, -1, -2], [-4, 6, 3], [-4, -2, 8]],
)
Our Example. Source: Image by the author.

QR Decomposition by Givens Rotation

We assume you already know what vector projection is. If you do not, you may refer to medium.

Givens Rotation

In the method of Givens Rotation, similar to Gram-Schmidt and Householder Transformation, we try to decompose each column vector in A to a set of linear combinations of orthogonal vectors in Q.

Therefore, we will try to map each column to a set of orthogonal vectors.

Source: Image by the author.

Unlike Householder Transformation, we map the column vector to a set of orthogonal vectors by rotating it, instead of reflecting it. This is called the Givens Rotation method. Before going into our 3x3 matrix example, we will introduce the Matrix Rotation Concept with a 2x2 matrix rotation example, illustrated in both graphic and numeric perspective.

Matrix Rotation

In linear algebra, we can use Matrix to perform vector rotation. Here is an example of a 2-by-2 matrix rotation matrix.

By the definition of Trigonometry, in a circle with radius r (x_1), the coordinate of point P is defined as (r cosθ, r sinθ).

Definition of Trigonometry. Source: Image by the author.

If we re-write the radius on the x-axis (x_1) and point P (x_2) in a vector form,

Source: Image by the author

And the Rotation Matrix G is defined as,

Source: Image by the author.

This rotation matrix G is rotating the vector x_1 to x_2.

Source: Image by the author.

Similarly in quadrant II, by the definition of Trigonometry, in a circle with radius r (x_1), the coordinate of point P is defined as (-r sinθ, r cosθ).

Source: Image by the author.

If we re-write the radius on x-axis (x_1) and point P (x_2) in a vector form,

Source: Image by the author.

This rotation matrix G is rotating the vector x_1 to x_2.

Source: Image by the author.

You can also use a similar concept for quadrant III and quadrant IV, you will get the same result.

This is the rotation matrix G !!!

Source: Image by the author.

Example of Matrix Rotation

Example 1:

Example 1. Source: Image by the author.

Example 2:

Example 2. Source: Image by the author.

Example 3:

Example 3. Source: Image by the author.

I hope you would understand more about matrix rotation by the above example.

Noted that the above matrix rotation is performed on a 2-D plane.

Matrix Rotation Example with Our 3-by-3 Matrix

For a matrix with a higher dimension, we cannot rotate the vector on all dimensions. Therefore, we can only rotate two dimensions each time and fix all other dimensions.

Dimension of Matrix. Source: Image by the author.

For the rotation matrix G, the dimension of G is equal to the dimension of A (i.e. 3-by-3 matrix). We can construct the matrix G similar to the above example, which can be done by expanding the matrix G with a 2-dimension.

If you want to rotate the vector along the x-axis and z-axis, then we select the first and third columns and rows. Then put the (cosθ, -sinθ, sinθ, cosθ) into the 4 intersection positions respectively.

Rotation Matrix to rotate along the x-axis and z-axis (Fix the y-axis). Source: Image by the author.

If you want to rotate the vector along the x-axis and y-axis,

Rotation Matrix to rotate along the x-axis and y-axis (Fix the z-axis). Source: Image by the author.

If you want to rotate the vector along the y-axis and z-axis,

Rotation Matrix to rotate along the y-axis and z-axis (Fix the x-axis). Source: Image by the author.

This is how we can perform rotation on the matrix with higher dimensions.

QR Decomposition by Givens Rotation

Now, let’s get into our example and see how we can use Givens Rotation to perform QR decomposition.

In the first step, we define the G_1 Matrix to rotate the submatrix with columns 1 & 2 and rows 1 & 2. Then, multiply the G_1 matrix with the original matrix A_1. We store the result as A_2 for the next iteration.

Source: Image by the author.

In the second step, we define the G_2 Matrix to rotate the submatrix with columns 1 & 3 and rows 1 & 3. Then, multiply the G_2 matrix with the matrix A_2 (result from the first step). We store the result as A_3 for the next iteration.

Source: Image by the author.

In the third step, we define the G_3 Matrix to rotate the submatrix with columns 2 & 3 and rows 2 & 3. Then, multiply the G_3 matrix with the matrix A_3 (result from the first step).

Source: Image by the author.

After all the iterations to convert matrix A into an upper-triangular matrix (R matrix), we need to find the Q matrix now.

Source: Image by the author.

Now we got both the Q matrix and the R matrix.

[Step-by-Step Python Code] QR Decomposition by Householder Transformation:

# QR Decomposition by Givens Rotation
def QR_Givens_Rotation(M: Matrix) -> tuple():
G_s = []
R = M.deep_copy()

for j in range(R.n_col):
for i in range(R.n_row - 1, j, -1):
if i > j:

col_to_remove = list(
filter(lambda s: s != i and s != j, [i for i in range(R.n_row)])
)
sub = R.sub_matrix(col_to_remove, col_to_remove)
col_vector = sub.get_column_vectors(0)

# Calculate the angle to rotate
theta = math.atan2(
-col_vector[1], col_vector[0]
) # y-coordinate first, then x-coordinate

# Construct Givens Rotation Matrix
G_mat = Matrix(n_row=R.n_row, n_col=R.n_col)
G_mat.set_diagonal()
for row in [i, j]:
for col in [i, j]:
if row == col:
G_mat.values[row][col] = math.cos(theta)
else:
G_mat.values[row][col] = (
1 if row > col else -1
) * math.sin(theta)

# Save the Givens Rotation Matrix
G_s.append(G_mat)

# Calculate the R Matrix for the next iteration
R = G_mat.multiply(R)

# Calculate the Q matrix by multiplying all the transpose of the Givens Matrix
Q = Matrix(M.n_row, M.n_col)
Q.set_diagonal(1)
for G in G_s:
G.transpose()
Q = Q.multiply(G)
G.transpose()

return (Q, R)
# main.py
# ----- Example of Givens Rotation -----
def givens_rotation():

A = Matrix(
n_row=3,
n_col=3,
two_d_array=[[2, -1, -2], [-4, 6, 3], [-4, -2, 8]],
)

print("----- Givens Rotations -----")
A.print_values(matrix_name="A")
Q, R = QR_Givens_Rotation(A)

Q.print_values(matrix_name="Q", num_digits=4)

R.print_values(matrix_name="R", num_digits=4)

print("----- Validate Result -----")
new_A = Q.multiply(R)
new_A.print_values(matrix_name="new_A", num_digits=4)

Python Output

Output from main.py, Source: Image by the author.

Done! We successfully implement Givens Rotation for QR decomposition.

The Python code of the above example can be found on GitHub.

If you like this article, give me a like and share it with your friends. You may also leave me a comment/message too.

--

--

Anthony Kwok

Data Science | ML & AI | Statistics | Blockchain | Cooking