Recall that in Gaussian Elimination, row operations are used to change the coefficient matrix to an upper
triangular matrix. The solution is then found by back substitution, starting from the
last equation in the reduced system. In Gauss--Jordan Reduction, row operations are
used to diagonalize the coefficient matrix, and the answers are read directly.
The goal of this section is to identify Gaussian elimination with LU factorization. The original m-by-n matrix A
becomes a product of two or more special matrices that are actually triangular matrices. Namely, the factorization comes from elimination:
\( {\bf A} = {\bf L}\,{\bf U} , \) where L is lower triangular m-by-m matrix and U is upper m-by-n triangular matrix.
Such representation is called the LU-decomposition or LU-factorization. Computers
usually solve square systems of linear equations using the LU decomposition, and it is also a key step when inverting
a matrix, or computing the determinant of a matrix. The LU decomposition was introduced by a
Polish astronomer, mathematician, and geodesist Tadeusz Banachiewicz (1882--1954) in 1938.
For a linear system \( {\bf A}\,{\bf x} = {\bf b} \) of n equations in n
unknowns, the methods LU-decomposition and Gauss--Jordan elimination differ in bookkeeping but otherwise involve the same number of flops. However,
LU-factorization has the following advantages:
Gaussian elimination and Gauss--Jordan elimination both use the augmented matrix \( \left[ {\bf A} \, | \, {\bf b} \right] ,\)
so b must be known. In contrast, LU-decomposition uses only matrix A, so once that factorization is complete, it can be applied to any vector b.
For large linear systems in which computer memory is at a premium, one can dispense with the storage of the 1's
and zeroes that appear on or below the main diagonal of U, since those entries are known. The space
that this opens up can then be used to store the entries of L.
It should come as no surprise that Mathematica has a built-in
LU factorisation command, LUDecomposition, with returns both
upper and lower triangular matrices as a single n×n matrix, and a pivot
list:
{lu, p, c} = LUDecomposition[matrix]
where l is in the strictly lower‐triangular part of lu with ones
assumed along the diagonal:
l = lu SparseArray[{i_, j_} /; j < i -> 1, {n, n}] + IdentityMatrix[n];
u is in the upper‐triangular part of lu:
u = lu SparseArray[{i_, j_} /; j >= i -> 1, {n, n}];
Then their product l.u reconstructs the original matrix.
Not every square matrix has an LU-factorization. However, if it is
possible to reduce a square matrix A to row echelon form by
Gaussian elimination without performing any row interchanges, then
A will have an LU-decomposition, though it may not be
unique.
LU-decomposition: Step 1: rewrite the system of algebraic equations \( {\bf A} {\bf x} = {\bf b} \) as
\[
{\bf L}{\bf U} {\bf x} = {\bf b} .
\]
Step 2: Define a new \( n\times 1 \) matrix y (which is actually a column vector)
by
\[
{\bf U} {\bf x} = {\bf y} .
\]
Step 3:
Rewrite the given equation as \( {\bf L} {\bf y} = {\bf b} \) and solve this system for y. Step 4: Substitute y into the equation \( {\bf U} {\bf x} = {\bf y} \) and solve for x. ▣
To see all steps in LU-factorization without row exchange, you may want to use
the following subroutine:
LUfactorization[A0_, n_] := Module[{A = A0}, U = A0; L = IdentityMatrix[n];
Print[MatrixForm[L], MatrixForm[U], " = " , MatrixForm[A0]];
For[p = 1, p <= n - 1, p++,
For[i = p + 1, i <= n, i++,
m = A[[i, p]]/A[[p, p]];
L[[i, p]] = m;
A[[i]] = A[[i]] - m A[[p]];
U = A;
Print[MatrixForm[L], MatrixForm[U], " = ", MatrixForm[A0]]; ];];]
To control every column elimination, one may want to use
PivotDown[m_, {i_, j_}, oneflag_: 0] :=
Block[{k}, If[m[[i, j]] == 0, Return[m]];
Return[Table[
Which[k < i, m[[k]], k > i, m[[k]] - m[[k, j]]/m[[i, j]] m[[i]],
k == i && oneflag == 0, m[[k]] , k == 1 && oneflag == 1,
m[[k]]/m[[i, j]] ], {k, 1, Length[m]}]]]
One may want to use the following subroutine to determine LU-factorization:
LUfactor1[n_] := Module[{}, r = Table[j, {j, n}];
For[p = 1, p <= n - 1, p++,
For[j = p + 1, j <= m, j++,
If[Abs[A[[r[[j]], p]]] > Abs[A[[r[[p]], p]]],
r[[{j, p}]] = r[[{p, j}]] ];];
For[k = p + 1, k <= n, k++,
A[[r[[k]], p]] = A[[r[[k]], p]] / A[[r[[p]], p]] ;
A[[r[[k]], Range[p + 1, n] ]] =
A[[r[[k]], Range[p + 1, n] ]] -
A[[r[[k]], p]] A[[r[[p]], Range[p + 1, n] ]]; ];];
L = P = IdentityMatrix[n];
Z = Table[0, {j, n}];
P = P[[r]];
U = A[[r]];
For[i = 1, i <= n, i++,
L[[i, Range[1, i - 1] ]] = A[[r[[i]], Range[1, i - 1] ]];
U[[i, Range[1, i - 1] ]] = Z[[Range[1, i - 1] ]]; ];]
Procedure for constructing LU-decomposition: Step 1: Reduce \( n \times n \) matrix A
to a row echelon form U by Gaussian elimination without row interchanges, keeping track of the multipliers
used to introduce the leading coefficients (usually 1's) and multipliers used to introduce the zeroes below
the leading coefficients.
Step 2: In each position along the main diagonal L, place the reciprocal of the multiplier
that introduced the leading 1 in that position of U.
Step 3:
In each position below the main diagonal of L, place the negative of the multiplier used to introduce the zero
in that position of U.
Step 4: Form the decomposition \( {\bf A} = {\bf L} {\bf U} . \)
Recall that the elementary operations on the rows of a matrix are
equivalent to multiplying by an elementary matrix E:
(1) multiplying row i by a nonzero scalar α , denoted by \( {\bf E}_i (\alpha ) ;\)
(2) adding β times row j to row i, denoted by \( {\bf E}_{ij} (\beta ) \) (here β is any
scalar), and
(3) interchanging rows i and j, denoted by \( {\bf E}_{ij} \) (here \( i \ne j \) ),
called elementary row operations of types 1,2 and 3, respectively.
Correspondingly, a square matrix E is called an elementary matrix if it can be obtained
from an identity matrix by performing a single elementary operation.
Theorem: Every elementary matrix is
invertible, and the inverse is also an elementary matrix. ▣
Example 1: For illustration, consider 4×4
elementary matrices
Notice that matrix \( {\bf L}_{n \times n} = [l_{i,j}] \) has only one unknown to be solved for in its first row. Once the matrix L has been formed, forward substitution step, L y = b, can be conducted, beginning with the first equation as it has only one unknown:
\[
y_1 = \frac{b_1}{l_{1,1}} .
\]
Subsequent steps of forward substitution can be represented by the following formula:
Now that y has been found, it can be used in the back substitution step, U x = y, to solve for solution vector \( {\bf x}_{n \times 1} , \) where \( {\bf U}_{n \times n} = [u_{i,j}] \) is the upper triangular matrix calculated in LU-decomposition algorithm, and \( {\bf y}_{n \times 1} \) is the right hand side array.
Back substitution begins with solving the n-th equation as it has only one unknown:
\[
x_n = \frac{y_n}{u_{n,n}} .
\]
The remaining unknowns are solved for working backwards from the (n-1)-th equation to the first equation using the formula below:
which is precisely the matrix that results when we add \( -1 \) times the first row of
A to the third row. Next, we multiply by matrix \( {\bf E}_{21} (-2) = \begin{bmatrix} 1&0&0 \\ -2&1&0 \\ 0&0&1 \end{bmatrix} . \)
This yields