GMRES 方法的数学推导及其算法表示

GMRES 方法的数学推导及其算法表示

  1. GMRES 解为 Krylov 子空间 2 范数意义下的极小化残差的最小二乘解。
  2. 考虑 Arnoldi 过程中正交基和上 Hessenberg 系数矩阵的分解关系 A V m = V m + 1 H ˉ m AV_m = V_{m+1} \bar{H}_m AVm=Vm+1Hˉm,子空间最小二乘问题从 V m V_m Vm 转到了 H ˉ m \bar{H}_m Hˉm。
  3. 上 Hessenberg 方程通过上三角化进行处理,上三角化的方式可采用 Givens 变换。
  4. 耦合 Given 变换上三角化上 Hessenberg 矩阵的过程到 Arnoldi 过程中,即得到了实用 GMRES 算法。

文章目录

    • [GMRES 方法的数学推导及其算法表示](#GMRES 方法的数学推导及其算法表示)
      • [GMRES 方法推导](#GMRES 方法推导)
      • [最小二乘问题的 Givens 变换求解](#最小二乘问题的 Givens 变换求解)
      • 幸运中断
      • [实用 GMRES 算法与 MATLAB 编程实现](#实用 GMRES 算法与 MATLAB 编程实现)

GMRES 方法推导

考虑一般线性方程组求解问题

A x = b Ax=b Ax=b

假定 V m V_m Vm 是 Krylov 子空间 K m ( A , r 0 / ∥ r 0 ∥ 2 ) \mathcal{K}_m(A, r_0 /\left\|r_0\right\|_2) Km(A,r0/∥r0∥2) 一组正交基, x 0 x_0 x0 表示给定的迭代初值, r 0 r_0 r0 为初始残差 r 0 = b − A x 0 r_0 = b-Ax_0 r0=b−Ax0。

我们用 V m V_m Vm 表示以 v 1 , ⋯   , v m v_1, \cdots, v_m v1,⋯,vm 为列的 n × m n \times m n×m 矩阵。
x 0 + K m x_0+\mathcal{K}_m x0+Km 中的任意向量 x x x 可写为
x = x 0 + V m y , x=x_0+V_m y, x=x0+Vmy,

我们可以在投影空间中寻求 2 范数最小的解,即最小化
J ( y ) = ∥ b − A x ∥ 2 = ∥ b − A ( x 0 + V m y ) ∥ 2 , J(y)=\|b-A x\|_2=\left\|b-A\left(x_0+V_m y\right)\right\|_2, J(y)=∥b−Ax∥2=∥b−A(x0+Vmy)∥2,

我们用 h i j h_{ij} hij 表示的是向量 w j = A v j w_j = Av_j wj=Avj 在 v j v_j vj 上的投影内积。
H ˉ m \bar{H}m Hˉm 表示元素为 h i j h{i j} hij 的 ( m + 1 ) × m (m+1) \times m (m+1)×m 的上 Hessenberg 矩阵, H m H_m Hm 表示在 H ˉ m \bar{H}_m Hˉm 中删去最后一行所得的矩阵。


A v j = ∑ i = 1 j + 1 h i j v i , j = 1 , 2 , ⋯   , m . A v_j=\sum_{i=1}^{j+1} h_{i j} v_i, \quad j=1,2, \cdots, m . Avj=i=1∑j+1hijvi,j=1,2,⋯,m.

写成矩阵形式,实际上是
A V m = V m + 1 H ˉ m AV_m = V_{m+1} \bar{H}_m AVm=Vm+1Hˉm

那么有
b − A x = b − A ( x 0 + V m y ) = r 0 − A V m y = β v 1 − V m + 1 H ˉ m y = V m + 1 ( β e 1 − H ˉ m y ) b-A x=b-A\left(x_0+V_m y\right)=r_0-A V_m y=\beta v_1-V_{m+1} \bar{H}m y=V{m+1}\left(\beta e_1-\bar{H}_m y\right) b−Ax=b−A(x0+Vmy)=r0−AVmy=βv1−Vm+1Hˉmy=Vm+1(βe1−Hˉmy)

其中 β = ∣ ∣ r 0 ∣ ∣ 2 \beta = ||r_0||_2 β=∣∣r0∣∣2。那么,问题就变为了极小化问题
y m = arg ⁡ min ⁡ y ∥ β e 1 − H ˉ m y ∥ 2 . y_m=\arg \min _y\left\|\beta e_1-\bar{H}_m y\right\|_2 . ym=argymin βe1−Hˉmy 2.

结合 Arnoldi 正交化过程,可得 GMRES 算法如下,

最小二乘问题的 Givens 变换求解

求解最小二乘问题 min ⁡ ∥ β e 1 − H ˉ m y ∥ \min \left\|\beta e_1-\bar{H}_m y\right\| min βe1−Hˉmy 可以通过 Givens 变换,将规模为 m × ( m − 1 ) m\times{(m-1)} m×(m−1) 的上 Hessenberg 矩阵 H ˉ m \bar{H}_m Hˉm 变为最后一行为 0 的上三角矩阵。

定义 g ˉ 0 ≡ β e 1 \bar{g}0 \equiv \beta e_1 gˉ0≡βe1。以 m = 5 m=5 m=5 举例来说,
H ˉ 5 = ( h 11 h 12 h 13 h 14 h 15 h 21 h 22 h 23 h 24 h 25 h 32 h 33 h 34 h 35 h 43 h 44 h 45 h 54 h 55 h 65 ) , g ˉ 0 = ( β 0 0 0 0 0 ) . \bar{H}5=\left(\begin{array}{ccccc} h{11} & h
{12} & h_{13} & h_{14} & h_{15} \\ h_{21} & h_{22} & h_{23} & h_{24} & h_{25} \\ & h_{32} & h_{33} & h_{34} & h_{35} \\ & & h_{43} & h_{44} & h_{45} \\ & & & h_{54} & h_{55} \\ & & & & h_{65} \end{array}\right), \quad \bar{g}_0=\left(\begin{array}{c} \beta \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \end{array}\right) . Hˉ5= h11h21h12h22h32h13h23h33h43h14h24h34h44h54h15h25h35h45h55h65 ,gˉ0= β00000 .

我们可以定义一系列的旋转矩阵 Ω i \Omega_i Ωi,举例来说,
Ω 1 = ( c 1 s 1 − s 1 c 1 1 1 1 ) \Omega_1=\left(\begin{array}{ccccc} c_1 & s_1 & & & \\ -s_1 & c_1 & & & \\ & & 1 & & \\ & & & 1 & \\ & & & & 1 \end{array}\right) Ω1= c1−s1s1c1111
s 1 = h 21 h 11 2 + h 21 2 , c 1 = h 11 h 11 2 + h 21 2 s_1=\frac{h_{21}}{\sqrt{h_{11}^2+h_{21}^2}}, \quad c_1=\frac{h_{11}}{\sqrt{h_{11}^2+h_{21}^2}} s1=h112+h212 h21,c1=h112+h212 h11

以此类推。

那么,通过定义 Q m = Ω m Ω m − 1 ⋯ Ω 1 Q_m=\Omega_m \Omega_{m-1} \cdots \Omega_1 Qm=ΩmΩm−1⋯Ω1,有
R ˉ m = H ˉ m ( m ) = Q m H ˉ m g ˉ m = Q m ( β e 1 ) = ( γ 1 , ⋯   , γ m + 1 ) T . \begin{aligned} \bar{R}_m & =\bar{H}_m^{(m)}=Q_m \bar{H}_m \\ \bar{g}m & =Q_m\left(\beta e_1\right)=\left(\gamma_1, \cdots, \gamma{m+1}\right)^{\mathrm{T}} . \end{aligned} Rˉmgˉm=Hˉm(m)=QmHˉm=Qm(βe1)=(γ1,⋯,γm+1)T.


min ⁡ ∥ β e 1 − H ˉ m y ∥ 2 = min ⁡ ∥ g ˉ m − R ˉ m y ∥ 2 . \min \left\|\beta e_1-\bar{H}_m y\right\|_2=\min \left\|\bar{g}_m-\bar{R}_m y\right\|_2 . min βe1−Hˉmy 2=min gˉm−Rˉmy 2.

因为 R ˉ m \bar{R}_m Rˉm 最后一行是 0,用 R m R_m Rm 和 g m g_m gm 分别表示从 R ˉ m \bar{R}_m Rˉm 和 g ˉ m \bar{g}_m gˉm 中删除最后一行所得的 m × m m \times m m×m 上三角矩阵和 m m m 维向量。可以知道上述问题的最小二乘解为
y m = R m − 1 g m y_m=R_m^{-1} g_m ym=Rm−1gm

且残差范数
∥ b − A x m ∥ 2 = ∣ γ m + 1 ∣ \left\|b-A x_m\right\|2=\left|\gamma{m+1}\right| ∥b−Axm∥2=∣γm+1∣

幸运中断

由 Ω i \Omega_i Ωi 的表达方式,可以知道
γ j + 1 = − s j γ j \gamma_{j+1}=-s_j \gamma_j γj+1=−sjγj

事实上,容易证明,在 Arnoldi 正交基生成过程中, h j + 1 , j = 0 h_{j+1, j}=0 hj+1,j=0,当且仅当提前求解问题最小二乘解且误差为 0,即 b − A x j = 0 b-A x_j=0 b−Axj=0,也就是说近似解 x j x_j xj 就是精确解。因此, h j + 1 , j = 0 h_{j+1, j}=0 hj+1,j=0 可以作为中断条件,行内称之为"幸运中断"。

实用 GMRES 算法与 MATLAB 编程实现

将上述 Givens 变换上三角化的过程,耦合到整个 Arnoldi 正交化过程中,就得到了标准的实用的 GMRES 算法了。

可以看得出来,这个算法需要把每次的 Givens 变换矩阵都存下来,还是比较耗费内存的,所以后面有了带重启的 GMRES 算法。当然,考虑内存有限,也可以实用 BICGSTAB 算法。

算法的一些细节处理,我写了一个简单的 MATLAB 编程实现如下,仅供参考:

复制代码
% 生成一个随机的正定矩阵测试
n = 100;
A = gallery('compar', n); 
b = rand(n, 1);
x0 = zeros(n, 1);

% 调用算法
[x, res] = gmres(A, b, x0, 1e-6, 50);

x_ref = A\b;

err = norm(x - x_ref)

function [x, resvec] = gmres(A, b, x0, tol, iter_max)
    % 输入: A-矩阵, b-右端项, x0-初值, tol-容差, iter_max-最大迭代次数
    % 输出: x-近似解, resvec-残差历史
    
    n = length(b);
    r0 = b - A * x0;
    beta = norm(r0);
    
    if beta < tol
        x = x0; return;
    end
    
    % 初始化
    V = zeros(n, iter_max + 1);
    V(:, 1) = r0 / beta;
    H = zeros(iter_max + 1, iter_max);
    g = zeros(iter_max + 1, 1);
    g(1) = beta;
    
    cs = zeros(iter_max, 1); % 存储 Givens 余弦
    sn = zeros(iter_max, 1); % 存储 Givens 正弦
    resvec = [];

    for j = 1:iter_max
        % --- Arnoldi 过程 ---
        w = A * V(:, j);
        for i = 1:j
            H(i, j) = V(:, i)' * w;
            w = w - H(i, j) * V(:, i);
        end
        H(j+1, j) = norm(w);
        V(:, j+1) = w / H(j+1, j);
        
        % --- 应用之前的 Givens 旋转到当前列 ---
        for i = 1:j-1
            temp = cs(i) * H(i, j) + sn(i) * H(i+1, j);
            H(i+1, j) = -sn(i) * H(i, j) + cs(i) * H(i+1, j);
            H(i, j) = temp;
        end
        
        % --- 计算并应用当前的 Givens 旋转 ---
        [cs(j), sn(j)] = col_rotation(H(j, j), H(j+1, j));
        H(j, j) = cs(j) * H(j, j) + sn(j) * H(j+1, j);
        H(j+1, j) = 0;
        
        % --- 更新残差向量 g ---
        g(j+1) = -sn(j) * g(j);
        g(j) = cs(j) * g(j);
        
        relres = abs(g(j+1)) / beta;
        resvec = [resvec; relres];
        
        % 检查收敛
        if relres < tol
            break;
        end
    end
    
    % --- 回代求解 H*y = g ---
    y = H(1:j, 1:j) \ g(1:j);
    
    % --- 计算最终解 ---
    x = x0 + V(:, 1:j) * y;
end

% 辅助函数:计算 Givens 旋转参数
function [c, s] = col_rotation(a, b)
    if b == 0
        c = 1; s = 0;
    elseif abs(b) > abs(a)
        tau = a / b;
        s = 1 / sqrt(1 + tau^2);
        c = s * tau;
    else
        tau = b / a;
        c = 1 / sqrt(1 + tau^2);
        s = c * tau;
    end
end
相关推荐
plus4s1 小时前
2月22日(94-96题)
算法
tankeven2 小时前
HJ98 喜欢切数组的红
c++·算法
adore.9682 小时前
2.22 oj基础92 93 94+U12
数据结构·c++·算法
颜酱2 小时前
前缀和技巧全解析:从基础到进阶
javascript·后端·算法
Rhystt2 小时前
代码随想录第二十六天|669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树
数据结构·c++·算法·leetcode
想做功的洛伦兹力13 小时前
2026/2/22日打卡
数据结构·算法
不染尘.3 小时前
字符串哈希
开发语言·数据结构·c++·算法·哈希算法
今儿敲了吗3 小时前
25| 丢手绢
数据结构·c++·笔记·学习·算法
wostcdk3 小时前
归并排序 & 逆序对
数据结构·算法