The Cholesky decomposition
The Cholesky decomposition is another way of solving systems of linear equations. It can
be significantly faster and uses a lot less memory than the LU decomposition, by exploiting
the property of symmetric matrices. However, the matrix being decomposed must be
Hermitian (or real-valued symmetric and thus square) and positive definite. This means
that the Amatrix is decomposed as A=LLT, where L is a lower triangular matrix with real and
positive numbers on the diagonals, and LT is the conjugate transpose of L.
Let's consider another example of a system of linear equations where the Amatrix is both
Hermitian and positive definite. Again, the equation is in the form of Ax=B,
where A and B take the following values:
Let's represent these matrices as NumPy arrays:
In [ ]:
"""
Cholesky decomposition with NumPy
"""
import numpy as np
A = np.array([
[10., -1., 2., 0.],
[-1., 11., -1., 3.],
[2., -1., 10., -1.],
[0., 3., -1., 8.]])
B = np.array([6., 25., -11., 15.])
L = np.linalg.cholesky(A)
The cholesky() function of numpy.linalg would compute the lower triangular factor of
the A matrix. Let's view the lower triangular matrix:
In [ ]:
In [ ]:
print(L)
Out[ ]:
[[ 3.16227766 0. 0. 0. ]
[-0.31622777 3.3015148 0. 0. ]
[ 0.63245553 -0.24231301 3.08889696 0. ]
[ 0. 0.9086738 -0.25245792 2.6665665 ]]
To verify that the Cholesky decomposition results are correct, we can use the definition of
the Cholesky factorization by multiplying L by its conjugate transpose, which will lead us
back to the values of the A matrix:
In [ ]:
print(np.dot(L, L.T.conj())) # A=L.L*
Out [ ]:
[[10. -1. 2. 0.]
[-1. 11. -1. 3.]
[ 2. -1. 10. -1.]
[ 0. 3. -1. 8.]]
Before solving for x, we need to solve for LTx as y. Let's use the solve() method of numpy.linalg:
In [ ]:
y = np.linalg.solve(L, B) # L.L*.x=B; When L*.x=y, then L.y=B
To solve for x, we need to solve again using the conjugate transpose of L andy:
In [ ]:
x = np.linalg.solve(L.T.conj(), y) # x=L*'.y
Let's print our result of x:
In [ ]:
print(x)
Out[ ]:
[ 1. 2. -1. 1.]
The output gives us our values of x for a, b, c, and d.
To show that the Cholesky factorization gives us the correct values, we can verify the answer
by multiplying the A matrix by the transpose of x to return the values of B:
In [ ] :
print(np.mat(A) * np.mat(x).T) # B=Ax
Out[ ]:
[[ 6.]
[ 25.]
[-11.]
[ 15.]]
This shows that the values of x by the Cholesky decomposition would lead to the same values given by B.