Command Palette

Search for a command to run...

Linear Methods of AI

LU Decomposition

What is LU Decomposition?

LU decomposition is an abbreviation for Lower-Upper decomposition. This name comes from the two matrices resulting from decomposition:

  • L (Lower) = Lower triangular matrix that has zero elements above the main diagonal
  • U (Upper) = Upper triangular matrix that has zero elements below the main diagonal

Why do we need this decomposition? Because solving linear equation systems with triangular matrices is much easier than with regular matrices.

Basic Concepts of LU Decomposition

LU decomposition is a way to break down a matrix into the multiplication of two simpler matrices. Imagine we have a complex puzzle, then we disassemble it into pieces that are easier to reassemble.

For a given matrix AA, we get:

PA=LUP \cdot A = L \cdot U

Where PP is a permutation matrix (row order arranger), LL is a lower triangular matrix, and UU is an upper triangular matrix.

Gaussian elimination computes this LU decomposition through a series of systematic row operations. This process can be written as:

U=LrPrL3P3L2P2L1P1AU = L_r \cdot P_r \cdot \ldots \cdot L_3 \cdot P_3 \cdot L_2 \cdot P_2 \cdot L_1 \cdot P_1 \cdot A

with i=1,,ri = 1, \ldots, r, row exchange matrix PiP_i or Pi=IP_i = I and elimination matrix:

Li=(1λi+1iλmi1)L_i = \begin{pmatrix} 1 & & & \\ & \ddots & & \\ & & \lambda_{i+1i} & \\ & & \vdots & \ddots \\ & & \lambda_{mi} & & 1 \end{pmatrix}

The inverse of LiL_i is:

Li1=(1λi+1iλmi1)L_i^{-1} = \begin{pmatrix} 1 & & & \\ & \ddots & & \\ & & -\lambda_{i+1i} & \\ & & \vdots & \ddots \\ & & -\lambda_{mi} & & 1 \end{pmatrix}

Since Pi1=PiP_i^{-1} = P_i, we can rewrite this sequence of operations into a simpler form until we finally get L1PA=UL^{-1} \cdot P \cdot A = U.

Structure of Decomposition Results

From Gaussian elimination with steps j1,,jrj_1, \ldots, j_r, we get three matrices with special structure:

(0u1j1u1nl2100u2j2u2nl31l320000urjrurml(r+1)r00000000lm1lm2lmr0000)\begin{pmatrix} 0 & u_{1j_1} & \cdots & & \cdots & u_{1n} \\ l_{21} & 0 & 0 & u_{2j_2} & \cdots & u_{2n} \\ l_{31} & l_{32} & 0 & 0 & \ddots & \\ \vdots & \vdots & \ddots & 0 & 0 & u_{rj_r} \cdots u_{rm} \\ & & & l_{(r+1)r} & 0 & 0 & 0 & 0 \\ \vdots & \vdots & & \vdots & 0 & 0 & 0 & 0 \\ l_{m1} & l_{m2} & \cdots & l_{mr} & 0 & 0 & 0 & 0 \end{pmatrix}

Matrix PP is obtained from applying permutation vector pp to the rows of the identity matrix. The three matrices have properties:

  1. UU is an upper triangular matrix in row echelon form with rank rr
  2. LL is a regular lower triangular matrix with 1 on the diagonal
  3. PP is a permutation matrix with P1=PTP^{-1} = P^T

Gaussian Elimination Steps

Let's look at a concrete example. Imagine we are cleaning house floor by floor, starting from the top.

  1. First column with pivot element a21=3a_{21} = 3. We swap the first and second rows like rearranging furniture positions.

    A=(333302421231)A = \begin{pmatrix} 3 & 3 & 3 & 3 \\ 0 & 2 & 4 & 2 \\ 1 & 2 & 3 & 1 \end{pmatrix}
    r=1, Steps ={1},p=(2,1,3),v=1r = 1, \text{ Steps } = \{1\}, p = (2,1,3), v = 1

    Eliminate other entries in that column: λ21=0\lambda_{21} = 0, λ31=13\lambda_{31} = -\frac{1}{3}

  2. Second column with pivot element a22=2a_{22} = 2. No exchange needed.

    Elimination: λ32=12\lambda_{32} = -\frac{1}{2}

  3. Third column has no pivot element that can be used.

  4. Fourth column with pivot element a34=1a_{34} = -1. No more operations needed.

Final result:

r=3,Steps={1,2,4},p=(2,1,3),v=1r = 3, \text{Steps} = \{1, 2, 4\}, p = (2,1,3), v = 1

From this elimination result, we obtain:

U=(333302420001)U = \begin{pmatrix} 3 & 3 & 3 & 3 \\ 0 & 2 & 4 & 2 \\ 0 & 0 & 0 & -1 \end{pmatrix}
L=(1000101/31/21)L = \begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 1/3 & 1/2 & 1 \end{pmatrix}
P=(010100001)P = \begin{pmatrix} 0 & 1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{pmatrix}

The proof shows that LU=PAL \cdot U = P \cdot A for the initially given matrix AA.

Algorithm and Complexity

The Gaussian elimination algorithm works like systematic cleaning. For each column, we perform:

  1. Find the best pivot element
  2. Swap rows if necessary
  3. Eliminate elements below the pivot
  4. Store multiplier information

The time complexity for computing LU decomposition is 13n3+O(n2)\frac{1}{3}n^3 + O(n^2) arithmetic operations. The proof shows that multiplication and addition occur simultaneously in the elimination row transformation aij:=aij+λirarla_{ij} := a_{ij} + \lambda_{ir} \cdot a_{rl}.

j=1ni=j+1nl=j+1n1=j=1n(nj)2\sum_{j=1}^n \sum_{i=j+1}^n \sum_{l=j+1}^n 1 = \sum_{j=1}^n (n-j)^2
=j=1n(n22nj+j2)= \sum_{j=1}^n (n^2 - 2nj + j^2)
=n32nj=1nj+j=1nj2= n^3 - 2n \sum_{j=1}^n j + \sum_{j=1}^n j^2
=n32nn(n+1)2+n(n+1)(2n+1)6= n^3 - 2n \frac{n(n+1)}{2} + \frac{n(n+1)(2n+1)}{6}
=n3n3+26n3+O(n2)= n^3 - n^3 + \frac{2}{6}n^3 + O(n^2)
=13n3+O(n2)= \frac{1}{3}n^3 + O(n^2)

Algorithm Implementation in Python

Here is the implementation of the LU decomposition algorithm in Python:

Pythonlu_decomposition.py
import numpy as npdef lu_decomposition(A):  """  Perform LU decomposition with partial pivoting  Input: Matrix A (n x n)  Output: L, U, P (Lower, Upper, and Permutation matrices)  """  n = A.shape[0]  U = A.copy().astype(float)  L = np.zeros((n, n))  P = np.eye(n)    for i in range(n):      max_row = i      for k in range(i + 1, n):          if abs(U[k, i]) > abs(U[max_row, i]):              max_row = k            if max_row != i:          U[[i, max_row]] = U[[max_row, i]]          P[[i, max_row]] = P[[max_row, i]]          if i > 0:              L[[i, max_row], :i] = L[[max_row, i], :i]            for k in range(i + 1, n):          if U[i, i] != 0:              factor = U[k, i] / U[i, i]              L[k, i] = factor              U[k, i:] = U[k, i:] - factor * U[i, i:]    np.fill_diagonal(L, 1)  return L, U, Pdef forward_substitution(L, b):  """  Forward substitution to solve L * y = b  """  n = len(b)  y = np.zeros(n)    for i in range(n):      y[i] = b[i] - np.dot(L[i, :i], y[:i])    return ydef backward_substitution(U, y):  """  Backward substitution to solve U * x = y  """  n = len(y)  x = np.zeros(n)    for i in range(n - 1, -1, -1):      if U[i, i] != 0:          x[i] = (y[i] - np.dot(U[i, i+1:], x[i+1:])) / U[i, i]    return xdef solve_linear_system(A, b):  """  Solve system Ax = b using LU decomposition  """  L, U, P = lu_decomposition(A)  pb = np.dot(P, b)  y = forward_substitution(L, pb)  x = backward_substitution(U, y)  return x, L, U, P

Solving Linear Systems

After obtaining LU decomposition, solving the system Ax=bA \cdot x = b becomes like solving a puzzle that has been sorted.

The system Ax=bA \cdot x = b transforms into Ux=L1PbU \cdot x = L^{-1} \cdot P \cdot b through two stages:

Forward Substitution

The forward substitution algorithm solves Ly=PbL \cdot y = P \cdot b with regular lower triangular matrix LL and vector c=Pbc = P \cdot b. This process is like filling stairs from bottom to top, where each step depends on the previous step.

For each row i=1,,mi = 1, \ldots, m, we calculate:

yi:=1lii(cij=1i1lijyj)y_i := \frac{1}{l_{ii}} \cdot \left( c_i - \sum_{j=1}^{i-1} l_{ij} \cdot y_j \right)

This algorithm is efficient because we only need to calculate one value at each step. The diagonal element liil_{ii} is always 1 for matrix LL from LU decomposition, so division becomes simple.

Backward Substitution

The backward substitution algorithm solves Ux=yU \cdot x = y with matrix UU in row echelon form with rr steps on columns j1,,jrj_1, \ldots, j_r and vector d=yd = y.

First, we check whether the system can be solved. If r<mr < m and there exists di0d_i \neq 0 for i{r+1,,m}i \in \{r + 1, \ldots, m\}, then the system has no solution.

If the system can be solved, we initialize kernel matrix KK with size n×(nr)n \times (n-r), and start with k=0k = 0 and i=ri = r.

The algorithm works backward from column j=nj = n to j=1j = 1. For each column, we check whether that column is a pivot step or not.

  1. If column j is a pivot step, meaning j=jij = j_i for step ii, then we calculate the solution for variable xjx_j:

    xj:=1uij(dil=j+1nuilxl)x_j := \frac{1}{u_{ij}} \cdot \left( d_i - \sum_{l=j+1}^n u_{il} \cdot x_l \right)

    And we also calculate the contribution of this variable to the kernel matrix:

    Kjq:=1uij(l=j+1nuilKlq)K_{jq} := \frac{1}{u_{ij}} \cdot \left( - \sum_{l=j+1}^n u_{il} \cdot K_{lq} \right)

    for q=1,,nrq = 1, \ldots, n - r, then we decrease ii by 1.

  2. If column j is not a pivot step, meaning there is no pivot in that column, then variable xjx_j is a free variable. We set:

    • k:=k+1k := k + 1
    • xj:=0x_j := 0 (particular solution)
    • Kjk:=1K_{jk} := 1 (kernel basis)

This algorithm produces solution xx and matrix KK that satisfy Ux=dU \cdot x = d and UK=0U \cdot K = 0.

The columns of matrix KK form a basis for the kernel (null space) of matrix UU. This means that each column KK is a vector that when multiplied by UU produces a zero vector.

The complete solution set is:

{x+K(t1tnr):t1,,tnrR}\left\{ x + K \cdot \begin{pmatrix} t_1 \\ \vdots \\ t_{n-r} \end{pmatrix} : t_1, \ldots, t_{n-r} \in \mathbb{R} \right\}

Application Example

Let's see how LU decomposition is used to solve linear systems concretely. Suppose we have vector b=(433)b = \begin{pmatrix} 4 \\ 3 \\ 3 \end{pmatrix} and want to solve system Ax=bA \cdot x = b.

  1. The first step is to calculate c=Pbc = P \cdot b. Since permutation matrix PP swaps the first row with the second row, we get:

    c=Pb=(010100001)(433)=(343)c = P \cdot b = \begin{pmatrix} 0 & 1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} 4 \\ 3 \\ 3 \end{pmatrix} = \begin{pmatrix} 3 \\ 4 \\ 3 \end{pmatrix}
  2. The second step is forward substitution to solve Ly=cL \cdot y = c. We use the lower triangular matrix LL that we have obtained. This process is done from top to bottom like filling stairs one by one.

    For the first row with l11=1l_{11} = 1, we get y1=c1=3y_1 = c_1 = 3.

    For the second row with l22=1l_{22} = 1, we get y2=c2=4y_2 = c_2 = 4.

    For the third row with l33=1l_{33} = 1, we calculate:

    y3=c3l31y1l32y2y_3 = c_3 - l_{31} \cdot y_1 - l_{32} \cdot y_2
    =3133124= 3 - \frac{1}{3} \cdot 3 - \frac{1}{2} \cdot 4
    =312=0= 3 - 1 - 2 = 0

    So we obtain:

    y=L1c=(340)y = L^{-1} \cdot c = \begin{pmatrix} 3 \\ 4 \\ 0 \end{pmatrix}
  3. The third step is backward substitution to solve Ux=yU \cdot x = y. Matrix UU in row echelon form has pivots in columns 1, 2, and 4. Column 3 has no pivot so it becomes a free variable.

    From the backward substitution process, we obtain the particular solution:

    x=(1200)x = \begin{pmatrix} -1 \\ 2 \\ 0 \\ 0 \end{pmatrix}

    and kernel matrix:

    K=(1210)K = \begin{pmatrix} 1 \\ -2 \\ 1 \\ 0 \end{pmatrix}
  4. Result interpretation is very important to understand. Solution xx is one particular solution of the equation system. Matrix KK shows the direction in which we can move in the solution space without changing the result of multiplication AxA \cdot x.

  5. Mathematical verification shows that for any parameter value t1t_1, the general solution x+Kt1x + K \cdot t_1 still satisfies the original equation.

    Let's prove by calculating A(x+Kt1)A \cdot (x + K \cdot t_1). The result is:

    A(x+Kt1)=A(1200)+A(1210)t1A \cdot (x + K \cdot t_1) = A \cdot \begin{pmatrix} -1 \\ 2 \\ 0 \\ 0 \end{pmatrix} + A \cdot \begin{pmatrix} 1 \\ -2 \\ 1 \\ 0 \end{pmatrix} \cdot t_1
    =(433)+(000)t1=b= \begin{pmatrix} 4 \\ 3 \\ 3 \end{pmatrix} + \begin{pmatrix} 0 \\ 0 \\ 0 \end{pmatrix} \cdot t_1 = b

    Note that AK=0A \cdot K = 0, which means vector KK is in the null space of matrix AA. This explains why adding multiples of KK to the solution does not change the result.

Compared to computing LU decomposition completely, this forward and backward substitution process is much more efficient for solving linear systems with different right-hand side vectors.