迭代法简介
迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程,跟迭代法相对应的是直接法(或者称为一次解法),即一次性解决问题。迭代算法是用计算机解决问题的一种基本方法,它利用计算机运算速度快、适合做重复性操作的特点,让计算机对一组指令(或一定步骤)进行重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值,迭代法又分为精确迭代和近似迭代。比较典型的迭代法如“二分法”和"牛顿迭代法”属于近似迭代法。
Jacobi迭代
以如下方程组为例:
高斯消元法(高中用的那种)可以算出结果分别为1,2,3
Jacobi的计算过程:
先对每行分别进行变换,左边分别只留下
:
相信大家到这一步都会,那么我们就开始分别计算
的值吧。
先设 都为0,第一次迭代,他们的结果分别为:
然后把
分别带入
计算,则:
迭代10次可得结果如下:
次数 | |||
---|---|---|---|
1 | 0.3 | 1.5 | 2.0 |
2 | 0.8 | 1.76 | 2.66 |
3 | 0.918 | 1.926 | 2.864 |
4 | 0.972 | 1.97 | 2.954 |
5 | 0.989 | 1.99 | 2.982 |
6 | 0.996 | 1.996 | 2.994 |
7 | 0.999 | 1.999 | 2.998 |
8 | 1.0 | 2.0 | 2.999 |
9 | 1.0 | 2.0 | 3.0 |
10 | 1.0 | 2.0 | 3.0 |
其python代码如下:
x1=0
x2=0
x3=0
print('Jacobi')
for i in range(10):
x11=round(0.2*x2+0.1*x3+0.3,3)
x22=round(0.2*x1+0.1*x3+1.5,3)
x33=round(0.2*x1+0.4*x2+2,3)
print('|',i+1,'|',x11,'|',x22,'|',x33,'|')
x1=x11
x2=x22
x3=x33
其中round是将结果保留3位小数。
上面这个过程叫Jacobi迭代。
Gauss-Seidel迭代
高斯迭代唯一的区别在于,在每次迭代的过程中,都使用最新的值,直接上代码大家应该也可以看明白:
x1=0
x2=0
x3=0
print('Gauss-Seidel')
for i in range(10):
x1=round(0.2*x2+0.1*x3+0.3,3)
x2=round(0.2*x1+0.1*x3+1.5,3)
x3=round(0.2*x1+0.4*x2+2,3)
print('|',i+1,'|',x1,'|',x2,'|',x3,'|')
其10次迭代的结果如下:
次数 | |||
---|---|---|---|
1 | 0.3 | 1.56 | 2.684 |
2 | 0.88 | 1.944 | 2.954 |
3 | 0.984 | 1.992 | 2.994 |
4 | 0.998 | 1.999 | 2.999 |
5 | 1.0 | 2.0 | 3.0 |
6 | 1.0 | 2.0 | 3.0 |
7 | 1.0 | 2.0 | 3.0 |
8 | 1.0 | 2.0 | 3.0 |
9 | 1.0 | 2.0 | 3.0 |
10 | 1.0 | 2.0 | 3.0 |
可以看到,只用5次就得到了正确的结果。
所以这里可以发现,高斯迭代法使用的空间小,并且计算速度快。
例2
为了计算复用,可以将函数封装一下:
#1.(1)
data=[
[10,-2,-1,3],
[-2,10,-1,15],
[-1,-2,5,10]
]
x=zeros(3)
xx=zeros(3)
print('Jacobi')
for i in range(10):
xx[0]=round((-data[0][1]*x[1]-data[0][2]*x[2]+data[0][3])/data[0][0],3)
xx[1]=round((-data[1][0]*x[0]-data[1][2]*x[2]+data[1][3])/data[1][1],3)
xx[2]=round((-data[2][0]*x[0]-data[2][1]*x[1]+data[2][3])/data[2][2],3)
x[0]=xx[0];x[1]=xx[1];x[2]=xx[2]
print('|',i+1,'|',x[0],'|',x[1],'|',x[2],'|')
#print(i+1,x[0],x[1],x[2])
x=zeros(3)
print('Gauss-Seidel')
for i in range(10):
x[0]=round((-data[0][1]*x[1]-data[0][2]*x[2]+data[0][3])/data[0][0],3)
x[1]=round((-data[1][0]*x[0]-data[1][2]*x[2]+data[1][3])/data[1][1],3)
x[2]=round((-data[2][0]*x[0]-data[2][1]*x[1]+data[2][3])/data[2][2],3)
print('|',i+1,'|',x[0],'|',x[1],'|',x[2],'|')
#print(i+1,x[0],x[1],x[2])
得到的结果和上面一致:
Jacobi:
次数 | |||
---|---|---|---|
1 | 0.3 | 1.5 | 2.0 |
2 | 0.8 | 1.76 | 2.66 |
3 | 0.918 | 1.926 | 2.864 |
4 | 0.972 | 1.97 | 2.954 |
5 | 0.989 | 1.99 | 2.982 |
6 | 0.996 | 1.996 | 2.994 |
7 | 0.999 | 1.999 | 2.998 |
8 | 1.0 | 2.0 | 2.999 |
9 | 1.0 | 2.0 | 3.0 |
10 | 1.0 | 2.0 | 3.0 |
Gauss-Seidel:
次数 | |||
---|---|---|---|
1 | 0.3 | 1.56 | 2.684 |
2 | 0.88 | 1.944 | 2.954 |
3 | 0.984 | 1.992 | 2.994 |
4 | 0.998 | 1.999 | 2.999 |
5 | 1.0 | 2.0 | 3.0 |
6 | 1.0 | 2.0 | 3.0 |
7 | 1.0 | 2.0 | 3.0 |
8 | 1.0 | 2.0 | 3.0 |
9 | 1.0 | 2.0 | 3.0 |
10 | 1.0 | 2.0 | 3.0 |
上面这个例子是《数值计算方法》第二版 北京理工大学出版社 习题三的1(1),下面计算1(1)。
只需要修改数据:
#1.(2)
data=[
[8,-3,2,20],
[4,11,-1,33],
[2,1,4,12]
]
运行结果如下:
Jacobi:
次数 | |||
---|---|---|---|
1 | 2.5 | 3.0 | 3.0 |
2 | 2.875 | 2.364 | 1.0 |
3 | 3.136 | 2.045 | 0.971 |
4 | 3.024 | 1.948 | 0.921 |
5 | 3.0 | 1.984 | 1.001 |
6 | 2.994 | 2.0 | 1.004 |
7 | 2.999 | 2.003 | 1.003 |
8 | 3.0 | 2.001 | 1.0 |
9 | 3.0 | 2.0 | 1.0 |
10 | 3.0 | 2.0 | 1.0 |
Gauss-Seidel:
次数 | |||
---|---|---|---|
1 | 2.5 | 2.091 | 1.227 |
2 | 2.977 | 2.029 | 1.004 |
3 | 3.01 | 1.997 | 0.996 |
4 | 3.0 | 2.0 | 1.0 |
5 | 3.0 | 2.0 | 1.0 |
6 | 3.0 | 2.0 | 1.0 |
7 | 3.0 | 2.0 | 1.0 |
8 | 3.0 | 2.0 | 1.0 |
9 | 3.0 | 2.0 | 1.0 |
10 | 3.0 | 2.0 | 1.0 |
可以看出高斯法只需要4次就有结果了。
例3
以习题三的3题为例:
data=[
[1,2,-2,1],
[1,1,1,1],
[2,2,1,1]
]
其结果如下:
Jacobi:
次数 | |||
---|---|---|---|
1 | 1.0 | 1.0 | 1.0 |
2 | 1.0 | -1.0 | -3.0 |
3 | -3.0 | 3.0 | 1.0 |
4 | -3.0 | 3.0 | 1.0 |
5 | -3.0 | 3.0 | 1.0 |
6 | -3.0 | 3.0 | 1.0 |
7 | -3.0 | 3.0 | 1.0 |
8 | -3.0 | 3.0 | 1.0 |
9 | -3.0 | 3.0 | 1.0 |
10 | -3.0 | 3.0 | 1.0 |
Gauss-Seidel:
次数 | |||
---|---|---|---|
1 | 1.0 | 0.0 | -1.0 |
2 | -1.0 | 3.0 | -3.0 |
3 | -11.0 | 15.0 | -7.0 |
4 | -43.0 | 51.0 | -15.0 |
5 | -131.0 | 147.0 | -31.0 |
6 | -355.0 | 387.0 | -63.0 |
7 | -899.0 | 963.0 | -127.0 |
8 | -2179.0 | 2307.0 | -255.0 |
9 | -5123.0 | 5379.0 | -511.0 |
10 | -11779.0 | 12291.0 | -1023.0 |
可以看出Jacobi迭代法迭代3次就能计算出答案,而Gauss-Seidel法得到的结果却发散了,可见Gauss-Seidel在使用时还有一定的要求。
上述内容是本人课程学习随笔,如有错误欢迎指出,共同学习。