求解线性方程组
在线性代数中,有一类经典问题,就是求解线性方程组,我们熟知的解法有高斯消元法,但是高斯消元法属于直接求解的方法,不适合编程计算,因此引入更适合计算机求解的迭代法。
以线性方程组:
$
\left[
\begin{matrix}
10 & -1 & -2 \
-1 & 10 & -2 \
-1 & -1 & 5
\end{matrix}
\right] x =
\left[
\begin{matrix}
7.2 \
8.3 \
4.2
\end{matrix}
\right]
$
为例
Jacobi迭代法
考虑线性方程组$Ax=b$
用L和U分别表示严格下三角矩阵和严格上三角矩阵
可以利用迭代公式
$x^{k+1}=D^{-1}(b-(L+U)x^{k}))$
进行迭代求解,可以通过精度控制迭代次数,还需要控制迭代是否收敛,不然迭代次数再多也无法求解。
迭代法需要给定解列向量的初值,因此初值的选取也很重要。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
import numpy as np
def Jacobi(A, B, N, x):
# Ax=B N为迭代次数
# 获得对角矩阵的数组
D = np.diag(A)
# 获得L+U矩阵,减去对角矩阵即可
# diagflat为D数组转为对角矩阵
R = A - np.diagflat(D)
# R = L + U
print(R/D)
for i in range(N):
# 迭代过程,可以直接/D表示逆矩阵
x = (B - np.dot(R, x))/D
return x
A = np.array([[10, -1, -2], [-1, 10, -2], [-1, -1, 5]] )
B = np.array([7.2, 8.3, 4.2])
# 设定迭代初始值
x = np.array([1, 1, 1])
answer = Jacobi(A, B, 30, x)
print(answer)
|
求解结果为
x = [1.1, 1.2, 1.3]
Gauss Seidel迭代法
Gauss Seidel法使用了另一种迭代格式,获得了快的收敛速度
首先我们利用迭代求解的特性,新得到的值总会比老值更优,因此使用新值来进行迭代,即
$x^{k+1}=D^{-1}(b+Lx^{k+1}+Ux^k)$
化简
$x^{k+1}=(D-L)^{-1}(Ux^k+b)$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
import numpy as np
def GaussSeidel(A, B, N, x):
# 下三角矩阵
L = np.tril(A)
# 严格上三角矩阵
U = A - L
# 获得对角矩阵
D = np.diagflat(np.diag(A))
LL = L - D
# x^{k+1} = (D + L)^-1 (b - Ux^{k})
# 输出迭代矩阵
print(np.dot(np.linalg.inv(D-LL), U))
for i in range(N):
# 使用linalg包中的inv函数求出L矩阵的逆矩阵
# 使用上述迭代公式求解
x = np.dot(np.linalg.inv(L), B - np.dot(U, x))
return x
A = np.array([[10, -1, -2], [-1, 10, -2], [-1, -1, 5]] )
B = np.array([7.2, 8.3, 4.2])
# 设定迭代初始值
x = np.array([1, 1, 1])
answer = GaussSeidel(A, B, 30, x)
print(answer)
|
解得x = [1.1, 1.2, 1.3]