之前在数值求解柏松方程以及热传导方程的讲解中,离散化之后会形成一系列的非线性方程组,然后又讲解了如何使用牛顿法求解该非线性方程组,最终发现问题转化成了形如:

线性方程组的数值求解。之前都是简单的使用 Mathematica 的 FindRoot[]NSolve[] 函数求解,本次利用共轭梯度法数值求解线性方程组。这样一步一步拆解、简化问题是具有启发性的,能够一步一步帮助我们解决问题。


共轭梯度法

共轭梯度法(英语:Conjugate Gradient Method)是求解系数矩阵为对称正定矩阵的线性方程组的数值解的方法。共轭梯度法是一个迭代方法,它适用于系数矩阵为稀疏矩阵的线性方程组,因为使用像Cholesky分解这样的直接方法求解这些系统所需的计算量太大了。这种方程组在数值求解偏微分方程时很常见。


A 是实对称正定矩阵

求解 ,其中 𝐴 是实对称正定矩阵

结果为


Mathematica

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ConjugateGradient1[A_, b_] :=
Module[{x, r, p, k, \[Alpha], \[Beta], n = Length[b]},
x[0] = Table[0., n];

r[0] = b - A . x[0];
p[0] = r[0];
k = 0;

While[k < 100,
\[Alpha][k] = ConjugateTranspose[r[k]] . r[k]/
ConjugateTranspose[p[k]] . A . p[k];
x[k + 1] = x[k] + \[Alpha][k] p[k];
r[k + 1] = r[k] - \[Alpha][k] (A . p[k]);

Print[Norm[r[k + 1]]/n, ",", x[k + 1]];
If[Norm[r[k + 1]]/n < 10^-15, Break[]];

\[Beta][k] = ConjugateTranspose[r[k + 1]] . r[k + 1]/
ConjugateTranspose[r[k]] . r[k];
p[k + 1] = r[k + 1] + \[Beta][k] p[k];
k++];

x[k + 1]
]

1
ConjugateGradient1[{{1, 2}, {3, 4}}, {5, 11}]

上述求解不收敛,这是因为矩阵 并不是对称正定矩阵。我们可以求解等价方程

In[]:=
1
2
3
ConjugateGradient1[
ConjugateTranspose[{{1, 2}, {3, 4}}] . {{1, 2}, {3, 4}},
ConjugateTranspose[{{1, 2}, {3, 4}}] . {5, 11}]
Out[]:=

左边是误差,右边是解。可以看出经过 3 次迭代就达到相当高的精度。


本次讲解了 A 是实对称正定矩阵时的共轭梯度算法,下次会介绍 A 不是实对称正定矩阵时的共轭梯度算法。

共轭梯度法也是一种数值优化算法,可以用于求解无约束的最优化问题,用于求解具有二次目标函数的线性方程组或最小化二次函数的问题。与传统的梯度下降法不同,共轭梯度法在每个迭代步骤中以更智能的方式更新解向量,从而加速收敛。

这里是共轭梯度法的一些关键特点:

  1. 适用性:共轭梯度法适用于系数矩阵为稀疏矩阵的线性方程组,因为直接使用像Cholesky分解这样的方法求解这些系统所需的计算量太大了。

  2. 迭代更新:在每个迭代步骤中,共轭梯度法使用共轭方向来更新解向量。这些共轭方向是相互正交的,从而避免了梯度下降法中的振荡问题。

  3. 收敛速度:相对于最速下降法,共轭梯度法通常收敛更快。它充分利用了问题的二次性质,避免了梯度下降法的收敛慢的缺点。

总之,共轭梯度法不仅是解决大型线性方程组最有用的方法之一,也是解大型非线性最优化最有效的算法之一。


请大家多多关注、点赞、收藏、转发,让更多有需要的人可以看到,以后会分享更多实用的算法。

万分感谢!🙏