平方根法求解對稱正定方程組
1.對稱正定矩陣三角分解或Cholesky分解定理
如果
A
A
A為
n
n
n階對稱正定矩陣,則存在一個實的非奇異下三角矩陣
L
L
L使
A
=
L
L
T
A=LL^T
A=LLT,當限定
L
L
L的對角元素為正時,這種分解是唯一的.
下面用直接分解方法來確定計算
L
L
L元素的遞推公式.因為
A
=
[
l
11
l
21
l
22
⋮
⋮
⋱
l
n
1
l
n
2
…
l
n
n
]
[
l
11
l
21
…
l
n
1
l
22
…
l
n
2
⋱
⋮
l
n
n
]
A=\begin{bmatrix} l_{11}&&&\\ l_{21}&l_{22}&&\\ \vdots&\vdots&\ddots&\\ l_{n1}&l_{n2}&\ldots&l_{nn} \end{bmatrix} \begin{bmatrix} l_{11}&l_{21}&\ldots&l_{n1}\\ &l_{22}&\ldots&l_{n2}\\ &&\ddots&\vdots\\ &&&l_{nn} \end{bmatrix}
其中
l
i
i
>
0
(
i
=
1
,
2
,
…
,
n
)
.
l_{ii}>0(i=1,2,\ldots,n).
lii>0(i=1,2,…,n).由矩陣乘法及
l
j
k
=
0
(
當
j
<
k
時
)
,
得
l_{jk}=0(當j<k時),得
ljk=0(當j<k時),得
a
i
j
=
∑
k
=
1
n
l
i
k
l
j
k
=
∑
k
=
1
j
−
1
l
i
k
l
j
k
+
l
j
j
l
i
j
,
a_{ij}=\sum_{k=1}^{n}l_{ik}l_{jk}=\sum_{k=1}^{j-1}l_{ik}l_{jk}+l_{jj}l_{ij},
於是得到解對稱正定方程組
A
x
=
b
Ax=b
Ax=b的平方根計算公式:
對於
j
=
1
,
2
,
…
,
n
j=1,2,\ldots,n
j=1,2,…,n
(
1
)
l
j
j
=
(
a
j
j
−
∑
k
=
1
j
−
1
l
j
k
2
)
1
2
;
(1)l_{jj}=(a_{jj}-\sum\limits_{k=1}^{j-1}l_{jk}^2)^{\frac{1}{2}};
(1)ljj=(ajj−k=1∑j−1ljk2)21;
(
2
)
l
i
j
=
(
a
i
j
−
∑
k
=
1
j
−
1
l
i
k
l
j
k
)
/
l
j
j
,
i
=
j
+
1
,
…
,
n
.
(2)l_{ij}=(a_{ij}-\sum\limits_{k=1}^{j-1}l_{ik}l_{jk})/l_{jj},i=j+1,\ldots,n.
求解
A
x
=
b
,
Ax=b,
Ax=b,即求解兩個三角形方程組:
1.
L
y
=
b
,
求
y
;
Ly=b,求y;\quad\quad\quad\quad
Ly=b,求y; 2.
L
T
x
=
y
,
求
x
.
L^Tx=y,求x.
LTx=y,求x.
(
3
)
y
i
=
(
b
i
−
∑
k
=
1
i
−
1
l
i
k
y
k
)
/
l
i
i
,
i
=
1
,
2
,
…
,
n
.
(3)y_i=(b_i-\sum\limits_{k=1}^{i-1}l_{ik}y_k)/l_{ii},i=1,2,\ldots,n.
(3)yi=(bi−k=1∑i−1likyk)/lii,i=1,2,…,n.
(
4
)
x
i
=
(
b
i
−
∑
k
=
i
+
1
n
l
k
i
x
k
)
/
l
i
i
,
i
=
n
,
n
−
1
,
…
,
1.
(4)x_i=(b_i-\sum\limits_{k=i+1}^{n}l_{ki}x_k)/l_{ii},i=n,n-1,\ldots,1.
(4)xi=(bi−k=i+1∑nlkixk)/lii,i=n,n−1,…,1.
2.Python實現平方根法
# 自己原創平方根法
def cholesky_decomposition(sym_pos_define_matrix: np.ndarray, right_hand_side_vector: np.ndarray):
rows, columns = sym_pos_define_matrix.shape
# judge if it is a square matrix
if rows == columns:
# 判斷是否對稱
if (sym_pos_define_matrix.T == sym_pos_define_matrix).all():
for k in range(rows): # 判斷各階順序主子式是否為0,即判定是否正定
if det(sym_pos_define_matrix[:k + 1, :k + 1]) <= 0:
raise Exception("cannot decompose")
else:
# 初始化單位下三角矩陣L
square_ones_matrix = np.ones((rows, columns))
lower_triangle_matrix = np.tril(square_ones_matrix)
for j in range(rows):
prod = 0
for k in range(j):
prod += lower_triangle_matrix[j, k] * lower_triangle_matrix[j, k]
lower_triangle_matrix[j, j] = np.sqrt(sym_pos_define_matrix[j, j] - prod)
for i in range(j + 1, rows):
prod = 0
for k in range(j):
prod += lower_triangle_matrix[i, k] * lower_triangle_matrix[j, k]
lower_triangle_matrix[i, j] = (sym_pos_define_matrix[i, j] - prod) / lower_triangle_matrix[j, j]
else:
raise Exception("error,the input matrix must be a symmetric-matrix")
else:
raise Exception("ERROR:please pass a square matrix.")
return inv(lower_triangle_matrix.transpose()) @ inv(lower_triangle_matrix) @ right_hand_side_vector
3.平方根解對稱正定矩陣方程組
[ 4 2 − 4 0 2 4 0 0 2 2 − 1 − 2 1 3 2 0 − 4 − 1 14 1 − 8 − 3 5 6 0 − 2 1 6 − 1 − 4 − 3 3 2 1 − 8 − 1 22 4 − 10 − 3 4 3 − 3 − 4 4 11 1 − 4 0 2 5 − 3 − 10 1 14 2 0 0 6 3 − 3 − 4 2 19 ] [ x 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 ] = [ 0 − 6 20 23 9 − 22 − 15 45 ] \begin{bmatrix} 4&2&-4&0&2&4&0&0\\ 2&2&-1&-2&1&3&2&0\\ -4&-1&14&1&-8&-3&5&6\\ 0&-2&1&6&-1&-4&-3&3\\ 2&1&-8&-1&22&4&-10&-3\\ 4&3&-3&-4&4&11&1&-4\\ 0&2&5&-3&-10&1&14&2\\ 0&0&6&3&-3&-4&2&19 \end{bmatrix} \begin{bmatrix} x1\\ x2\\ x3\\ x4\\ x5\\ x6\\ x7\\ x8\\ \end{bmatrix}= \begin{bmatrix} 0\\-6\\20\\23\\9\\-22\\-15\\45 \end{bmatrix} ⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡42−40240022−1−21320−4−1141−8−3560−216−1−4−3321−8−1224−10−343−3−44111−4025−3−1011420063−3−4219⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡x1x2x3x4x5x6x7x8⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡0−620239−22−1545⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤
4.測試
if __name__ == '__main__':
symmetric_positive_define_matrix2 = np.array([[4, 2, -4, 0, 2, 4, 0, 0],
[2, 2, -1, -2, 1, 3, 2, 0],
[-4, -1, 14, 1, -8, -3, 5, 6],
[0, -2, 1, 6, -1, -4, -3, 3],
[2, 1, -8, -1, 22, 4, -10, -3],
[4, 3, -3, -4, 4, 11, 1, -4],
[0, 2, 5, -3, -10, 1, 14, 2],
[0, 0, 6, 3, -3, -4, 2, 19]],dtype=np.float64)
column_vector = np.array([0, -6, 20, 23, 9, -22, -15, 45],dtype=np.float64).reshape((8, 1))
print(cholesky_decomposition(symmetric_positive_define_matrix2, column_vector))