柯列斯基分解cholesky decomposition只能用于实对称正定矩阵,实对称正定矩阵一般用于定义内积。柯列斯基分解是将矩阵分解为如下形式:
A = G G T A=GG^T A=GGT
其中 G G G是下三角矩阵。柯列斯基分解主要有两种算法:LU分解法和递推算法。
LU分解法主要分三步:
# 柯列斯基分解
def cholesky(self):
l, u = self.lu_decomposition()
# u的对角线元素开根号
n = len(self.__vectors)
d_array = [
[math.sqrt(u.vectors[i][j]) if i == j else 0 for j in range(n)]
for i in range(n)
]
d = Matrix(d_array)
return l * d, d * u
递推算法利用的是两个分解出来的矩阵是互为转置的特点进行的。按列进行主循环迭代,每个迭代步骤主要分两小步:
对角线元素使用公式就好了。利用以下迭代公式:
g i i = a i i − ∑ k = 1 i − 1 g i k 2 g_{ii}=\sqrt{a_{ii}-\sum_{k=1}^{i-1}g_{ik}^2} gii=aii−k=1∑i−1gik2
非对角线元素使用下面这个公式:
g j i = 1 g i i ( a i j − ∑ k = 1 i − 1 g i k g j k ) g_{ji}=\frac1{g_{ii}}(a_{ij}-\sum_{k=1}^{i-1}g_{ik}g_{jk}) gji=gii1(aij−k=1∑i−1gikgjk)
算法清晰了,python代码就容易了:
# 柯列斯基分解迭代法
def cholesky_iterate(self):
n = len(self.__vectors)
array = [[0 for _ in range(n)] for _ in range(n)]
for i in range(n):
# 对角线元素
s = 0
for k in range(i):
s += array[k][i] * array[k][i]
array[i][i] = math.sqrt(self.__vectors[i][i] - s)
# 非对角线元素
for j in range(i+1,n):
s1 = 0
for k in range(i):
s1 += array[k][i] * array[k][j]
array[i][j] = (self.__vectors[j][i] - s1) / array[i][i]
matrix = Matrix(array)
return matrix, Matrix(matrix.transpose())