Introduction
在之前我实现了求解低阶矩阵的一些算法。考虑线性方程组Ax=b,其中A为非奇异矩阵,当A是低阶稠密矩阵时,可以使用之前提到的中的高斯消元法以及列主
元消元法(详情请参考高斯消元法之讲解与代码实现)来进行求解。但是实际生活中工程技术产生的矩阵都是大型的稀疏矩阵(阶数很大,但零元素很多),当A是高阶稀疏矩阵时,就可以利用迭代法来进行求解。迭代法利用了A中零元素较多的特点,这对于计算机的存储和运算是很有利的。
迭代法的基本思想是:对于线性方程组的第行,假设除去外,其他已知,那么我就可以求出这一个,考虑到矩阵稀疏的特点,每一行的计算就显得很容易了。通过迭代,每一行都基于之前算出的结果,对当前行的进行更新,如果迭代向量具有收敛的性质,那么我们最后就可以逼近一个精确解。
我们通过变换,可以将Ax=b等价变换为。构造向量序列,其中表示迭代次数。
如果存在,则说明迭代法收敛,否则,该迭代法发散。所以我们每次使用迭代法求解矩阵的时候就需要判断矩阵是否收敛。
。
注意:在使用迭代法求解的时候,要确保是可以收敛到一个精确解的。这里给出一个判断矩阵收敛的定理:对于一个线性方程组,迭代法收敛的充要条件是矩阵B的谱半径ρ(B) < 1
这里主要分析四种迭代方法:雅可比迭代法、高斯赛德尔迭代法、超松弛迭代法、共轭梯度法。
雅可比迭代法(Jocobi Method)
分析
现在我来讲解雅可比迭代法。雅可比迭代法是对上述迭代过程的详细展开。对于线性方程组的系数矩阵A,可分解为三部分:
设,可以得到Ax=b的雅可比迭代法:
其中,称J为解Ax=b的雅可比迭代法的迭代矩阵。
解Ax=b的雅可比迭代法的计算公式为:
根据上述计算公式就可以使用雅可比迭代法求解了。
代码实现
Matlab代码:
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 27 28 29 30 31 32 33 34 35 36
| function[xn]=jacobi(A,b,max) n=size(A,1); eps = 0.000001;
if nargin == 2 max = 200; end
x0=zeros(n,1); xn=zeros(n,1); x0(1)=1;
times = 0; while norm(xn-x0)>=eps && times <= max times=times+1; x0=xn;
for i=1:n sum = 0; for j =1:n if (j~=i) sum = sum + A(i,j) * x0(j); end end xn(i)=(b(i)-sum)/A(i,i); end
if(times>=max) return; end end
disp(times); disp(xn);
|
高斯赛德尔迭代法(Gauss-Seidel Method)
分析
高斯-赛德尔迭代法可以看作是对雅可比迭代法的优化改进。它的思路在于,更新每一步的时候,可以利用已经更新的值,这样可以减少迭代次数,因为它计算每一个分量的时候是基于当前的最新分量。
设,可以得到Ax=b的高斯-赛德尔迭代法:
其中。
求解Ax=b的高斯赛德尔迭代法计算公式为
这就是高斯赛德尔迭代法的计算公式。
代码实现
Matlab代码:
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| function[xn]=Gauss_Seidel(A,b, max) n=size(A,1);
if nargin == 2 max = 200; end
eps = 0.000001;
x0=zeros(n,1); xn=zeros(n,1); x0(1)=1;
if det(A) == 0 return; end
times = 0; while norm(xn-x0)>=eps && times <= max times=times+1; x0=xn;
for i=1:n sum1 = 0; sum2 = 0; for j =1:i-1 sum1 = sum1 + A(i,j) * xn(j); end for j=i+1:n sum2 = sum2 + A(i,j) * x0(j); end xn(i)=(b(i) - sum1 - sum2)/A(i,i); end
if(times>=max) return; end end
disp(times); disp(xn);
|
超松弛迭代法(Successive Over Relaxation Method)
分析
超松弛迭代法,SOR,是对于高斯赛德尔迭代法的改进。它的关键之处在于松弛因子,这个因子可以控制收敛的方向来控制迭代速度和迭代精度。由于迭代速度和迭代精度是相互矛盾的,如果我想得到更快的迭代速度(倾向于向新的x靠近),那么我就有可能偏离了我的正确值;如果我追求迭代精度(倾向于向旧的x靠近)那么,我的迭代速度就很慢。松弛因子就是用来调节这两者的,务求找到一个平衡点。这里直接给出SOR的计算方法。
使用SOR的时候,需要注意的是矩阵A必须是对称正定矩阵,同时。
代码实现
Matlab代码:
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 27 28 29 30 31 32 33 34 35 36 37 38
| function[xn,times]=SOR(A,b,w,max) n=size(A,1); eps = 0.00001;
if nargin == 3 max = 200; end
x0=zeros(n,1); xn=zeros(n,1); x0(1)=1;
times = 0; while norm(xn-x0)>=eps && times <= max times=times+1; x0=xn;
for i=1:n sum1 = 0; sum2 = 0; for j =1:i-1 sum1 = sum1 + A(i,j) * xn(j); end for j=i:n sum2 = sum2 + A(i,j) * x0(j); end xn(i)=x0(i) + w * (b(i) - sum1 - sum2)/A(i,i); end
if(times>=max) return; end end
disp(times); disp(xn);
|
共轭梯度法(Conjugate Gradient Method)
分析
谈到共轭梯度法,首先要了解与线性方程组等价的变分问题。
设是对称正定矩阵,,求解的线性方程组为Ax=b。考虑如下定义的二次函数,该函数等价于对应的线性方程组。
性质1: 对一切的梯度为
性质2: 对一切及,
性质3:设是线性方程组Ax=b的解,则
,
且对一切,有
根据上述二次函数的性质,我们可以知道,当为令最小时,是该方程的解。这样,我们就把求解矩阵的问题转化为求解二次函数极小值点的问题
共轭梯度法的思想是,对于初始的一个x,使用方向进行k次搜索,求得,然后确定的方向,这样能使x^{(k+1)}更快地求得。其主要迭代公式为:
\alpha_k的值可以根据如下公式计算:
因为我们每步的求解过程中,都需要基于当前的x,求出下一个极小值,即
,
由于
,
对上式求导,求出极小值
解得
又因为我们希望能使能够更快地求得,因此我们有
,
然后我们把x分解成,所以得到
,
由于我们需要对x求导,又因为x用y来表示,所以对y求偏导。因为要为0,所以交叉项必须为0,这样一组向量p称为共轭向量。
以上就是对于共轭梯度法的核心思想的分析。下面直接给出算法:
(1)任取初始向量,一般取为0,计算.
(2)对计算
(3)若,或,则计算停止,得出结果。
这就是共轭梯度法的简要算法分析。
代码实现
Matlab代码:
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 27 28 29 30 31 32 33 34 35 36 37 38 39
| function[x] = CG(A,b,max)
n = size(A,1); x0 = zeros(n,1); r0=b-A*x0; p0=r0;
if nargin == 2 max = 200; end
eps = 1.0e-6; times = 0; while 1 if ((abs(p0) < eps)) break; end if (times > max) break; end times = times + 1; a0 = (r0' * r0) / (p0' * A*p0); x1 = x0 + a0*p0;
r1 = r0 - a0*A*p0;
b0 = (r1'*r1)/(r0'*r0);
p1 = r1 + b0 *p0;
x0 = x1; r0 = r1; p0 = p1; end x = x0; end
|
小结
四个算法的时间比较
对比四种算法对同一个矩阵的求解计算时间:
n = 10
| 方法 | 时间 |
|:—-:|:—-:|
| 雅可比迭代法 | 0.0002|
| 高斯赛德尔迭代法 |0.0003|
| SOR迭代法 |0.0003|
| 共轭梯度法 |0.0001|
n = 100
| 方法 | 时间 |
|:—-:|:—-:|
| 雅可比迭代法 | 0.0053|
| 高斯赛德尔迭代法 |0.0044|
| SOR迭代法 |0.0048|
| 共轭梯度法 |0.0040|
n = 200
| 方法 | 时间 |
|:—-:|:—-:|
| 雅可比迭代法 | 0.0254|
| 高斯赛德尔迭代法 |0.0128|
| SOR迭代法 |0.0120|
| 共轭梯度法 |0.0036|
可以看出,迭代法的计算速度普遍较快,尤其是计算高维矩阵的时候,优势更加明显。其中,共轭梯度法的计算速度最快。
对迭代速度的影响
这个测试是为了研究不同的对SOR的速度的影响。这里采用测量迭代次数的方法,即对于不同omega,看看哪个算法的误差小于某个指定的值,记录当时的迭代次数,对于每次迭代我给了最高的迭代次数500。
结果如下:

从图中可以看出,对于测试用的这个矩阵,最佳的松弛因子约为1.5。对于不同的矩阵,最佳松弛因子是不同的。
以上就是四种求解大型稀疏矩阵的迭代法的分析与实现,同时我也对算法的性能做出了简单的评估,谢谢!
参考资料:
1.数值分析(第5版) 李庆扬,王能超,易大义 *编
v1.5.2