Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions linear_algebra/qr_decomposition.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""
In linear algebra, a QR decomposition, also known as a QR factorization or QU factorization,

Check failure on line 2 in linear_algebra/qr_decomposition.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (E501)

linear_algebra/qr_decomposition.py:2:89: E501 Line too long (92 > 88)
is a decomposition of a matrix A into a product A = QR
of an orthonormal matrix Q and an upper triangular matrix R.
QR decomposition is often used to solve the linear least squares (LLS) problem
and is the basis for a particular eigenvalue algorithm, the QR algorithm.

This algorithm will simply attempt to perform QR decomposition on any square matrix.

Reference: https://en.wikipedia.org/wiki/QR_decomposition
"""

from __future__ import annotations
import numpy as np
from scipy.linalg import qr

Check failure on line 15 in linear_algebra/qr_decomposition.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (I001)

linear_algebra/qr_decomposition.py:13:1: I001 Import block is un-sorted or un-formatted help: Organize imports


def qr_decomposition(A: np.ndarray) -> tuple[np.ndarray, np.ndarray]:

Check failure on line 18 in linear_algebra/qr_decomposition.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (N803)

linear_algebra/qr_decomposition.py:18:22: N803 Argument name `A` should be lowercase
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide descriptive name for the parameter: A

"""
Perform QR decomposition on a given matrix and raises an error if in
m×n matrix A if m is smaller than n or m,n is less than 2

Check failure on line 21 in linear_algebra/qr_decomposition.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (RUF002)

linear_algebra/qr_decomposition.py:21:6: RUF002 Docstring contains ambiguous `×` (MULTIPLICATION SIGN). Did you mean `x` (LATIN SMALL LETTER X)?

>>> A = np.array([[1, 2, 3], [4, 5, 9], [7, 8, 15]])
>>> Q,R = qr_decomposition(A)
>>> Q
array([[-0.17, 0.9 , 0.41],
[-0.51, 0.28, -0.82],
[-0.85, -0.35, 0.41]])
>>> R
array([[-17.75, -9.63, -8.11],
[ 0. , 0.41, -0.41],
[ 0. , 0. , 0. ]])
>>> A = np.array([[1, 2], [4, 5], [7, 8]])
>>> Q,R = qr_decomposition(A)
>>> Q
array([[-0.21, 0.89, 0.41],
[-0.52, 0.25, -0.82],
[-0.83, -0.38, 0.41]])
>>> R
array([[-9.64, -8.09],
[ 0. , -0.76],
[ 0. , 0. ]])
>>> A = np.array([[1, 2, 3], [4, 5, 6]])
>>> Q,R = qr_decomposition(A)
Traceback (most recent call last):
...
ValueError: row size should be greater than column size
>>> A = np.array([[1], [4]])
>>> Q,R = qr_decomposition(A)
Traceback (most recent call last):
...
ValueError: row size and column size should be greater than 2
>>> A = np.array([[1,4]])
>>> Q,R = qr_decomposition(A)
Traceback (most recent call last):
...
ValueError: row size should be greater than column size
"""

rows, columns = np.shape(A)
if rows < columns:
msg = "row size should be greater than column size"
raise ValueError(msg)
if rows < 2 or columns < 2:
msg = "row size and column size should be greater than 2"
raise ValueError(msg)
# Perform QR decomposition with pivoting
# Q: Orthogonal matrix
# R: Upper triangular matrix
# P: Pivot indices (permutation vector)

Q, R, P = qr(A, pivoting=True)

Check failure on line 72 in linear_algebra/qr_decomposition.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (N806)

linear_algebra/qr_decomposition.py:72:11: N806 Variable `P` in function should be lowercase

Check failure on line 72 in linear_algebra/qr_decomposition.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (N806)

linear_algebra/qr_decomposition.py:72:8: N806 Variable `R` in function should be lowercase

Check failure on line 72 in linear_algebra/qr_decomposition.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (N806)

linear_algebra/qr_decomposition.py:72:5: N806 Variable `Q` in function should be lowercase

# Note: The bottom row of R is all zeros because the matrix is rank-deficient.
# Verification: A[:, P] should equal Q @ R
AP = A[:, P]

Check failure on line 76 in linear_algebra/qr_decomposition.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (N806)

linear_algebra/qr_decomposition.py:76:5: N806 Variable `AP` in function should be lowercase
if np.allclose(AP, Q @ R):
return np.round(Q, 2), np.round(R, 2)
else:
msg = "No matrix found which decompose given matrix"
raise ValueError(msg)


if __name__ == "__main__":
import doctest

doctest.testmod()
Loading