线性方程的迭代方法
线性方程的迭代方法
本文将介绍求解线性方程 \(Ax = b\) 的几种方法。 其中 A 是一个大型稀疏矩阵,通常以算子的形式给出,例如在偏微分方程中。这类问题的规模太大,以至于像LU分解之类的直接方法受内存限制无法使用,故需要使用迭代求解。
静态(Stationary)方法
采用如下迭代格式:
M是一个相对于A更便于求逆的矩阵。可以很方便的验证上述格式在\(Ax=b\) 是不动点。M有3种常用的选择
- \(A\) 的对角元 \(D\) (Jacobi 格式),其具体迭代为:
 
- \(A\) 的下三角元 \(D+L\) (Gauss-Siedel 格式),其具体迭代为:
 
- 以上二者线性组合 \({1\over \omega}D+L\) (SOR 格式),其具体迭代为:
 
共轭梯度法(Conjugate gradient, CG)
当\(A\) 对称正定时,可将原问题化为最小化 \(\phi(x)={1\over 2}x^TAx-b^Tx\). 从一个点 \(x\)开始,沿一个方向 \(p\) 搜索 \(\phi(x+ap)\) 的最小值,得到
再把 \(x+ap\) 当做新的起点,换个方向重复以上步骤就可以不断减小 \(r\) 直到找到解。剩下就是选择搜索的方向。注意到\(\nabla\phi(x)=-r\), 即 \(r\) 是 \(\phi(x)\) 下降最快的方向,故可以选取 \(r\) 作为每次搜索的方向。但实际上有更好的办法。记 \(P_{i-1}=[p_0, \cdots, p_{i-1}]\in\mathbb{R}^{n\times i}\) 为前 \(i\) 次的搜索方向,则 \(x_i=x_0+P_{i-1}y_{i-1}\), 其中 \(y_{i-1}\) 为每次迭代的 \(a\) 。则在第 \(i\) 次迭代中
如果 \(P_{i-1}^TAp_i=0\) , 即 \(\forall j<i,p_j^TAp_i=0\) ,则上式变为
注意到现在 \(a\) 和 \(y_{i-1}\) 已经分开了。则现在有
设 \(\mathcal{K}_i=\left<p_0,\cdots,p_i\right>\) ,其中尖括号表示向量张成的空间,\(\mathcal{K}_i+x_0=\{x_0+x|x\in\mathcal{K}_i\}\) 。则按这种方法迭代的 \(x_i\) 满足
由此,我们选择 \(p_i\) 为 \(r_i\) 减去其在 \(A\mathcal{K}_{i-1}=\{Ax|x\in\mathcal{K}_{i-1}\}\) 上的投影。记 \((A\mathcal{K}_{i-1})^\perp=\{x|\forall x'\in\mathcal{K}_{i-1},x^TAx'=0\}\), 则有
到此我们已经得到了一个算法。但其在每步中需要使用 Gram-Schmidt 方法来求 \(p_i\) 。下面说明 \(p_i\) 是 \(r_i\) 和 \(p_{i-1}\) 的线性组合,从而对算法优化。先证几个命题。
Proposition 1: \(\mathcal{K}_k=\left<r_0,Ar_0,\cdots,A^kr_0\right>\)
Proof: 使用归纳法。\(k=0\) 时显然成立,设命题对于 \(k\) 成立,注意到
又 \(z_i\in A\mathcal{K}_{i-1}\), 则
Proposition 2: \(P_{i-1}^Tr_i=0\)
Proof: 由前得知,\(x_i=x_0+P_{i-1}y_{i-1}\) ,
Proposition 3: \(\forall j\ne i,\space r_i^Tr_j=0\)
Proof: 由命题二得 \(\forall x\in\mathcal{K}_{i-1},\space x^Tr_i=0\) ,故只需证明 \(r_i\in \mathcal{K}_i\) 。使用归纳法,当 \(i=1\) 时显然,若对 \(i-1\) 成立,则 \(r_i=r_{i-1}-a_{i-1}Ap_{i-1}\) ,又由命题一得 \(A\mathcal{K}_{i-1}\sub\mathcal{K}_i\),即 \(Ap_{i-1}\in\mathcal{K}_i\),则 \(r_i\in\mathcal{K}_i\qquad\square\)
由命题三可知,\(\mathcal{K}_i=\left<r_0,\cdots,r_i\right>\), 且 \(r_0,\cdots,r_i\) 构成一组正交基。
Proposition 4: \(p_i\in\left<r_i,p_{i-1}\right>\)
Proof: 首先,\(z_i\) 满足
可设 \(z_i=AP_{i-1}y_{i-1},\space y_{i-1}\in\mathbb{R}^i\),则
设 \(y_{i-1}=[w_{i-1},\space\beta_{i-1}]^T\),又 \(r_{i-1}-r_i=Ap_{i-1}\),易得
最后一式第二项同 \(\left\|r_{i-1}-z_{i-1}\right\|^2\) 比较得
即
代回得
最终实现
import numpy as np
def CG(A,b,x,n):
    r = b - A @ x
    for i in range(n):
        s = r @ r
        if i==0:
            p = r
        else:
            p = r + s / _s * _p
        _s, _p = s, p
        q = A @ p
        a = s / (q @ p)
        x += a * p
        r -= a * q
        print(max(abs(r)))
    return x
BiCG
Let \(\mathcal{K}_m=\left<r_0,\cdots,A^{m-1}r_0\right>\), \(\mathcal{L}_m=\left<r_0,\cdots,\left(A^{T}\right)^{m-1}r_0\right>\), let \(V_m=\{v_1,\cdots,v_m\}\) be a set of basis of \(\mathcal{K}_m\), $W_m={ w_1,\cdots,w_m } $ be a set of basis of \(\mathcal{L}_m\). We further require that \(V_m\) and \(W_m\) satisfies \(W_m^TV_m=I_m\) . Then \(W_m^TAV_m\) and \(V_m^TA^TW_m\) are both Hessian, thus \(T_m=W_m^TAV_m\) is tridiagonal,
Then we calculate the LU decompostion of \(T_m=L_mU_m\), with the diagonal of Lm equals to 1
where
Now consider finding \(x_m\in x_0+\mathcal{K}_m\), such that \(r_m=b-Ax_m\) is orthogonal to \(\mathcal{L}_m\) . It follows immediately that \(r_m\in \mathcal{K}_{m+1}\) and $r_m\perp\mathcal{L}_m $ , then \(r_m=kv_{m+1}\). Let \(x_m=x_0+V_my_m\), then \(W_m^Tr_m=W_m^T(r_0-AV_my_m)=0\), i.e. \(y_m=T_m^{-1}(\beta e_0)\) , and \(x_m=x_0+V_mU_m^{-1}L_m^{-1}(\beta e_0)\) . Let \(P_m=V_mU_m^{-1}\) and \(Z_m=L_m^{-1}(\beta e_0)\), then by employ that
we can deduce that
Thus \(x_m=x_{m-1}+p_mz_m\) . Now define \(P^*_m=W_mL_m^{-1}\) , then \((P^*_m)^TAP_m=I_m\) . Now we can derive the BiCG algorithm using following equation
where
then
resulting code
def BCG(A,b,x,n):
    r1 = b - A @ x
    r2 = np.array(r1)
    for i in range(n):
        s = r1 @ r2
        if i==0:
            p1 = r1
            p2 = r2
        else:
            p1 = r1 + s / _s * _p1
            p2 = r2 + s / _s * _p2
        _s, _p1, _p2 = s, p1, p2
        q1 = A   @ p1
        q2 = A.T @ p2
        a = s / (p2 @ q1)
        x  = x + a * p1
        r1 = r1 - a * q1
        r2 = r2 - a * q2
        print(max(abs(r1)))
    return x
                    
                
                
            
        
浙公网安备 33010602011771号