<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://debianws.lexgopc.com/wiki143/index.php?action=history&amp;feed=atom&amp;title=Incomplete_Cholesky_factorization</id>
	<title>Incomplete Cholesky factorization - Revision history</title>
	<link rel="self" type="application/atom+xml" href="http://debianws.lexgopc.com/wiki143/index.php?action=history&amp;feed=atom&amp;title=Incomplete_Cholesky_factorization"/>
	<link rel="alternate" type="text/html" href="http://debianws.lexgopc.com/wiki143/index.php?title=Incomplete_Cholesky_factorization&amp;action=history"/>
	<updated>2026-10-26T23:54:51Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.1</generator>
	<entry>
		<id>http://debianws.lexgopc.com/wiki143/index.php?title=Incomplete_Cholesky_factorization&amp;diff=3956910&amp;oldid=prev</id>
		<title>imported&gt;RandFreeman: Adding short description: &quot;Approximation of a matrix&#039;s Cholesky factorization&quot;</title>
		<link rel="alternate" type="text/html" href="http://debianws.lexgopc.com/wiki143/index.php?title=Incomplete_Cholesky_factorization&amp;diff=3956910&amp;oldid=prev"/>
		<updated>2025-06-23T18:46:09Z</updated>

		<summary type="html">&lt;p&gt;Adding &lt;a href=&quot;https://en.wikipedia.org/wiki/Short_description&quot; class=&quot;extiw&quot; title=&quot;wikipedia:Short description&quot;&gt;short description&lt;/a&gt;: &amp;quot;Approximation of a matrix&amp;#039;s Cholesky factorization&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Short description|Approximation of a matrix&amp;#039;s Cholesky factorization}}&lt;br /&gt;
In [[numerical analysis]], an &amp;#039;&amp;#039;&amp;#039;incomplete Cholesky factorization&amp;#039;&amp;#039;&amp;#039; of a symmetric [[positive definite matrix]] is a [[sparse matrix|sparse]] approximation of the [[Cholesky factorization]]. An incomplete Cholesky factorization is often used as a [[preconditioner]] for algorithms like the [[conjugate gradient method]].&lt;br /&gt;
&lt;br /&gt;
The Cholesky factorization of a positive definite matrix &amp;#039;&amp;#039;A&amp;#039;&amp;#039; is &amp;#039;&amp;#039;A&amp;#039;&amp;#039; = &amp;#039;&amp;#039;LL&amp;#039;&amp;#039;* where &amp;#039;&amp;#039;L&amp;#039;&amp;#039; is a [[lower triangular matrix]]. An incomplete Cholesky factorization is given by a sparse lower triangular matrix &amp;#039;&amp;#039;K&amp;#039;&amp;#039; that is in some sense close to &amp;#039;&amp;#039;L&amp;#039;&amp;#039;. The corresponding preconditioner is &amp;#039;&amp;#039;KK&amp;#039;&amp;#039;*.&lt;br /&gt;
&lt;br /&gt;
One popular way to find such a matrix &amp;#039;&amp;#039;K&amp;#039;&amp;#039; is to use the algorithm for finding the exact Cholesky decomposition in which &amp;#039;&amp;#039;K&amp;#039;&amp;#039; has the same sparsity pattern as &amp;#039;&amp;#039;A&amp;#039;&amp;#039; (any entry of &amp;#039;&amp;#039;K&amp;#039;&amp;#039; is set to zero if the corresponding entry in &amp;#039;&amp;#039;A&amp;#039;&amp;#039; is also zero). This gives an incomplete Cholesky factorization which is as sparse as the matrix &amp;#039;&amp;#039;A&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
== Motivation ==&lt;br /&gt;
Consider the following matrix as an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{A}=\begin{bmatrix} 5 &amp;amp; -2 &amp;amp; 0 &amp;amp; -2 &amp;amp;-2\\ -2 &amp;amp; 5 &amp;amp; -2 &amp;amp; 0 &amp;amp; 0 \\ 0 &amp;amp; -2 &amp;amp; 5 &amp;amp; -2 &amp;amp; 0\\ -2 &amp;amp; 0 &amp;amp;-2 &amp;amp; 5 &amp;amp; -2\\ -2 &amp;amp; 0 &amp;amp; 0 &amp;amp;-2 &amp;amp; 5\\ \end{bmatrix}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If we apply the full regular [[Cholesky decomposition]], it yields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{L}=\begin{bmatrix} 2.24 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0\\ -0.89 &amp;amp; 2.05 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 \\ 0 &amp;amp; -0.98 &amp;amp; 2.02 &amp;amp; 0 &amp;amp; 0\\ -0.89 &amp;amp; -0.39 &amp;amp;-1.18 &amp;amp; 1.63 &amp;amp; 0\\ -0.89 &amp;amp; -0.39 &amp;amp; -0.19 &amp;amp; -1.95 &amp;amp; 0.45\\ \end{bmatrix}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And, by definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{A}=\mathbf{L}\mathbf{L&amp;#039;}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However, by applying Cholesky decomposition, we observe that some zero elements in the original matrix end up being non-zero elements in the decomposed matrix, like elements (4,2), (5,2) and (5,3) in this example. These elements are known as &amp;quot;fill-ins&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
This is not an issue per se, but it is very problematic when working with [[Sparse matrix|sparse matrices]], since the fill-ins generation is mostly unpredictable and reduces the matrix sparsity, impacting the efficiency of sparse matrix algorithms.&lt;br /&gt;
&lt;br /&gt;
Therefore, given the importance of the Cholesky decomposition in matrix calculations, it is extremely relevant to repurpose the regular method, so as to eliminate the fill-ins generation. The incomplete Cholesky factorization does exactly that, by generating a matrix L similar to the one generated by the regular method, but conserving the zero elements in the original matrix.&lt;br /&gt;
&lt;br /&gt;
Naturally:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{A}\neq\mathbf{L_{ichol}}\mathbf{L_{ichol} &amp;#039;}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Multiplying matrix L generated by incomplete Cholesky factorization by its transpose won&amp;#039;t yield the original matrix, but a similar one.&lt;br /&gt;
&lt;br /&gt;
== Algorithm ==&lt;br /&gt;
For &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; from &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; to &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
L_{ii}  = \left( {a_{ii}  - \sum\limits_{k = 1}^{i - 1} {L_{ik}^2 } } \right)^{{1 \over 2}} &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
For &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; from &amp;lt;math&amp;gt;i+1&amp;lt;/math&amp;gt; to &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;:&lt;br /&gt;
::&amp;lt;math&amp;gt;&lt;br /&gt;
L_{ji}  = {1 \over {L_{ii} }}\left( {a_{ji}  - \sum\limits_{k = 1}^{i - 1} {L_{ik} L_{jk} } } \right)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Implementation ==&lt;br /&gt;
&lt;br /&gt;
Implementation of the incomplete Cholesky factorization in the [[GNU Octave]] language. The factorization is stored as a lower triangular matrix, with the elements in the upper triangle set to zero.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;octave&amp;quot;&amp;gt;&lt;br /&gt;
function a = ichol(a)&lt;br /&gt;
	n = size(a,1);&lt;br /&gt;
&lt;br /&gt;
	for k = 1:n&lt;br /&gt;
		a(k,k) = sqrt(a(k,k));&lt;br /&gt;
		for i = (k+1):n&lt;br /&gt;
		    if (a(i,k) != 0)&lt;br /&gt;
		        a(i,k) = a(i,k)/a(k,k);            &lt;br /&gt;
		    endif&lt;br /&gt;
		endfor&lt;br /&gt;
		for j = (k+1):n&lt;br /&gt;
		    for i = j:n&lt;br /&gt;
		        if (a(i,j) != 0)&lt;br /&gt;
		            a(i,j) = a(i,j) - a(i,k)*a(j,k);  &lt;br /&gt;
		        endif&lt;br /&gt;
		    endfor&lt;br /&gt;
		endfor&lt;br /&gt;
	endfor&lt;br /&gt;
&lt;br /&gt;
    for i = 1:n&lt;br /&gt;
        for j = i+1:n&lt;br /&gt;
            a(i,j) = 0;&lt;br /&gt;
        endfor&lt;br /&gt;
    endfor            &lt;br /&gt;
endfunction&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sparse example ==&lt;br /&gt;
Consider again the matrix displayed in the beginning of this article. Since it is symmetric and the method only uses the lower triangular elements, we can represent it by:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{A_{tri}}=\begin{bmatrix} 5 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 \\ -2 &amp;amp; 5 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 \\ 0 &amp;amp; -2 &amp;amp; 5 &amp;amp; 0 &amp;amp; 0 \\ -2 &amp;amp; 0 &amp;amp; -2 &amp;amp; 5 &amp;amp; 0 \\ -2 &amp;amp; 0 &amp;amp; 0 &amp;amp; -2 &amp;amp; 5 \end{bmatrix}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
More specifically, in its sparse form as a coordinate list, sweeping rows first:&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Value	5	-2	-2	-2	5	-2	5	-2	5	-2	5&lt;br /&gt;
Row		1	2	4	5	2	3	3	4	4	5	5&lt;br /&gt;
Col		1	1	1	1	2	2	3	3	4	4	5&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Then, we take the square root of (1,1) and divide the other (i,1) elements by the result:&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Value	2.24 -0.89 -0.89 -0.89	| 5 -2 5 -2 5 -2 5&lt;br /&gt;
Row		1	  2	   4	 5	    | 2 3  3 4  4 5  5&lt;br /&gt;
Col		1	  1	   1  	 1	    | 2 2  3 3  4 4  5&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;After that, for all the other elements with column greater than 1, calculate (i,j)=(i,j)-(i,1)*(j,1) if (i,1) and (j,1) exist. For example: (5,4) = (5,4)-(5,1)*(4,1) = -2 -(-0.89*-0.89) = -2.8.&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Value	2.24 -0.89 -0.89 -0.89	| 4.2 -2 5 -2 4.2 -2.8 4.2&lt;br /&gt;
Row		1	  2	   4	 5	    | 2   3  3 4  4	  5    5&lt;br /&gt;
Col		1	  1	   1  	 1	    | 2   2  3 3  4	  4    5&lt;br /&gt;
                                  ↑           ↑   ↑    ↑&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;The elements (2,2), (4,4), (5,4) and (5,5) (marked with an arrow) have been recalculated, since they obey this rule. On the other hand, the elements (3,2), (3,3) and (4,3) won&amp;#039;t be recalculated since the element (3,1) doesn&amp;#039;t exist, even though the elements (2,1) and (4,1) exist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now, repeat the process, but for (i,2). Take the square root of (2,2) and divide the other (i,2) elements by the result:&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Value	2.24 -0.89 -0.89 -0.89	| 2.05 -0.98 | 5 -2 4.2 -2.8 4.2&lt;br /&gt;
Row		1	  2	   4	 5	    | 2    3     | 3  4 4   5    5&lt;br /&gt;
Col		1	  1	   1  	 1	    | 2    2     | 3  3 4   4    5&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Again, for elements with column greater than 2, calculate (i,j)=(i,j)-(i,2)*(j,2) if (i,2) and (j,2) exist:&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Value	2.24 -0.89 -0.89 -0.89	| 2.05 -0.98 | 4.05 -2 4.2 -2.8 4.2&lt;br /&gt;
Row		1	  2	   4	 5	    | 2    3     | 3    4  4   5    5&lt;br /&gt;
Col		1	  1	   1  	 1	    | 2    2     | 3    3  4   4    5&lt;br /&gt;
                                               ↑&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Repeat for (i,3). Take the square root of (3,3) and divide the other (i,3):&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Value	2.24 -0.89 -0.89 -0.89	2.05 -0.98 | 2.01 -0.99 | 4.2 -2.8 4.2&lt;br /&gt;
Row		1	  2	   4	 5	    2    3     | 3    4     | 4	  5    5&lt;br /&gt;
Col		1	  1	   1  	 1	    2    2     | 3    3     | 4	  4    5&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For elements with column greater than 3, calculate (i,j)=(i,j)-(i,3)*(j,3) if (i,3) and (j,3) exist:&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Value	2.24 -0.89 -0.89 -0.89	2.05 -0.98 | 2.01 -0.99 | 3.21 -2.8 4.2&lt;br /&gt;
Row		1	  2	   4	 5	    2    3     | 3    4     | 4	   5    5&lt;br /&gt;
Col		1	  1	   1  	 1	    2    2     | 3    3     | 4	   4    5&lt;br /&gt;
                                                          ↑&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Repeat for (i,4). Take the square root of (4,4) and divide the other (i,4):&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Value	2.24 -0.89 -0.89 -0.89	2.05 -0.98 2.01 -0.99 | 1.79 -1.56 | 4.2&lt;br /&gt;
Row		1	  2	   4	 5	    2    3     3    4     | 4	   5   | 5&lt;br /&gt;
Col		1	  1	   1  	 1	    2    2     3    3     | 4	   4   | 5&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;For elements with column greater than 4, calculate (i,j)=(i,j)-(i,4)*(j,4) if (i,4) and (j,4) exist:&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Value	2.24 -0.89 -0.89 -0.89	2.05 -0.98 2.01 -0.99 | 1.79 -1.56 | 1.76&lt;br /&gt;
Row		1	  2	   4	 5	    2    3     3    4     | 4	   5   | 5&lt;br /&gt;
Col		1	  1	   1  	 1	    2    2     3    3     | 4	   4   | 5&lt;br /&gt;
                                                                     ↑&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Finally take the square root of (5,5):&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Value	2.24 -0.89 -0.89 -0.89	2.05 -0.98 2.01 -0.99 1.79 -1.56 | 1.33&lt;br /&gt;
Row		1	  2	   4	 5	    2    3     3    4     4	   5     | 5&lt;br /&gt;
Col		1	  1	   1  	 1	    2    2     3    3     4	   4     | 5&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Expanding the matrix to its full form:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{L}=\begin{bmatrix} 2.24 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 \\ -0.89 &amp;amp; 2.05 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 \\ 0 &amp;amp; -0.98 &amp;amp; 2.01 &amp;amp; 0 &amp;amp; 0 \\ -0.89 &amp;amp; 0 &amp;amp; -0.99 &amp;amp; 1.79 &amp;amp; 0 \\ -0.89 &amp;amp; 0 &amp;amp; 0 &amp;amp; -1.56 &amp;amp; 1.33 \end{bmatrix}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that in this case no fill-ins were generated compared to the original matrix. The elements (4,2), (5,2) and (5,3) are still zero.&lt;br /&gt;
&lt;br /&gt;
However, if we perform the multiplication of L to its transpose:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mathbf{LL&amp;#039;}=\begin{bmatrix} 5 &amp;amp; -2 &amp;amp; 0 &amp;amp; -2 &amp;amp; -2 \\ -2 &amp;amp; 5 &amp;amp; -2 &amp;amp; 0.8 &amp;amp; 0.8 \\ 0 &amp;amp; -2 &amp;amp; 5 &amp;amp; -2 &amp;amp; 0 \\ -2 &amp;amp; 0.8 &amp;amp; -2 &amp;amp; 5 &amp;amp; -2 \\ -2 &amp;amp; 0.8 &amp;amp; 0 &amp;amp; -2 &amp;amp; 5 \end{bmatrix}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We get a matrix slightly different from the original one, since the decomposition didn&amp;#039;t take into account all the elements, in order to eliminate the fill-ins.&lt;br /&gt;
&lt;br /&gt;
== Sparse implementation ==&lt;br /&gt;
The sparse version for the incomplete Cholesky factorization (the same procedure presented above) implemented in [[MATLAB]] can be seen below. Naturally, MATLAB has its own means for dealing with sparse matrixes, but the code below was made explicit for pedagogic purposes. This algorithm is efficient, since it treats the matrix as a sequential 1D array, automatically avoiding the zero elements.&amp;lt;syntaxhighlight lang=&amp;quot;matlab&amp;quot;&amp;gt;&lt;br /&gt;
function A=Sp_ichol(A)&lt;br /&gt;
	n=size(A,1);&lt;br /&gt;
	ncols=A(n).col;&lt;br /&gt;
    c_end=0;&lt;br /&gt;
    for col=1:ncols&lt;br /&gt;
        is_next_col=0;&lt;br /&gt;
        c_start=c_end+1;&lt;br /&gt;
        for i=c_start:n&lt;br /&gt;
            if A(i).col==col % in the current column (col):&lt;br /&gt;
                if A(i).col==A(i).row &lt;br /&gt;
                    A(i).val=sqrt(A(i).val); % take the square root of the current column&amp;#039;s diagonal element&lt;br /&gt;
                    div=A(i).val;&lt;br /&gt;
                else&lt;br /&gt;
                    A(i).val=A(i).val/div; % divide the other current column&amp;#039;s elements by the square root of the diagonal element&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            if A(i).col&amp;gt;col % in the next columns (col+1 ... ncols):&lt;br /&gt;
                if is_next_col==0&lt;br /&gt;
                    c_end=i-1;&lt;br /&gt;
                    is_next_col=1;&lt;br /&gt;
                end&lt;br /&gt;
                v1=0;&lt;br /&gt;
                v2=0;&lt;br /&gt;
                for j=c_start:c_end&lt;br /&gt;
                    if A(j).col==col&lt;br /&gt;
                        if A(j).row==A(i).row % search for current column&amp;#039;s (col) elements A(j) whose row index is the same as current element&amp;#039;s A(i) row index&lt;br /&gt;
                            v1=A(j).val;&lt;br /&gt;
                        end&lt;br /&gt;
                        if A(j).row==A(i).col % search for current column&amp;#039;s (col) elements A(j) whose row index is the same as current element&amp;#039;s A(i) column index&lt;br /&gt;
                            v2=A(j).val;&lt;br /&gt;
                        end&lt;br /&gt;
                        if v1~=0 &amp;amp;&amp;amp; v2~=0 % if these elements exist in the current column (col), recalculate the current element A(i):&lt;br /&gt;
                            A(i).val=A(i).val-v1*v2;&lt;br /&gt;
                            break;&lt;br /&gt;
                        end&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
* [http://www.cfd-online.com/Wiki/Incomplete_Cholesky_factorization Incomplete Cholesky factorization] at CFD Online wiki&lt;br /&gt;
* {{Citation | last1=Golub | first1=Gene H. | author1-link=Gene H. Golub | last2=Van Loan | first2=Charles F. | author2-link=Charles F. Van Loan | title=Matrix Computations | publisher=Johns Hopkins | edition=3rd | isbn=978-0-8018-5414-9 | year=1996}}. See Section 10.3.2.&lt;br /&gt;
&lt;br /&gt;
{{Numerical linear algebra}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Numerical linear algebra]]&lt;/div&gt;</summary>
		<author><name>imported&gt;RandFreeman</name></author>
	</entry>
</feed>