6.1. LU decomposition#
LU decomposition (also known as LU factorisation) is a procedure for decomposing a square matrix \(A\) into the product of a lower triangular matrix \(L\) and an upper triangular matrix \(U\) such that
The advantage of writing a matrix as a product of \(L\) and \(U\) is that the solution to a triangular set of equations is easy to calculate using forward or back substitution. Consider the LU decomposition of a \(3\times 3\) matrix
which gives a system of 9 equations (one for each element in \(A\)) in 12 unknowns which has an infinite number of solutions. If we use the condition \(\ell_{ii} = 1\) then[1]
The elements in the lower triangular region, where \(i>j\), are
which is rearranged to
For the elements in the upper triangular region where \(i\le j\) we have
which is rearranged to
So to calculate an LU decomposition we loop through each column of \(A\) and calculate the elements of \(\ell_{ij}\) and \(u_{ij}\) for that column.
(LU decomposition)
The LU decomposition of an \(n \times n\) square matrix \(A\) results in two \(n \times n\) matrices \(L\) and \(U\) such that \(A = LU\). The elements of \(L\) and \(U\) are calculated using
(LU decomposition)
Inputs: A square \(n \times n\) matrix \(A\).
Outputs: Two square \(n \times n\) matrices \(L\) and \(U\) such that \(A = LU\).
\(L \gets I_n\)
\(U \gets \vec{0}_{n \times n}\)
For each column \(j\) in \(A\) do
For each row \(i\) in \(A\) do
If \(i \leq j\)
\(u_{ij} \gets a_{ij} - \displaystyle\sum_{k=1}^{i-1} \ell_{ik}u_{kj} \)
Else
\(\ell_{ij} \gets \dfrac{1}{u_{jj}} \left( a_{ij} - \displaystyle \sum_{k=1}^{j-1} \ell_{ik}u_{kj} \right)\)
Return \(L\) and \(U\)
Determine the LU decomposition of the following matrix
Solution (click to show)
Stepping through the columns of \(A\)
Therefore
Checking that \(LU=A\)
6.1.1. Code#
The code below defines a function called lu()
which calculates the LU decomposition of a matrix.
def lu(A):
n = A.shape[0]
L, U = np.eye(n), np.zeros((n, n))
for j in range(n):
for i in range(n):
sum_ = 0
if i <= j:
for k in range(i):
sum_ += L[i,k] * U[k,j]
U[i,j] = A[i,j] - sum_
else:
for k in range(j):
sum_ += L[i,k] * U[k,j]
L[i,j] = (A[i,j] - sum_) / U[j,j]
return L, U
function [L, U] = lu(A)
n = size(A, 1);
L = eye(n);
U = zeros(n);
for j = 1 : n
for i = 1 : n
sum_ = 0;
if i <= j
for k = 1 : i - 1
sum_ = sum_ + L(i,k) * U(k,j);
end
U(i,j) = A(i,j) - sum_;
else
for k = 1 : j - 1
sum_ = sum_ + L(i,k) * U(k,j);
end
L(i,j) = (A(i,j) - sum_) / U(j,j);
end
end
end
end