LU decomposition

From testwiki
Jump to navigation Jump to search

Template:Short description In numerical analysis and linear algebra, lowerโ€“upper (LU) decomposition or factorization factors a matrix as the product of a lower triangular matrix and an upper triangular matrix (see matrix multiplication and matrix decomposition). The product sometimes includes a permutation matrix as well. LU decomposition can be viewed as the matrix form of Gaussian elimination. Computers usually solve square systems of linear equations using LU decomposition, and it is also a key step when inverting a matrix or computing the determinant of a matrix. It is also sometimes referred to as LR decomposition (factors into left and right triangular matrices). The LU decomposition algorithm for general matrices was introduced by the Polish astronomer Tadeusz Banachiewicz in 1938.[1]

Definitions

LDU decomposition of a Walsh matrix

Let Template:Mvar be a square matrix. An LU factorization refers to expression of Template:Mvar into product of two factors โ€“ a lower triangular matrix Template:Mvar and an upper triangular matrix Template:Mvar such that Template:Math. Sometimes factorization is impossible without prior reordering of Template:Mvar to prevent division by zero or uncontrolled growth of rounding errors. Hence alternative expression becomes Template:Math, where in formal notation permutation matrix factors Template:Mvar and Template:Mvar indicate permutation of rows (or columns) of Template:Mvar. In theory Template:Mvar (or Template:Mvar) is obtained by permutations of rows (or columns) of the identity matrix; in practice the corresponding permutations are applied directly to rows (or columns) of Template:Mvar.

Matrix Template:Mvar of side Template:Mvar has n2 coefficients while two triangle matrices combined contain Template:Math coefficients, and therefore Template:Mvar coefficients of matrices Template:Mvar are not independent. The convention is to set Template:Mvar unitriangular, i.e. with all Template:Mvar main diagonal elements equal to one. However, setting instead Template:Mvar matrix unitriangular reduces to the same procedure after transpose of matrix product (cf. properties of matrix transposition): B=A๐–ณ=(LU)๐–ณ=U๐–ณL๐–ณ. After transposition, Template:Math is lower triangle while Template:Math is upper unitriangular factor of Template:Mvar. This demonstrates also, that operations on rows (e.g. pivoting) are equivalent to those on columns of a transposed matrix, and in general choice of row or column algorithm offers no advantage.

In the lower triangular matrix all elements above the main diagonal are zero, in the upper triangular matrix, all the elements below the diagonal are zero. For example, for a Template:Resx matrix Template:Mvar, its LU decomposition looks like this: [a11a12a13a21a22a23a31a32a33]=[โ„“1100โ„“21โ„“220โ„“31โ„“32โ„“33][u11u12u130u22u2300u33].

Without a proper ordering or permutations in the matrix, the factorization may fail to materialize. For example, it is easy to verify (by expanding the matrix multiplication) that a11=โ„“11u11. If a11=0, then at least one of โ„“11 and u11 has to be zero, which implies that either Template:Mvar or Template:Mvar is singular. This is impossible if Template:Mvar is nonsingular (invertible). In terms of operations, zeroing/elimination of remaining elements of first column of Template:Mvar involves division of a21,a31 with a11, impossible if it is 0. This is a procedural problem. It can be removed by simply reordering the rows of Template:Mvar so that the first element of the permuted matrix is nonzero. The same problem in subsequent factorization steps can be removed the same way. For numerical stability against rounding errors/division by small numbers it is important to select a11 of large absolute value (cf. pivoting).

LU through recursion

The above example of Template:Resx matrices demonstrates that matrix product of top row and leftmost columns of involved matrices plays special role for Template:Mvar to succeed. Let us mark consecutive versions of matrices with (0),(1),… and then let us write matrix product Aโ‰กA(0)=L(0)U(0) in such way that these rows and columns are separated from the rest. In doing so we shall use block matrix notation, such that e.g. aโ‰กa11 is an ordinary number, ๐ฐ๐–ณโ‰ก(a12,a13)๐–ณ is a row vector and ๐ฏ=(a21,a31) is a column vector and A′ is sub-matrix of matrix A(0) without top row and leftmost column. Then we can replace A(0)=L(0)U(0) with a block matrix product. Namely it turns out that one can multiply matrix blocks in such way as if they were ordinary numbers, i.e. row times column, except that now their components are sub-matrices, sometimes reduced to scalars or vectors. Thus u๐ฅ denotes a vector obtained from ๐ฅ after multiplication of each component by a number Template:Nowrap ๐ฅ๐ฎ๐–ณ is an outer product of vectors Template:Nowrap i.e. a matrix which first column is Template:Nowrap next is u13๐ฅ and so on for all components of ๐ฎ and L(1)U(1) is a product of sub-matrices of L(0),U(0) (a๐ฐ๐–ณ๐ฏA′)=(1๐ŸŽ๐–ณ๐ฅL(1))(u๐ฎ๐–ณ๐ŸŽU(1))=(u๐ฎ๐–ณu๐ฅ๐ฅ๐ฎ๐–ณ+L(1)U(1))

From equality of first and last matrices follow final Template:Nowrap Template:Nowrap ๐ฅ=(1/a)๐ฏ while matrix A′ becomes updated/replaced with A(1)โ‰กL(1)U(1)= Template:Nowrap Now comes the crucial observation: nothing prevents us to treat A(1) the same way as we did with Template:Nowrap repeatedly. If dimension of A is Template:Resx, after Template:Math such steps all columns ๐ฏ form sub-diagonal part of triangle matrix L and all pivots a combined with rows ๐ฐ๐–ณ form upper triangle matrix Template:Nowrap as required. In the above example Template:Math so only two steps suffice.

The above procedure demonstrates that at no step the top diagonal pivot element a of consecutive sub-matrices can be zero. To avoid it columns or rows may be swapped so that a becomes nonzero. Such procedure involving permutation is called LUP, decomposition with pivoting.

Permutation of columns corresponds to matrix product AQ(0) where Q(0) is a permutation matrix, i.e. the identity matrix I after the same column permutation. After all steps such LUP decomposition applies to Template:Nowrap Present computation scheme and similar in Cormen et al.Template:Sfnp are examples of Template:Dfni. They demonstrate two general properties of LU factorization: Template:Ordered list Recurrence algorithms are not overly costly in terms of algebraic operations yet they suffer from practical disadvantage due to need to update and store most elements of Template:Mvar at each step. It will be seen that by reordering calculations it is possible to dispose with storage of intermediate values.

LU factorization with partial pivoting

It turns out that a proper permutation of rows (or columns) to select column (or row) absolute maximal pivot Template:Math is sufficient for numerically stable LU factorization, except for known pathological cases. It is called 'Template:Dfni' (LUP): PA=LU,(AQ=LU), where Template:Mvar and Template:Mvar are again lower and upper triangular matrices, and Template:Mvar and Template:Mvar are corresponding permutation matrices, which, when correspondingly left- and right-multiplied to Template:Mvar, reorder the rows and columns of Template:Mvar. It turns out that all square matrices can be factorized in this form,[2] and the factorization is numerically stable in practice.Template:Sfnp This makes LUP decomposition a useful technique in practice.

A variant called 'Template:Dfni' at each step involves search of maximum element the way rook moves on a chessboard, along column, row, column again and so on till reaching a pivot maximal in both its row and column. It can be proven that for large matrices of random elements its cost of operations at each step is similarly to partial pivoting proportional to the length of matrix side unlike its square for full pivoting.

LU factorization with full pivoting

An 'Template:Dfni' involves both row and column permutations to find absolute maximum element in the whole submatrix: PAQ=LU, where Template:Mvar, Template:Mvar, and Template:Mvar are defined as before, and Template:Mvar is a permutation matrix that reorders the columns of Template:Mvar.Template:Sfnp

Lower-diagonal-upper (LDU) decomposition

A 'Template:Dfni' (LDU) is a decomposition of the form A=LDU, where Template:Mvar is a diagonal matrix, and Template:Mvar and Template:Mvar are unitriangular matrices, meaning that all the entries on the diagonals of Template:Mvar and Template:Mvar are one.

Rectangular matrices

Above we required that Template:Mvar be a square matrix, but these decompositions can all be generalized to rectangular matrices as well.Template:Sfnmp In that case, Template:Mvar and Template:Mvar are square matrices both of which have the same number of rows as Template:Mvar, and Template:Mvar has exactly the same dimensions as Template:Mvar. 'Upper triangular' should be interpreted as having only zero entries below the main diagonal, which starts at the upper left corner. Similarly, the more precise term for Template:Mvar is that it is the row echelon form of the matrix Template:Mvar.

Example

We factor the following Template:Resx matrix: [4363]=[โ„“110โ„“21โ„“22][u11u120u22].

One way to find the LU decomposition of this simple matrix would be to simply solve the linear equations by inspection. Expanding the matrix multiplication gives {โ„“11โ‹…u11+0โ‹…0=4โ„“11โ‹…u12+0โ‹…u22=3โ„“21โ‹…u11+โ„“22โ‹…0=6โ„“21โ‹…u12+โ„“22โ‹…u22=3

This system of equations is underdetermined. In this case any two nonzero elements of Template:Mvar and Template:Mvar matrices are parameters of the solution and can be set arbitrarily to any nonzero value. Therefore, to find the unique LU decomposition, it is necessary to put some restriction on Template:Mvar and Template:Mvar matrices. For example, we can conveniently require the lower triangular matrix Template:Mvar to be a unit triangular matrix, so that all the entries of its main diagonal are set to one. Then the system of equations has the following solution: โ„“11=โ„“22=1โ„“21=1.5u11=4u12=3u22=โˆ’1.5

Substituting these values into the LU decomposition above yields [4363]=[101.51][430โˆ’1.5].

Existence and uniqueness

Square matrices

Any square matrix Template:Mvar admits LUP and PLU factorizations.[2] If Template:Mvar is invertible, then it admits an LU (or LDU) factorization if and only if all its leading principal minors are nonzeroTemplate:Sfnp[3] (for example [0110] does not admit an LU or LDU factorization). If Template:Mvar is a singular matrix of rank Template:Mvar, then it admits an LU factorization if the first Template:Mvar leading principal minors are nonzero, although the converse is not true.Template:Sfnp

If a square, invertible matrix has an LDU factorization (with all diagonal entries of Template:Mvar and Template:Mvar equal to Template:Math), then the factorization is unique.[3] In that case, the LU factorization is also unique if we require that the diagonal of either Template:Mvar or Template:Mvar consists of ones.

In general, any square matrix Template:Math could have one of the following:

  1. a unique LU factorization (as mentioned above);
  2. infinitely many LU factorizations if any of the first Template:Math columns are linearly dependent;
  3. no LU factorization if the first Template:Math columns are linearly independent and at least one leading principal minor is zero.

In Case 3, one can approximate an LU factorization by changing a diagonal entry Template:Mvar to Template:Math to avoid a zero leading principal minor.[4]

Symmetric positive-definite matrices

If Template:Mvar is a symmetric (or Hermitian, if Template:Mvar is complex) positive-definite matrix, we can arrange matters so that Template:Mvar is the conjugate transpose of Template:Mvar. That is, we can write Template:Mvar as A=LLโˆ—.

This decomposition is called the Cholesky decomposition. If Template:Mvar is positive definite, then the Cholesky decomposition exists and is unique. Furthermore, computing the Cholesky decomposition is more efficient and numerically more stable than computing some other LU decompositions.

General matrices

For a (not necessarily invertible) matrix over any field, the exact necessary and sufficient conditions under which it has an LU factorization are known. The conditions are expressed in terms of the ranks of certain submatrices. The Gaussian elimination algorithm for obtaining LU decomposition has also been extended to this most general case.Template:Sfnp

Algorithms

Closed formula

When an LDU factorization exists and is unique, there is a closed (explicit) formula for the elements of Template:Mvar, Template:Mvar, and Template:Mvar in terms of ratios of determinants of certain submatrices of the original matrix Template:Mvar.Template:Sfnp In particular, Template:Math, and for Template:Math, Template:Mvar is the ratio of the Template:Mvar-th principal submatrix to the Template:Math-th principal submatrix. Computation of the determinants is computationally expensive, so this explicit formula is not used in practice.

Using Gaussian elimination

The following algorithm is essentially a modified form of Gaussian elimination. Computing an LU decomposition using this algorithm requires Template:Math floating-point operations, ignoring lower-order terms. Partial pivoting adds only a quadratic term; this is not the case for full pivoting.Template:Sfnp

Generalized explanation

Notation

Given an Template:Times matrix Template:Nowrap define A(0) as the original, unmodified version of the matrix Template:Mvar. The parenthetical superscript (e.g., Template:Math) of the matrix Template:Mvar is the version of the matrix. The matrix Template:Math is the Template:Mvar matrix in which the elements below the main diagonal have already been eliminated to 0 through Gaussian elimination for the first Template:Mvar columns.

Below is a matrix to observe to help us remember the notation (where each Template:Math represents any real number in the matrix):

A(nโˆ’1)=(โˆ—โ‹ฏโˆ—0โ‹ฑโ‹ฑโˆ—โ‹ฎ0an,n(nโˆ’1)โ‹ฎโ‹ฎai,n(nโˆ’1)โˆ—โ‹ฎโ‹ฎโ‹ฑ0โ‹ฏ0ai,n(nโˆ’1)โˆ—โ‹ฏโˆ—)

Procedure

During this process, we gradually modify the matrix Template:Mvar using row operations until it becomes the matrix Template:Mvar in which all the elements below the main diagonal are equal to zero. During this, we will simultaneously create two separate matrices Template:Mvar and Template:Mvar, such that Template:Math.

We define the final permutation matrix Template:Mvar as the identity matrix which has all the same rows swapped in the same order as the Template:Mvar matrix while it transforms into the matrix Template:Mvar. For our matrix Template:Math, we may start by swapping rows to provide the desired conditions for the Template:Mvar-th column. For example, we might swap rows to perform partial pivoting, or we might do it to set the pivot element Template:Mvar on the main diagonal to a nonzero number so that we can complete the Gaussian elimination.

For our matrix Template:Math, we want to set every element below an,n(nโˆ’1) to zero (where an,n(nโˆ’1) is the element in the Template:Mvar-th column of the main diagonal). We will denote each element below an,n(nโˆ’1) as ai,n(nโˆ’1) (where Template:Math). To set ai,n(nโˆ’1) to zero, we set Template:Math for each row Template:Mvar. For this operation, Template:Nowrap Once we have performed the row operations for the first Template:Math columns, we have obtained an upper triangular matrix Template:Math which is denoted by Template:Mvar.

We can also create the lower triangular matrix denoted as Template:Mvar, by directly inputting the previously calculated values of Template:Mvar via the formula below.

L=(10โ‹ฏ0โ„“2,1โ‹ฑโ‹ฑโ‹ฎโ‹ฎโ‹ฑโ‹ฑ0โ„“N,1โ‹ฏโ„“N,Nโˆ’11)

Example

If we are given the matrix A=(05223421279), we will choose to implement partial pivoting and thus swap the first and second row so that our matrix Template:Mvar and the first iteration of our Template:Mvar matrix respectively become A(0)=(42105223279),P(0)=(010100001). Once we have swapped the rows, we can eliminate the elements below the main diagonal on the first column by performing row2=row2โˆ’(โ„“2,1)โ‹…row1row3=row3โˆ’(โ„“3,1)โ‹…row1 such that, โ„“2,1=04=0โ„“3,1=24=0.5 Once these rows have been subtracted, we have derived from Template:Math the matrix A(1)=(42105223068.5).

Because we are implementing partial pivoting, we swap the second and third rows of our derived matrix and the current version of our Template:Mvar matrix respectively to obtain A(1)=(421068.505223),P(1)=(010001100). Now, we eliminate the elements below the main diagonal on the second column by performing Template:Math such that Template:Math. Because no nonzero elements exist below the main diagonal in our current iteration of Template:Mvar after this row subtraction, this row subtraction derives our final Template:Mvar matrix (denoted as Template:Mvar) and final Template:Mvar matrix: A(2)=A(Nโˆ’1)=U=(421068.5000.25),P=(010001100). After also switching the corresponding rows, we obtain our final Template:Mvar matrix: L=(100โ„“3,110โ„“2,1โ„“3,21)=(1000.5100561)

Now these matrices have a relation such that Template:Math.

Relations when no rows are swapped

If we did not swap rows at all during this process, we can perform the row operations simultaneously for each column Template:Mvar by setting A(n):=Lnโˆ’1A(nโˆ’1), where Lnโˆ’1 is the Template:Times identity matrix with its Template:Mvar-th column replaced by the transposed vector Template:Math.

In other words, the lower triangular matrix Lnโˆ’1=(1โ‹ฑ1โˆ’โ„“n+1,nโ‹ฎโ‹ฑโˆ’โ„“N,n1).

Performing all the row operations for the first Template:Math columns using the A(n):=Lnโˆ’1A(nโˆ’1) formula is equivalent to finding the decomposition A=L1L1โˆ’1A(0)=L1A(1)=L1L2L2โˆ’1A(1)=L1L2A(2)=โ‹ฏ=L1โ‹ฏLNโˆ’1A(Nโˆ’1). Denote Template:Math so that Template:Math.

Now let's compute the sequence of Template:Math. We know that Template:Mvar has the following formula: Ln=(1โ‹ฑ1โ„“n+1,nโ‹ฎโ‹ฑโ„“N,n1)

If there are two lower triangular matrices with 1s in the main diagonal, and neither have a nonzero item below the main diagonal in the same column as the other, then we can include all nonzero items at their same location in the product of the two matrices. For example:

(1000077100012010063001070001)(1000001000022100033010044001)=(1000077100012221006333010744001)

Finally, multiply Template:Mvar together and generate the fused matrix denoted as Template:Mvar (as previously mentioned). Using the matrix Template:Mvar, we obtain Template:Math.

It is clear that in order for this algorithm to work, one needs to have an,n(nโˆ’1)โ‰ 0 at each step (see the definition of Template:Mvar. If this assumption fails at some point, one needs to interchange Template:Mvar-th row with another row below it before continuing. This is why an LU decomposition in general looks like Template:Math.

LU Banachiewicz decomposition

Illustration of operation of Banachiewicz LU algorithm to obtain 3-rd row and column of respectively matrices Template:Mvar and Template:Mvar. Involved matrices are named above squares marking their content. Matrix products and subtractions are applied only to elements in the thick frame boxes. Green filled thin frame boxes indicate values already known, from previous stages. Blue boxes indicate places in Template:Mvar and Template:Mvar matrices for storing of results.

Although Banachiewicz (1938) LU decomposition algorithm preceded the advent of programmed electronic computers, it was ready made for direct implementation into code as index swapping, transpose and column by column multiplication remain native built capabilities of the most programming languages and they are handled by compilers alone with little delay of the actual execution. The peculiar matrix notation used by Banachiewicz enabled him to multiply matrices column by column, a convenient feature for mechanical calculations as he could reveal consecutive factors by sliding a ruler to next rows of matrices. For human readers however, his equations are best transformed into standard matrix notation. To obtain from a full matrix Template:Mvar triangle matrices Template:Mvar and Template:Mvar calculations, start by copying top row and leftmost column of Template:Mvar respectively into corresponding positions of matrices Template:Mvar and Template:Mvar. The known unit diagonal elements of Template:Mvar are not stored nor used throughout the whole process. Next calculations continue for the subsequent rows and columns till the bottom right corner of Template:Mvar.

The figure illustrates calculations for 3rd row and column, assuming previous stages were already completed. Involved matrices are named above squares marking their content. Matrix products and subtractions are applied only to elements in the thick frame boxes. Green filled thin frame boxes indicate values already known, from previous stages. Blue boxes indicate places in Template:Mvar and Template:Mvar matrices for storing of results. Note that at each stage the result elements of Template:Mvar need to be divided by the corresponding pivot element on the main diagonal of Template:Mvar. This applies to the leftmost column of Template:Mvar too.

Note that after completion of 3rd stage the involved elements of matrix Template:Mvar are no longer used and neither those from the previous stages. This enables replacement of these elements with the result values of Template:Mvar and Template:Mvar, i.e. execution of LU decomposition Template:Em, so that the whole Template:Mvar is replaced with Template:Mvar and Template:Mvar except for the unit diagonal of Template:Mvar. Banachiewicz LU algorithm is well suited for partial pivoting by choosing the absolute maximum pivot from the newly calculated row of Template:Mvar and subsequently swapping its columns so that it lands on the main diagonal. More details can be figured out from inspection of the enclosed Fortran90 code.

All partial pivoting LU algorithms cost roughly the same amount, of order O(23n3) operations, where Template:Mvar is the number of rows or columns of Template:Mvar.

LU Crout decomposition

Note that the decomposition obtained through this procedure is a Template:Dfni: the main diagonal of Template:Mvar is composed solely of ones. If one would proceed by removing elements Template:Em the main diagonal by adding multiples of the Template:Em (instead of removing elements Template:Em the diagonal by adding multiples of the Template:Em), we would obtain a Crout decomposition, where the main diagonal of Template:Mvar is of ones.

Another (equivalent) way of producing a Crout decomposition of a given matrix Template:Mvar is to obtain a Doolittle decomposition of the transpose of Template:Mvar. Indeed, if Template:Math is the LU-decomposition obtained through the algorithm presented in this section, then by taking Template:Math and Template:Math, we have that Template:Math is a Crout decomposition.

Randomized algorithm

It is possible to find a low rank approximation to an LU decomposition using a randomized algorithm. Given an input matrix Template:Mvar and a desired low rank Template:Mvar, the randomized LU returns permutation matrices Template:Mvar, Template:Mvar and lower/upper trapezoidal matrices Template:Mvar, Template:Mvar of size Template:Times and Template:Times respectively, such that with high probability Template:Math, where Template:Mvar is a constant that depends on the parameters of the algorithm and Template:Math is the Template:Math-th singular value of the input matrix Template:Mvar.[5]

Theoretical complexity

If two matrices of order Template:Mvar can be multiplied in time Template:Math, where Template:Math for some Template:Math, then an LU-decomposition can be computed in time Template:Math.Template:Sfnp This means, for example, that an Template:Math algorithm exists based on the Coppersmithโ€“Winograd algorithm. See also for fast matrix multiplication algorithms article for more details.

Sparse-matrix decomposition

Special algorithms have been developed for factorizing large sparse matrices. These algorithms attempt to find sparse factors Template:Mvar and Template:Mvar. Ideally, the cost of computation is determined by the number of nonzero entries, rather than by the size of the matrix.

These algorithms use the freedom to exchange rows and columns to minimize fill-in (entries that change from an initial zero to a nonzero value during the execution of an algorithm).

General treatment of orderings that minimize fill-in can be addressed using graph theory.

Applications

Solving linear equations

Given a system of linear equations in matrix form A๐ฑ=๐›,

we want to solve the equation for Template:Math, given Template:Mvar and Template:Math. Suppose we have already obtained the LUP decomposition of Template:Mvar such that Template:Math, so Template:Math.

In this case the solution is done in two logical steps:

  1. First, we solve the equation Template:Math for Template:Math.
  2. Second, we solve the equation Template:Math for Template:Math.

In both cases we are dealing with triangular matrices (Template:Mvar and Template:Mvar), which can be solved directly by forward and backward substitution without using the Gaussian elimination process (however we do need this process or equivalent to compute the LU decomposition itself).

The above procedure can be repeatedly applied to solve the equation multiple times for different Template:Math. In this case it is faster (and more convenient) to do an LU decomposition of the matrix Template:Mvar once and then solve the triangular matrices for the different Template:Math, rather than using Gaussian elimination each time. The matrices Template:Mvar and Template:Mvar could be thought to have "encoded" the Gaussian elimination process.

The cost of solving a system of linear equations is approximately Template:Math floating-point operations if the matrix Template:Mvar has size Template:Mvar. This makes it twice as fast as algorithms based on QR decomposition, which costs about Template:Math floating-point operations when Householder reflections are used. For this reason, LU decomposition is usually preferred.Template:Sfnp

Inverting a matrix

When solving systems of equations, Template:Math is usually treated as a vector with a length equal to the height of matrix Template:Mvar. In matrix inversion however, instead of vector Template:Math, we have matrix Template:Mvar, where Template:Mvar is an Template:Times matrix, so that we are trying to find a matrix Template:Mvar (also a Template:Times matrix): AX=LUX=B.

We can use the same algorithm presented earlier to solve for each column of matrix Template:Mvar. Now suppose that Template:Mvar is the identity matrix of size Template:Mvar, Template:Mvar. It follows that the result Template:Mvar must be the inverse of Template:Mvar.Template:Sfnp

Computing the determinant

Given the LUP decomposition Template:Math of a square matrix Template:Mvar, the determinant of Template:Mvar can be computed straightforwardly as det⁡(A)=det⁡(Pโˆ’1)det⁡(L)det⁡(U)=(โˆ’1)S(โˆi=1nlii)(โˆi=1nuii).

The second equation follows from the fact that the determinant of a triangular matrix is simply the product of its diagonal entries, and that the determinant of a permutation matrix is equal to Template:Math where Template:Mvar is the number of row exchanges in the decomposition.

In the case of LU decomposition with full pivoting, Template:Math also equals the right-hand side of the above equation, if we let Template:Mvar be the total number of row and column exchanges.

The same method readily applies to LU decomposition by setting Template:Mvar equal to the identity matrix.

History

LU decomposition: LU factors and their product in original Banachiewicz(1938) matrix notation

The LU decomposition is related to elimination of linear systems of equations, as e.g. described by Ralston.Template:Sfnp The solution of Template:Mvar linear equations in Template:Mvar unknowns by elimination was already known to ancient Chinese.Template:Sfnp Before Gauss many mathematicians in Eurasia were performing and perfecting it yet as the method became relegated to school grade, few of them left any detailed descriptions. Thus the name Gaussian elimination is only a convenient abbreviation of a complex history.

The Polish astronomer Tadeusz Banachiewicz introduced the LU decomposition in 1938.Template:Sfnp About Banachiewicz, Paul Dwyer stated:Template:SfnpTemplate:Page needed Template:Blockquote

BanachiewiczTemplate:Sfnp was the first to consider elimination in terms of matrices and in this way formulated LU decomposition, as demonstrated by his graphic illustration. His calculations follow ordinary matrix ones, yet notation deviates in that he preferred to write one factor transposed, to be able to multiply them mechanically column by column, by sliding ruler down consecutive rows of both (using arithmometer). Combined with swapped order of indices his formulae in modern notation read ๐ฑโ‹…IA′=๐ŸŽโ†’A′๐ฑ=0โ‰ก(A|๐ฅ)๐ฑ,A=Gโ‹…Hโ†’AT=GTH,

where Template:Math; Template:Math; Template:Math refers to Template:Mvar extended with the last column; and the last component of Template:Math is Template:Math. Matrix formulae to calculate rows and columns of LU factors by recursion are given in the remaining part of Banachiewicz's paper as Eq. (2.3) and (2.4) Template:See below. This paper by Banachiewicz contains both derivation of Template:Mvar and Template:Math factors of respectively non-symmetric and symmetric matrices. They are sometimes confused as later publications tend to tie his name solely with the rediscovery of Cholesky decomposition. Banachiewicz himself can be excused of inaction as already next year he suffered from persecution by occupiers, spending three month in the Sachsenhausen Concentration Camp, on release from which he carried himself from a train his collaborator and co-prisoner Antoni Wilk, who died of exhaustion a week later.

Code examples

Fortran90 code example

Module mlu
      Implicit None
      Integer, Parameter :: SP = Kind(1d0) ! set I/O real precision
      Private
      Public luban, lusolve
Contains
      Subroutine luban (a, tol, g, h, ip, condinv, detnth)
! By Banachiewicz (1938, hereafter B38) LU decomposition method calculates such
! triangles L=G^T, and U=H  that square B=A^T=G^TH=LU. Partial pivoting
! by column permutation IP(:) is modern addition.
! Within the code a, g correspond to B38 A^T and G^T, so that a=gh holds.
!
! Normal use is for square A, however for RHS l already known
! input of (A|l)^T yields (L|y^T)^T where x in L^Tx=y is solution of Ax=l.
         Real (SP), Intent (In) :: a (:, :)! input matrix A(m,n), n<=m
         Real (SP), Intent (In) :: tol ! tolerance for near zero pivot
         Real (SP), Intent (Out) :: g (size(a,dim=1), size(a,dim=2)) ! L(m,n)
         Real (SP), Intent (Out) :: h (size(a,dim=2), size(a,dim=2)) ! U(n,n)
                                       ! note U columns are permuted
         Real (SP), Intent (Out) :: condinv ! 1/cond(A), 0 for singular A
         Real (SP), Intent (Out) :: detnth  ! sign*Abs(det(A))**(1/n)
         Integer, Intent (Out)   :: ip (size(a, dim=2)) ! columns permutation
!
         Integer :: k, n, j, l, isig
         Real (SP) :: tol0, pivmax, pivmin, piv
!
         n = size (a, dim=2)
         tol0 = Max (tol, 3._SP*epsilon(tol0))! use default for tol=0
!
! Rectangular A and G are permitted under condition:
         If (n > size(a, dim=1) .Or. n < 1) Stop 91
         Forall (k=1:n) ip (k) = k
         h = 0._SP
         g = 0._SP
         isig = 1
         detnth = 0._SP
         pivmax = Maxval (Abs (a(1, :)))
         pivmin = pivmax
!
         Do k = 1, n
! Banachiewicz (1938) Eq. (2.3)
            h(k, ip(k:)) = a(k, ip(k:)) - Matmul(g(k, :k-1), h(:k-1, ip(k:)))
!
! Find row pivot
            j = (Maxloc(Abs(h(k, ip(k:))), dim=1) + k-1)
            If (j /= k) Then ! Swap columns j and k
               isig = - isig ! Change Det(A) sign because of permutation
               l = ip (k)
               ip (k) = ip (j)
               ip (j) = l
            End If
            piv = Abs (h(k, ip(k)))
            pivmax = Max (piv, pivmax) ! Adjust condinv
            pivmin = Min (piv, pivmin)
            If (piv < tol0) Then ! singular matrix
               isig = 0
               pivmax = 1._SP
               Exit
            Else ! Account for pivot contribution to Det(A) sign and value
               If (h(k, ip(k)) < 0._SP) isig = - isig
               detnth = detnth + Log (piv)
            End If
!
! Transposed Banachiewicz (1938) Eq. (2.4)
            g (k+1:, k) = (a(k+1:, ip(k)) - &
               Matmul(g(k+1:, :k-1), h(:k-1, ip(k)))) / h (k, ip(k))
            g (k, k) = 1._SP
         End Do
!
         detnth = isig * Exp (detnth/n)
         condinv = Abs (isig) * pivmin / pivmax
! Test for square A(n,n) by uncommenting below
!         Print *, '|AQ-LU| ',Maxval (Abs(a(:,ip(:))-Matmul(g, h(:,ip(:)))))
      End Subroutine luban
      
      Subroutine lusolve(l,u,ip,x)
! Solves Ax=b system using triangle factors LU=A      
         Real (SP), Intent (In)    :: l (:, :) ! lower triangle matrix L(n,n)
         Real (SP), Intent (In)    :: u (:, :) ! upper triangle matrix U(n,n)
         Integer, Intent (In)      :: ip (:)   ! columns permutation IP(n)
         Real (SP), Intent (InOut) :: x (:, :) ! Input: m sets of RHSs B(n,m), 
                          ! Output: the corresponding sets of unknowns X(n,m)
         
         Integer :: n, m, i, j
        
         n = size(ip)
         m = size(x, dim=2)
         If (n<1.Or.m<1.Or.Any([n,n]/=shape(l)).Or.Any(shape(l)/=shape(u)).Or. &
            n/=size(x,dim=1)) Stop 91
         Do i = 1, m
            Do j = 1, n
               x(j,i) = x(j,i)-dot_product(x(:j-1,i),l(j,:j-1))
            End Do
            Do j = n, 1, -1
               x(j,i) = (x(j,i)-dot_product(x(j+1:,i),u(j,ip(j+1:)))) / &
                  u(j,ip(j))
            End Do
         End Do
      End Subroutine lusolve     
End Module mlu

C code example

/* INPUT: A - array of pointers to rows of a square matrix having dimension N
 *        Tol - small tolerance number to detect failure when the matrix is near degenerate
 * OUTPUT: Matrix A is changed, it contains a copy of both matrices L-E and U as A=(L-E)+U such that P*A=L*U.
 *        The permutation matrix is not stored as a matrix, but in an integer vector P of size N+1 
 *        containing column indexes where the permutation matrix has "1". The last element P[N]=S+N, 
 *        where S is the number of row exchanges needed for determinant computation, det(P)=(-1)^S    
 */
int LUPDecompose(double **A, int N, double Tol, int *P) {

    int i, j, k, imax; 
    double maxA, *ptr, absA;

    for (i = 0; i <= N; i++)
        P[i] = i; //Unit permutation matrix, P[N] initialized with N

    for (i = 0; i < N; i++) {
        maxA = 0.0;
        imax = i;

        for (k = i; k < N; k++)
            if ((absA = fabs(A[k][i])) > maxA) { 
                maxA = absA;
                imax = k;
            }

        if (maxA < Tol) return 0; //failure, matrix is degenerate

        if (imax != i) {
            //pivoting P
            j = P[i];
            P[i] = P[imax];
            P[imax] = j;

            //pivoting rows of A
            ptr = A[i];
            A[i] = A[imax];
            A[imax] = ptr;

            //counting pivots starting from N (for determinant)
            P[N]++;
        }

        for (j = i + 1; j < N; j++) {
            A[j][i] /= A[i][i];

            for (k = i + 1; k < N; k++)
                A[j][k] -= A[j][i] * A[i][k];
        }
    }

    return 1;  //decomposition done 
}

/* INPUT: A,P filled in LUPDecompose; b - rhs vector; N - dimension
 * OUTPUT: x - solution vector of A*x=b
 */
void LUPSolve(double **A, int *P, double *b, int N, double *x) {

    for (int i = 0; i < N; i++) {
        x[i] = b[P[i]];

        for (int k = 0; k < i; k++)
            x[i] -= A[i][k] * x[k];
    }

    for (int i = N - 1; i >= 0; i--) {
        for (int k = i + 1; k < N; k++)
            x[i] -= A[i][k] * x[k];

        x[i] /= A[i][i];
    }
}

/* INPUT: A,P filled in LUPDecompose; N - dimension
 * OUTPUT: IA is the inverse of the initial matrix
 */
void LUPInvert(double **A, int *P, int N, double **IA) {
  
    for (int j = 0; j < N; j++) {
        for (int i = 0; i < N; i++) {
            IA[i][j] = P[i] == j ? 1.0 : 0.0;

            for (int k = 0; k < i; k++)
                IA[i][j] -= A[i][k] * IA[k][j];
        }

        for (int i = N - 1; i >= 0; i--) {
            for (int k = i + 1; k < N; k++)
                IA[i][j] -= A[i][k] * IA[k][j];

            IA[i][j] /= A[i][i];
        }
    }
}

/* INPUT: A,P filled in LUPDecompose; N - dimension. 
 * OUTPUT: Function returns the determinant of the initial matrix
 */
double LUPDeterminant(double **A, int *P, int N) {

    double det = A[0][0];

    for (int i = 1; i < N; i++)
        det *= A[i][i];

    return (P[N] - N) % 2 == 0 ? det : -det;
}

C# code example

public class SystemOfLinearEquations
{
    public double[] SolveUsingLU(double[,] matrix, double[] rightPart, int n)
    {
        // decomposition of matrix
        double[,] lu = new double[n, n];
        double sum = 0;
        for (int i = 0; i < n; i++)
        {
            for (int j = i; j < n; j++)
            {
                sum = 0;
                for (int k = 0; k < i; k++)
                    sum += lu[i, k] * lu[k, j];
                lu[i, j] = matrix[i, j] - sum;
            }
            for (int j = i + 1; j < n; j++)
            {
                sum = 0;
                for (int k = 0; k < i; k++)
                    sum += lu[j, k] * lu[k, i];
                lu[j, i] = (1 / lu[i, i]) * (matrix[j, i] - sum);
            }
        }

        // lu = L+U-I
        // find solution of Ly = b
        double[] y = new double[n];
        for (int i = 0; i < n; i++)
        {
            sum = 0;
            for (int k = 0; k < i; k++)
                sum += lu[i, k] * y[k];
            y[i] = rightPart[i] - sum;
        }
        // find solution of Ux = y
        double[] x = new double[n];
        for (int i = n - 1; i >= 0; i--)
        {
            sum = 0;
            for (int k = i + 1; k < n; k++)
                sum += lu[i, k] * x[k];
            x[i] = (1 / lu[i, i]) * (y[i] - sum);
        }
        return x;
    }
}

MATLAB code example

function LU = LUDecompDoolittle(A)
    n = length(A);
    LU = A;
    for k = 2:n
        for i = 1 : k-1
            lamda = LU(k,i) / LU (i, i);
            LU(k,i) = lamda;
            LU(k,i+1:n) = LU(k,i+1:n) - LU(i,i+1:n) * lamda;
        end
    end
end

function x = SolveLinearSystem(LU, B)
    n = length(LU);
    y = zeros(size(B));
    % find solution of Ly = B
    for i = 1:n
        y(i,:) = B(i,:) - LU(i,1:i)*y(1:i,:);
    end
    % find solution of Ux = y
    x = zeros(size(B));
    for i = n:(-1):1
        x(i,:) = (y(i,:) - LU(i,(i + 1):n)*x((i + 1):n,:))/LU(i, i);
    end    
end

A = [ 4 3 3; 6 3 3; 3 4 3 ]
LU = LUDecompDoolittle(A)
B = [ 1 2 3; 4 5 6; 7 8 9; 10 11 12 ]'
x = SolveLinearSystem(LU, B)
A * x

See also

Notes

Template:Reflist

References

References

Computer code

Online resources

Template:Numerical linear algebra

de:GauรŸsches Eliminationsverfahren#LR-Zerlegung