1.矩阵三角分解原理
设
A
A
A为非奇异矩阵,且有分解式
A
=
L
U
,
A=LU,
A=LU,
A
=
[
a
11
a
12
…
a
1
n
a
21
a
21
…
a
2
n
⋮
⋮
⋮
a
n
1
a
n
1
…
a
n
n
]
A=\begin{bmatrix} a_{11}&a_{12}&\ldots&a_{1n}\\ a_{21}&a_{21}&\ldots&a_{2n}\\ \vdots&\vdots&&\vdots\\ a_{n1}&a_{n1}&\ldots&a_{nn} \end{bmatrix}
A=⎣⎢⎢⎢⎡a11a21⋮an1a12a21⋮an1………a1na2n⋮ann⎦⎥⎥⎥⎤
其中
L
L
L为单位下三角矩阵,
U
U
U为上三角矩阵,即
A
=
[
1
l
21
1
⋮
⋮
⋱
l
n
1
l
n
2
…
1
]
[
u
11
u
12
…
u
1
n
u
22
…
u
2
n
⋱
⋮
u
n
n
]
A=\begin{bmatrix} 1&&&\\ l_{21}&1&&\\ \vdots&\vdots&\ddots&\\ l_{n1}&l_{n2}&\ldots&1 \end{bmatrix} \begin{bmatrix} u_{11}&u_{12}&\ldots&u_{1n}\\ &u_{22}&\ldots&u_{2n}\\ &&\ddots&\vdots\\ &&&u_{nn} \end{bmatrix}
A=⎣⎢⎢⎢⎡1l21⋮ln11⋮ln2⋱…1⎦⎥⎥⎥⎤⎣⎢⎢⎢⎡u11u12u22……⋱u1nu2n⋮unn⎦⎥⎥⎥⎤
下面说明
L
,
U
L,U
L,U的元素可以由
n
n
n步直接定出,其中第
r
r
r步定出
U
U
U的第
r
r
r行和
L
L
L的第
r
r
r列.由上述分解式有
a
1
i
=
u
1
i
,
i
=
1
,
2
,
…
,
n
,
a_{1i}=u_{1i},i=1,2,\ldots,n,
a1i=u1i,i=1,2,…,n,
得到
U
U
U的第
1
1
1行元素;
a
i
1
=
l
i
1
u
11
,
l
i
1
=
a
i
1
/
u
11
,
i
=
2
,
3
,
…
,
n
,
a_{i1}=l_{i1}u_{11},l_{i1}=a_{i1}/u_{11},i=2,3,\ldots,n,
ai1=li1u11,li1=ai1/u11,i=2,3,…,n,
得到
L
L
L的第
1
1
1列元素.
设已经定出
U
U
U的第1行到第
r
−
1
r-1
r−1列元素.有上述分解式,利用矩阵乘法(注意当
r
<
k
,
l
r
k
=
0
r <k,l_{rk}=0
r<k,lrk=0),有
a
r
i
=
∑
k
=
1
n
l
r
k
u
k
i
=
∑
k
=
1
r
−
1
l
r
k
u
k
i
+
u
r
i
,
a_{ri}=\sum_{k = 1}^{n}l_{rk}u_{ki}=\sum_{k = 1}^{r-1}l_{rk}u_{ki}+u_{ri},
ari=k=1∑nlrkuki=k=1∑r−1lrkuki+uri,
故
u
r
i
=
a
r
i
−
∑
k
=
1
r
−
1
l
r
k
u
k
i
,
i
=
r
,
r
+
1
,
…
,
n
.
u_{ri}=a_{ri}-\sum_{k = 1}^{r-1}l_{rk}u_{ki},i=r,r+1,\ldots,n.
uri=ari−k=1∑r−1lrkuki,i=r,r+1,…,n.
又由该分解式有
a
i
r
=
∑
k
=
1
n
l
i
k
u
k
r
=
∑
k
=
1
r
−
1
l
i
k
u
k
r
+
l
i
r
u
r
r
.
a_{ir}=\sum_{k = 1}^{n}l_{ik}u_{kr}=\sum_{k = 1}^{r-1}l_{ik}u_{kr}+l_{ir}u_{rr}.
air=k=1∑nlikukr=k=1∑r−1likukr+lirurr.
总结上述讨论,得到直接三角分解法解
A
x
=
b
Ax=b
Ax=b(要求
A
A
A的所有顺序主子式都不为零)的计算公式.
-
u
1
i
=
a
1
i
(
i
=
1
,
2
,
…
,
n
)
,
l
i
1
=
a
i
1
/
u
11
,
i
=
2
,
3
,
…
,
n
.
u_{1i}=a_{1i}(i=1,2,\ldots,n),l_{i1}=a_{i1}/u_{11},i=2,3,\ldots,n.
u1i=a1i(i=1,2,…,n),li1=ai1/u11,i=2,3,…,n.
计算 U U U的第 r r r行, L L L的第 r r r列元素 ( r = 2 , 3 , … , n ) : (r=2,3,\ldots,n): (r=2,3,…,n): - u r i = a r i − ∑ k = 1 r − 1 l r k u k i , i = r , r + 1 , … , n ; u_{ri}=a_{ri}-\sum\limits_{k = 1}^{r-1}l_{rk}u_{ki},i=r,r+1,\ldots,n; uri=ari−k=1∑r−1lrkuki,i=r,r+1,…,n;
-
l
i
r
=
(
a
i
r
−
∑
k
=
1
r
−
1
l
i
k
u
k
r
)
/
u
r
r
,
i
=
r
+
1
,
…
,
n
,
且
r
≠
n
.
l_{ir}=(a_{ir}-\sum\limits_{k = 1}^{r-1}l_{ik}u_{kr})/u_{rr},i=r+1,\ldots,n,\text{且}r \ne n.
lir=(air−k=1∑r−1likukr)/urr,i=r+1,…,n,且r=n.
求解 L y = b , U x = y Ly=b,Ux=y Ly=b,Ux=y的计算公式: - { y 1 = b 1 , y i = b i − ∑ k = 1 i − 1 l i k y k , i = 2 , 3 , … , n ; \begin{cases} y_1=b_1,\\ y_i=b_i-\sum\limits_{k = 1}^{i-1}l_{ik}y_k,i=2,3,\ldots,n; \end{cases} ⎩⎨⎧y1=b1,yi=bi−k=1∑i−1likyk,i=2,3,…,n;
- { x n = y n / u n n , x i = ( y i − ∑ k = i + 1 n u i k x k ) / u i i , i = n − 1 , n − 2 , … , 1. \begin{cases} x_n=y_n/u_{nn},\\ x_i=(y_i-\sum\limits_{k=i+1}^{n}u_{ik}x_k)/u_{ii},i=n-1,n-2,\ldots,1. \end{cases} ⎩⎨⎧xn=yn/unn,xi=(yi−k=i+1∑nuikxk)/uii,i=n−1,n−2,…,1.
2.Python实现不选主元矩阵三角分解
# 自己原创
def triangle_decomposition(coefficient_matrix: np.ndarray):
"""
实现方程Ax=b系数矩阵A的Doolittle decomposition
:param coefficient_matrix: 初始系数矩阵A
:return: 单位下三角矩阵L,上三角矩阵U
"""
# first step: evaluate the decomposition condition
rows, columns = coefficient_matrix.shape
if rows == columns: # judge if it is a square matrix
for k in range(rows): # 判断各阶顺序主子式是否为0
if det(coefficient_matrix[:k + 1, :k + 1]) == 0:
raise Exception("cannot decompose ")
else:
# directive triangle decomposition
# 初始化
square_ones_matrix = np.ones((rows, columns))
lower_triangle_matrix = np.tril(square_ones_matrix)
upper_triangle_matrix = np.triu(square_ones_matrix)
# 计算第1行的U(1,i),第1列的L(i,1)
upper_triangle_matrix[0, :] = coefficient_matrix[0, :]
lower_triangle_matrix[1:, 0] = coefficient_matrix[1:, 0] / upper_triangle_matrix[0, 0]
# 计算第row行的U(row,i),第row列的L(i,row)
for row in range(1, rows - 1):
for i in range(row, rows):
# 定义一个累积和变量
row_i_prod = 0
for k in range(row):
row_i_prod += lower_triangle_matrix[row, k] * upper_triangle_matrix[k, i]
upper_triangle_matrix[row, i] = coefficient_matrix[row, i] - row_i_prod
for i in range(row + 1, rows):
# 定义一个累积和变量
i_row_prod = 0
for k in range(row):
i_row_prod += lower_triangle_matrix[i, k] * upper_triangle_matrix[k, row]
lower_triangle_matrix[i, row] = (coefficient_matrix[i, row] - i_row_prod) / upper_triangle_matrix[
row, row]
# 定义一个累积和变量,单独计算n行n列的U(n,n)
row_i_prod = 0
for k in range(rows - 1):
row_i_prod += lower_triangle_matrix[rows - 1, k] * upper_triangle_matrix[k, rows - 1]
upper_triangle_matrix[rows - 1, rows - 1] = coefficient_matrix[rows - 1, rows - 1] - row_i_prod
return lower_triangle_matrix, upper_triangle_matrix
else:
raise Exception("ERROR:please pass a square matrix.")
# 自己原创
def directive_triangle_decomposition(coefficient_matrix: np.ndarray, right_hand_side_vector: np.ndarray,
decomposition_function=triangle_decomposition):
"""
实现方程Ax=b系数矩阵A directive triangle decomposition
:param decomposition_function: 三角分解函数
:param coefficient_matrix: 初始系数矩阵A
:param right_hand_side_vector: 初始常数列向量b
:return: 解向量x
"""
l, u = decomposition_function(coefficient_matrix)
rows, columns = coefficient_matrix.shape
# Ly=b,此处不指定双精度浮点数据类型,则可能会损失精度,导致结果偏差太大
y = np.ones_like(right_hand_side_vector, dtype=np.float64)
y[0, 0] = right_hand_side_vector[0, 0]
for row in range(1, rows):
# 定义一个累积和变量
i_k_prod = 0
for k in range(row):
i_k_prod += l[row, k] * y[k, 0]
y[row, 0] = right_hand_side_vector[row, 0] - i_k_prod
# Ux=y,此处不指定双精度浮点数据类型,则可能会损失精度,导致结果偏差太大
x = np.ones_like(right_hand_side_vector, dtype=np.float64)
x[rows - 1] = y[rows - 1] / u[rows - 1, rows - 1]
for row in range(rows - 2, 0, -1):
i_k_prod = 0
for k in range(row + 1, rows):
i_k_prod += u[row, k] * x[k, 0]
x[row, 0] = (y[row, 0] - i_k_prod) / u[row, row]
return x
3.解方程
用直接三角分解法解 [ 1 2 3 2 5 2 3 1 5 ] [ x 1 x 2 x 3 ] = [ 14 18 20 ] \begin{bmatrix} 1&2&3\\ 2&5&2\\ 3&1&5 \end{bmatrix} \begin{bmatrix} x_1\\ x_2\\ x_3 \end{bmatrix}= \begin{bmatrix} 14\\ 18\\ 20 \end{bmatrix} ⎣⎡123251325⎦⎤⎣⎡x1x2x3⎦⎤=⎣⎡141820⎦⎤
4.测试
if __name__ == '__main__':
# 直接三角分解法-不选主元三角分解法测试成功,来源详见李庆扬数值分析第5版P153,e.g.5
square_matrix = np.array([[1, 2, 3], [2, 5, 2], [3, 1, 5]])
column_vector = np.array([14, 18, 20]).reshape((3, 1))
print(directive_triangle_decomposition(square_matrix, column_vector))