Skip to main content

Scientific Computing

Linear Algebra Sol...

Gaussian Elim... []

Scientific Computing

Linear Algebra Sol...

Cholesky deco... []

This material has been adapted from material by Martin Robinson from the "Scientific Computing" module of the SABS R³ Center for Doctoral Training.

This material has been adapted from material by Martin Robinson from the "Scientific Computing" module of the SABS R³ Center for Doctoral Training.

Creative Commons License
This course material was developed as part of UNIVERSE-HPC, which is funded through the SPF ExCALIBUR programme under grant number EP/W035731/1

This course material was developed as part of UNIVERSE-HPC, which is funded through the SPF ExCALIBUR programme under grant number EP/W035731/1

Creative Commons License

LU decomposition


Matrix decompositions

Matrix factorisations play a key role in the solution of problems of the type Ax=bA x = b. Often (e.g. ODE solvers), you have a fixed matrix AA that must be solved with many different bb vectors. A matrix factorisation is effectivly a pre-processing step that allows you to partition AA into multiple factors (e.g. A=LUA = LU in the case of LULU decomposition), so that the actual solve is as quick as possible. Different decompositions have other uses besides solving Ax=bA x = b, for example:

  • the LULU, QRQR and Cholesky decomposition can be used to quickly find the determinant of a large matrix, since det(AB)=det(A)det(B)\det(AB) = \det(A) \det(B) and the determinant of a triangular matrix is simply the product of its diagonal entries.

  • The Cholesky decomposition can be used to sample from a multivariate normal distribution, and is a very efficient technique to solve Ax=bA x = b for the specific case of a positive definite matrix.

  • The QRQR decomposition can be used to solve a minimum least squares problem, to find the eigenvalues and eigenvectors of a matrix, and to calulcate the Singular Value Decomposition (SVD), which is itself another very useful decomposition!

LULU decomposition

The LULU decomposition is closely related to gaussian elimination. It takes the original equation to be solved Ax=bA x = b and splits it up into two separate equations involving a unit lower triangular matrix LL, and the row echelon matrix UU:

Ly=bUx=y\begin{aligned} L y &= b \\ U x &= y \end{aligned}

where A=LUA = LU. The LL matrix is a unit lower triangular matrix and thus has ones on the diagonal, whereas UU is in row echelon form with pivot values in the leading coefficients of each row.

A=(1000100101)(p10p200p3000p4)A = \left( \begin{matrix} 1 & 0 & 0 & 0 \\ \ast & 1 & 0 & 0 \\ \ast & \ast & 1 & 0 \\ \ast & \ast & \ast & 1 \end{matrix}\right) \left(\begin{matrix} p_1 & \ast & \ast & \ast \\ 0 & p_2 & \ast & \ast \\ 0 & 0 & p_3 & \ast \\ 0 & 0 & 0 & p_4 \end{matrix}\right)

Thus, we have converted our original problem of solving Ax=bA x = b into two separate solves, first solving the equation Ly=bL y = b, and then using the result yy to solve Ux=yU x = y.

(1000100101)(y1y2y3y4)=(b1b2b3b4)(p10p200p3000p4)(x1x2x3x4)=(y1y2y3y4)\begin{aligned} \left(\begin{matrix} 1 & 0 & 0 & 0 \\ \ast & 1 & 0 & 0 \\ \ast & \ast & 1 & 0 \\ \ast & \ast & \ast & 1 \end{matrix}\right) \left(\begin{matrix} y_1 \\ y_2 \\ y_3 \\ y_4 \end{matrix}\right) &= \left(\begin{matrix} b_1 \\ b_2 \\ b_3 \\ b_4 \end{matrix}\right) \\ \left(\begin{matrix} p_1 & \ast & \ast & \ast \\ 0 & p_2 & \ast & \ast \\ 0 & 0 & p_3 & \ast \\ 0 & 0 & 0 & p_4 \end{matrix}\right) \left(\begin{matrix} x_1 \\ x_2 \\ x_3 \\ x_4 \end{matrix}\right) &= \left(\begin{matrix} y_1 \\ y_2 \\ y_3 \\ y_4 \end{matrix}\right) \end{aligned}

However, each of those solves is very cheap to compute, in this case for the 4x4 matrix shown above the solution of Ly=bL y = b only needs 6 multiplication and 6 additions, whereas Ux=yU x = y requires 4 divisions, 6 multiplications and 6 additions, leading to a total of 28 arithmetic operations, much fewer in comparison with the 62 operations required to solve the original equation Ax=bA x = b. In general, LULU decomposition for an n×nn \times n matrix takes about 2n3/32 n^3 / 3 flops, or floating point operations, to compute.

LULU factorisation without pivoting

A relativly simple LULU algorithm can be described if we assume that no pivoting is required during a gaussian elimination. In this case, the gaussian elimination process is a sequence of pp linear operations E1,E2,...,EpE_1, E_2, ..., E_p, with each operation EiE_i being a row replacement that adds a multiple of one row to another below it (i.e. EiE_i is lower triangular). The final matrix after applying the sequence of row reductions is UU in row echelon form, that is:

EpE2E1A=UE_p \cdots E_2 E_1 A = U

Since we have A=LUA = LU, we can show that the sequence of operations E1,E2,...,EpE_1, E_2, ..., E_p is also the sequence that reduces the matrix LL to an identity matrix:

A=(EpE2E1)1U=LU,A = (E_p \cdots E_2 E_1)^{-1} U = LU,

therefore,

L=(EpE2E1)1,L = (E_p \cdots E_2 E_1)^{-1},

and,

(EpE2E1)L=(EpE2E1)(EpE2E1)1=I(E_p \cdots E_2 E_1) L = (E_p \cdots E_2 E_1) (E_p \cdots E_2 E_1)^{-1} = I

This implies how we can build up the matrix LL. We choose values for LL such that the series of row operations E1,E2,...,EpE_1, E_2, ..., E_p convert the matrix LL to the identity matrix. Since each EiE_i is lower triangular, we know that both (EpE2E1)(E_p \cdots E_2 E_1) and (EpE2E1)1(E_p \cdots E_2 E_1)^{-1} are also lower triangular.

For example, consider the following matrix

A=(32136215347296115)A = \left(\begin{matrix} 3 & 2 & 1 & -3 \\ -6 & -2 & 1 & 5 \\ 3 & -4 & -7 & 2 \\ -9 & -6 & -1 & 15 \end{matrix}\right)

After three row reductions, R2+=2R1R_2 \mathrel{{+}{=}} 2 R_1, R3+=1R1R_3 \mathrel{{+}{=}} -1 R_1, and R3+=3R1R_3 \mathrel{{+}{=}} 3 R_1, we have the following result:

E1E2E3A=(3213020600)E_1 E_2 E_3 A = \left(\begin{matrix} 3 & 2 & 1 & -3 \\ 0 & 2 & * & * \\ 0 & -6 & * & * \\ 0 & 0 & * & * \end{matrix}\right)

To build the 1st column of LL, we simply divide the 1st column of AA by the pivot value 3, giving

L=(1000210011031)L = \left(\begin{matrix} 1 & 0 & 0 & 0 \\ -2 & 1 & 0 & 0 \\ 1 & * & 1 & 0 \\ -3 & * & * & 1 \end{matrix}\right)

For the next column we do the same, using the new pivot value A2,2=2A_{2,2} = 2 in row 2 to reduce A3,2A_{3,2} and A4,2A_{4,2} to zero, and then dividing the column vector under the pivot (6,0)T(-6, 0)^T by the pivot value 2 to obtain the next column of LL.

Repeating this process for all the columns in AA, we obtain the final factorisation. You can verify for yourself that repeating the same row operations we did to form UU to the matrix LL reduces it to the identity matrix.

L=(1000210013103021)L = \left(\begin{matrix} 1 & 0 & 0 & 0 \\ -2 & 1 & 0 & 0 \\ 1 & -3 & 1 & 0 \\ -3 & 0 & 2 & 1 \end{matrix}\right)
E1E2...EpA=U=(3213023100120002)E_1 E_2 ... E_p A = U = \left(\begin{matrix} 3 & 2 & 1 & -3 \\ 0 & 2 & 3 & -1 \\ 0 & 0 & 1 & 2 \\ 0 & 0 & 0 & 2 \end{matrix}\right)

Pivoting

Of course, for any practial LULU factorisation we need to consider pivoting. Any matrix AA can be factorised into PLUPLU, where PP is a permutation matrix, and LL and UU are defined as before. During the gaussian elimination steps we store an array of row indices pip_i indicating that row ii is interchanged with row pip_i, and the resultant array of pip_i can be used to build the permutation matrix PP (It would be wasteful to store the entire martix PP so the array pip_i is stored instead).

Thus, the LU algorithm proceeds as follows:

  1. Begin with the left-most column i=0i=0, find an appropriate pivot (e.g. maximum entry in the column) and designate this row as the pivot row. Interchange this row with row ii, and store the pivot row index as pip_i. Use row replacements to create zeros below the pivot. Create the corresponding column for LL by dividing by the pivot value.

  2. Continue along to the next column ii, again choosing a pivot row pip_i, interchanging it with row ii and creating zeros below the pivot, creating the new column in LL, and making sure to record which pivot row has been chosen for each column. Repeat this step for all the columns of the matrix.

  3. Once the last column has been done, UU should be in row echlon form and LL should be a unit lower triangular matrix. The array pip_i implicitly defines the permutation matrix PP

In practice, most library implementation store LL and UU in the same matrix since they are lower and upper triangular respectivly.

LDLLDL decomposition

It is often very benificial when solving linear systems to consider and take advantage of any special structure that the matrix AA might possesses. The LDLLDL decomposition is a varient on LU decomposition which is only applicable to a symmetric matrix AA (i.e. A=ATA = A^T). The advantage of using this decomposition is that it takes advantage of the redundent entries in the matrix to reduce the amount of computation to n3/3n^3/3, which is about a half that required for the LULU decomposition.

Other Reading

Software

Problems

LU decomposition

Take your gaussian elimination code that you wrote in the previous lesson and use it to write an LU decomposition function that takes in a martix AA, and returns LL, UU and the array pip_i. You can check your answer using scipy.linalg.lu_factor. Hint: the permutation matrix is tricky to construct, so you might want to use the test given in the documentation for lu_factor.