线性方程组求解的迭代方法&Python实现

目录

1 线性方程组迭代法概述

2 Jacobi迭代法和Gauss-Seidel迭代法

3 程序实现流程

 4 案例及Python代码


1 线性方程组迭代法概述

设线性方程组为

Ax=b

其中A为非奇异,且b≠0,则线性方程组存在唯一非零解x*。令A=M-N,其中M为非奇异,则上述公式可以改写成等价方程组:

x=Gx+f

其中,G=M^{-1}N,f=M^{-1}b。则可以得到迭代公式:

x_{n+1}=Gx_n+f

如果序列{{x_n}}是收敛的,则有:

\lim_{n\rightarrow \infty }x_n=x*.

2 Jacobi迭代法和Gauss-Seidel迭代法

M=\begin{bmatrix} a_1_1 & 0&...& 0\\ 0&a_2_2 & ...& 0\\ ...& ...& ... &... \\ 0& 0& ...& a_n_n \end{bmatrix},      N=\begin{bmatrix} 0 &a_1_2 &...&a_1_n \\ a_2_1& 0 & ...&a_2_n \\ ... & ...&... & ...\\ a_n_1& a_n_2 & ... & 0 \end{bmatrix}

则等价方程x=Gx+f可表示为:

其中,G=M^{-1}N,f=M^{-1}b。 

任取始解向量x^{(0)}=(x^{(0)}_1,x^{(0)}_2,...,x^{(0)}_n)^T,代入等价方程组可得迭代公式:

x^{(k+1)}=Gx^{(k)}+f,(k=0,1,2,...,n)

其分量形式可以表示为:

上述的迭代公式称为 Jacobi迭代法,简称J法。

如果将上式改为:

则称为Gauss-Seidel迭代法,简称G-S法。

G-S法和J法的不同点在于:每得到一个新分量x^{k+1}_i时,在计算以下各分量时,用x^{k+1}_i代替旧的x^k_i,因为新分量比旧分量更接近于真实解x_i*

3 程序实现流程

Jacobi迭代法:

Gauss-Seidel迭代法:

 

 4 案例及Python代码

已知线性方程组:

 采用 Jacobi迭代法和Gauss-Seidel迭代法求解上述方程组的解,误差要求为10^-^9,输出线性方程组的解以及迭代次数。

Python代码:

① Jacobi迭代法

#-----Jacobi迭代法求解上述方程组的解
import numpy as np
A=np.array([[4,-1,2],[2,-5,1],[-2,1,4]])
b=np.array([[7,-1,6]]).T
e=10**-9 #误差
N=10000 #最大迭代次数
n=len(b)
x0=np.zeros((n,1)) #迭代初值
x1=np.zeros((n,1)) #输出矩阵初始化
L_J=0 #初始化Jacobi迭代法的迭代次数
#-----Jacobi迭代法-----#
for i in range(N):
    for j in range(n):
      index=np.append(np.arange(0,j),np.arange(j+1,n)) #剔除掉j之后的线性序列
      x1[j]=(b[j]-A[j,index]@x0[index])/A[j,j] #迭代公式
    L_J=L_J+1 #累计迭代次数
    if max(abs(A@x1-b))<e: #利用残差判断
        break
    x0 = x1  # 更新初始向量
print(f"x1={x1}") #输出线性方程组的解
print(A@x1-b) #验证解的正确性
print(f"L_J={L_J}") #输出迭代次数

运行结果:

x1=[[1.1]
 [1. ]
 [1.8]]
[[6.65227873e-10]
 [3.32616823e-10]
 [0.00000000e+00]]
L_J=16

 ② Gauss-Seidel迭代法

#Gauss-Seidel迭代法求解上述方程组的解
import numpy as np
A=np.array([[4,-1,2],[2,-5,1],[-2,1,4]])
b=np.array([[7,-1,6]]).T
e=10**-9 #误差
max_number=10000 #最大迭代次数
n=len(b)
x0=np.zeros((n,1)) #迭代初值
x1=np.zeros((n,1)) #输出矩阵初始化
L_G=0 #初始化迭代次数
for k in range(max_number):
    for j in range(n):
      if j==0:
          x1[0]=(b[0]-A[0,1:n]@x0[1:n])/A[0,0]
      elif j==n:
          x1[n]=(b[n-1]-A[n-1,0:n]@x1[0:n])/A[0,0]
      else:
          x1[j]=(b[j]-A[j,0:j]@x1[0:j])/A[j,j]-A[j,j+1:n]@x0[j+1:n]/A[j,j] #迭代公式
    L_G=L_G+1 #更新迭代次数
    if max(abs(A@x1-b))<e: #利用残差判断
        break
    x0 = x1  # 更新迭代初值
print(f"x1={x1}") #输出线性方程组的解
print(A@x1-b) #验证解的正确性
print(f"L_G={L_G}") #输出迭代次数

运行结果如下:

x1=[[1.1]
 [1. ]
 [1.8]]
[[8.81430928e-10]
 [4.40715464e-10]
 [0.00000000e+00]]
L_G=17

  • 5
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用迭代法求解线性方程组的C语言代码: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define N 3 void gauss_seidel(double a[N][N], double b[N], double x[N], int max_iter, double tol) { int iter = 0; double error = 0.0, sum = 0.0; double x_new[N]; while (iter < max_iter) { for (int i = 0; i < N; i++) { sum = 0.0; for (int j = 0; j < N; j++) { if (j != i) { sum += a[i][j] * x[j]; } } x_new[i] = (b[i] - sum) / a[i][i]; } error = fabs(x_new[0] - x[0]); for (int i = 0; i < N; i++) { error = fmax(error, fabs(x_new[i] - x[i])); x[i] = x_new[i]; } if (error < tol) { printf("Converged after %d iterations\n", iter + 1); return; } iter++; } printf("Failed to converge after %d iterations\n", max_iter); } int main() { double a[N][N] = {{4.0, 1.0, -1.0}, {2.0, 7.0, 1.0}, {1.0, -3.0, 12.0}}; double b[N] = {3.0, -5.0, 14.0}; double x[N] = {0.0, 0.0, 0.0}; int max_iter = 1000; double tol = 1e-6; gauss_seidel(a, b, x, max_iter, tol); for (int i = 0; i < N; i++) { printf("x[%d] = %g\n", i, x[i]); } return 0; } ``` 其中,`a`是系数矩阵,`b`是常数向量,`x`是待求解的未知向量。`max_iter`是最大迭代次数,`tol`是容差。在函数`gauss_seidel`中,使用了高斯-塞德尔迭代法求解线性方程组。循环中,每次更新`x_new`后,计算当前的误差,如果误差小于容差,则认为已经收敛,函数返回。如果迭代次数达到最大值,但仍未收敛,则函数返回。最后在`main`函数中,给定系数矩阵、常数向量、初始、最大迭代次数和容差,调用`gauss_seidel`函数求解线性方程组,并输出结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dfreedom.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值