コンテンツにスキップ

Krylov 部分空間法 II:GMRES・前処理・疎行列の反復解法

対象読者: 本テーマのクリロフ部分空間法 I(Lanczos・共役勾配法)、QR 分解、最小二乗問題の章を学んだ人。非対称行列の反復解法と前処理は仮定しません。

前提となる記事:Krylov 部分空間法 I:Lanczos 法と共役勾配法の最適性と Chebyshev 多項式による収束評価、最小二乗問題:正規方程式・QR・特異値分解と感度、QR 分解:Householder 変換・Givens 回転・Gram–Schmidt の安定性

生 Markdown

連立一次方程式 Ax=bA\boldsymbol{x}=\boldsymbol{b} の未知数が何百万もあるとき、行列を丸ごと分解するのは重すぎます。そこで、行列とベクトルの積だけを繰り返して、答えに少しずつ近づく方法を使います。この記事では、そのときまでに作れる候補の中で誤差(残差)が一番小さいものを選ぶ GMRES という方法と、近づく速さを上げる前処理を扱います。読み終えると、速く収束する場合と遅い場合の違い、前処理を置いても計算が途中で壊れない条件を、証明つきで説明できるようになります。

  • GMRES は x0+Kk(A,r0)\boldsymbol{x}_0+\mathcal{K}_k(A,\boldsymbol{r}_0) の上で残差 ∥b−Ax∥2\|\boldsymbol{b}-A\boldsymbol{x}\|_2 を最小にします。Arnoldi の関係式により、これは (k+1)×k(k+1)\times k の Hessenberg 行列(対角の 1 つ下までしか成分をもたない行列)の最小二乗問題になり、Givens 回転で 1 反復あたり O(k)O(k) の追加計算で逐次に解けます。
  • 厳密な算術では、Arnoldi の過程が止まった時点で厳密解に達し、nn 回以内に終わります。
  • 残差は rk=pk(A)r0\boldsymbol{r}_k=p_k(A)\boldsymbol{r}_0(pk(0)=1p_k(0)=1)の形で、正規行列では ∥rk∥/∥r0∥≤min⁡pmax⁡λ∈σ(A)∣p(λ)∣\|\boldsymbol{r}_k\|/\|\boldsymbol{r}_0\|\le\min_p\max_{\lambda\in\sigma(A)}|p(\lambda)|、対角化可能な行列ではこれに κ(V)\kappa(V) が掛かります。固有値が円板 ∣z−c∣≤ρ<∣c∣|z-c|\le\rho<|c| に入れば (ρ/∣c∣)kκ(V)(\rho/|c|)^k\kappa(V) です。非正規性が強いと κ(V)\kappa(V) が天文学的になり、固有値だけでは収束を予言できません。
  • 右前処理 AM−1u=bAM^{-1}\boldsymbol{u}=\boldsymbol{b} の GMRES は、左前処理と同じ部分空間の上で元の系の残差を最小にします。
  • 対称な M 行列(Stieltjes 行列。非対角成分がすべて 0 以下の正定値な対称行列)では、非零パターンを固定した不完全 Cholesky 分解 IC(0)(Cholesky 分解の途中で新しくできる非零成分を捨てる近似)が破綻しません。証明の鍵は Schur 補行列(1 段ぶん消去したあとに残る小さな行列)が Stieltjes 行列であり続けることと、非負行列のスペクトル半径の単調性です。

偏微分方程式を離散化すると、未知数が 10510^5〜10810^8 の疎な線形方程式が現れます。直接法(Cholesky 分解と疎行列の直接法)は fill-in(分解の途中で、もとは零だった成分が非零になること)のため 3 次元の問題では記憶容量が足りなくなり、反復法が必要になります。対称正定値なら共役勾配法(Krylov 部分空間法 I)が標準ですが、移流のある流れの問題・非対称な離散化・固有値問題のシフト反転では行列が非対称になり、共役勾配法の最適性は使えません。

GMRES は「Krylov 部分空間の上で残差を最小にする」という最も素直な一般化です。その代わり、Lanczos の三項漸化式が使えないので、反復ごとに全部の基底ベクトルと直交化する必要があり、記憶と演算が反復回数とともに増えます。そこで実務では、(1) 反復回数そのものを減らす前処理と、(2) 一定回数で打ち切る再始動が欠かせません。この記事では GMRES の最適性と収束の理論、前処理の 2 つの置き方の違い、代表的な前処理である不完全 Cholesky 分解がいつ安全に計算できるかを証明します。

A∈Cn×nA\in\mathbb{C}^{n\times n} は正則、b∈Cn\boldsymbol{b}\in\mathbb{C}^n、初期値 x0\boldsymbol{x}_0、r0=b−Ax0≠0\boldsymbol{r}_0=\boldsymbol{b}-A\boldsymbol{x}_0\ne\boldsymbol{0}、β=∥r0∥\beta=\|\boldsymbol{r}_0\| とします。ノルムは 2 ノルム、Pk\mathcal{P}_k は次数 kk 以下の多項式の全体です。Krylov 部分空間 Kk(A,r0)\mathcal{K}_k(A,\boldsymbol{r}_0)、r0\boldsymbol{r}_0 の次数 dd、Arnoldi の過程の QkQ_k、HkH_k、H~k\tilde H_k は Krylov 部分空間法 I の Krylov 部分空間の定義(定義 2.1)[Krylov 部分空間法 I] と Arnoldi の過程(定義 3.1)[Krylov 部分空間法 I] の記号(b\boldsymbol{b} を r0\boldsymbol{r}_0 に置き換える)をそのまま使います。中心になるのは次の事実です。

定義 3.1(GMRES)↗

1≤k≤d1\le k\le d について、x0+Kk(A,r0)\boldsymbol{x}_0+\mathcal{K}_k(A,\boldsymbol{r}_0) の中で ∥b−Ax∥\|\boldsymbol{b}-A\boldsymbol{x}\| を最小にする xk\boldsymbol{x}_k を GMRES の第 kk 近似解、rk=b−Axk\boldsymbol{r}_k=\boldsymbol{b}-A\boldsymbol{x}_k をその残差という(存在と一意性は下の定理で示す)。

次の定理のねらいは 2 つです。GMRES の近似解が、Arnoldi の関係式を通して小さな最小二乗問題に置き換わること、そしてその問題が Givens 回転で 1 反復ずつ安く更新できることです。Givens 回転は 2 つの行だけを混ぜて 1 つの成分を 0 にする操作で、反復が進んで新しい列が 1 本増えたときも、その列に回転をかけ直して新しい回転を 1 つ足せば済みます。

定理 3.2(GMRES の最小残差性と実装)✓

1≤k<d1\le k<d とする。

  1. H~k\tilde H_k は列が一次独立で、∥βe1−H~ky∥\|\beta\boldsymbol{e}_1-\tilde H_k\boldsymbol{y}\| を最小にする yk∈Ck\boldsymbol{y}_k\in\mathbb{C}^k はただ 1 つである。xk\boldsymbol{x}_k はただ 1 つ存在して xk=x0+Qkyk\boldsymbol{x}_k=\boldsymbol{x}_0+Q_k\boldsymbol{y}_k、∥rk∥=∥βe1−H~kyk∥\|\boldsymbol{r}_k\|=\|\beta\boldsymbol{e}_1-\tilde H_k\boldsymbol{y}_k\|。
  2. A,b,x0A,\boldsymbol{b},\boldsymbol{x}_0 が実のとき、第 jj・j+1j+1 行に作用する Givens 回転 GjG_j(j=1,…,kj=1,\ldots,k)を順に選んで Gk⋯G1H~k=(Rk0T)G_k\cdots G_1\tilde H_k=\binom{R_k}{\boldsymbol{0}^{\mathsf{T}}}(RkR_k は k×kk\times k の正則な上三角)とでき、g=Gk⋯G1(βe1)\boldsymbol{g}=G_k\cdots G_1(\beta\boldsymbol{e}_1) とおくと yk=Rk−1(g1,…,gk)T\boldsymbol{y}_k=R_k^{-1}(g_1,\ldots,g_k)^{\mathsf{T}}、∥rk∥=∣gk+1∣\|\boldsymbol{r}_k\|=|g_{k+1}|。kk から k+1k+1 に進むときは、H~k+1\tilde H_{k+1} の新しい列に G1,…,GkG_1,\ldots,G_k を作用させ、新しい回転 Gk+1G_{k+1} を 1 つ加えるだけでよい。
証明(定理 3.2)

(1) Arnoldi の関係式(定理 3.2)[Krylov 部分空間法 I] の 1 により、x∈x0+Kk\boldsymbol{x}\in\boldsymbol{x}_0+\mathcal{K}_k は x=x0+Qky\boldsymbol{x}=\boldsymbol{x}_0+Q_k\boldsymbol{y}(y∈Ck\boldsymbol{y}\in\mathbb{C}^k)と書け、QkQ_k の列は一次独立なので y\boldsymbol{y} は x\boldsymbol{x} から一意に決まります。同じ定理の 2 と r0=βq1=Qk+1(βe1)\boldsymbol{r}_0=\beta\boldsymbol{q}_1=Q_{k+1}(\beta\boldsymbol{e}_1) から

b−Ax=r0−AQky=Qk+1(βe1−H~ky)\boldsymbol{b}-A\boldsymbol{x}=\boldsymbol{r}_0-AQ_k\boldsymbol{y}=Q_{k+1}\bigl(\beta\boldsymbol{e}_1-\tilde H_k\boldsymbol{y}\bigr)

で、Qk+1Q_{k+1} の列は正規直交なので ∥b−Ax∥=∥βe1−H~ky∥\|\boldsymbol{b}-A\boldsymbol{x}\|=\|\beta\boldsymbol{e}_1-\tilde H_k\boldsymbol{y}\| です。H~k\tilde H_k は上 Hessenberg で、j≤k<dj\le k<d について hj+1,j>0h_{j+1,j}>0 です。H~k\tilde H_k の第 2〜k+1k+1 行は対角成分 hj+1,j≠0h_{j+1,j}\ne0 の上三角行列をなすので、H~k\tilde H_k の列は一次独立です。最小二乗解の特徴づけ(定理 3.2)[最小二乗問題] の 3 により最小解 yk\boldsymbol{y}_k は一意で、xk=x0+Qkyk\boldsymbol{x}_k=\boldsymbol{x}_0+Q_k\boldsymbol{y}_k も一意です。

(2) j=1,…,kj=1,\ldots,k の順に、その時点の第 jj 列の (j,j)(j,j) 成分 aa と (j+1,j)(j+1,j) 成分 bb から Givens 回転の性質(命題 3.4)[QR 分解] の回転を作って第 jj・j+1j+1 行に作用させると、(j+1,j)(j+1,j) 成分が 0 になります。bb は元の hj+1,j>0h_{j+1,j}>0 のままです(それより前の回転は第 j+1j+1 行を動かさない)から (a,b)≠(0,0)(a,b)\ne(0,0) です。第 jj 列より左の列の第 jj・j+1j+1 行はすでに 0 なので壊れません。こうして H~k=Q(Rk0T)\tilde H_k=Q\binom{R_k}{\boldsymbol{0}^{\mathsf{T}}}、QT=Gk⋯G1Q^{\mathsf{T}}=G_k\cdots G_1 は QR 分解で、QR 分解による最小二乗解(定理 5.1)[最小二乗問題] により RkR_k は正則、yk=Rk−1(g1,…,gk)T\boldsymbol{y}_k=R_k^{-1}(g_1,\ldots,g_k)^{\mathsf{T}}、最小残差は ∣gk+1∣|g_{k+1}| です。

H~k+1\tilde H_{k+1} は H~k\tilde H_k の下に零の行を足し、右に新しい列 (h1,k+1,…,hk+2,k+1)T(h_{1,k+1},\ldots,h_{k+2,k+1})^{\mathsf{T}} を足したものです。G1,…,GkG_1,\ldots,G_k は第 11〜k+1k+1 行にしか作用しないので、最初の kk 列は (Rk0)\binom{R_k}{\boldsymbol{0}} のまま(第 k+2k+2 行は 0)です。新しい列に G1,…,GkG_1,\ldots,G_k を作用させ、その (k+1,k+1)(k+1,k+1)・(k+2,k+1)(k+2,k+1) 成分から Gk+1G_{k+1} を作れば QR 分解が更新され、g\boldsymbol{g} も (g1,…,gk+1,0)T(g_1,\ldots,g_{k+1},0)^{\mathsf{T}} に Gk+1G_{k+1} を作用させるだけです。

実装の要点. 反復 kk ごとの主な手間は、行列ベクトル積 1 回と、q1,…,qk\boldsymbol{q}_1,\ldots,\boldsymbol{q}_k との直交化(内積 kk 回、O(nk)O(nk))です。kk 回の合計は O(nk2)O(nk^2)、記憶は O(nk)O(nk) です。残差のノルム ∣gk+1∣|g_{k+1}| は xk\boldsymbol{x}_k を作らずに分かるので、停止の判定は安く済み、xk\boldsymbol{x}_k は最後に 1 回だけ作ります。浮動小数の Arnoldi では修正 Gram–Schmidt か再直交化を使います(QR 分解 の 再直交化の注意(注意 6.5)[QR 分解])。

命題 3.3(Arnoldi が止まれば厳密解)✓

k=dk=d(Arnoldi の過程が hd+1,d=0h_{d+1,d}=0 で止まる)のとき、HdH_d は正則で xd=x0+QdHd−1(βe1)\boldsymbol{x}_d=\boldsymbol{x}_0+Q_dH_d^{-1}(\beta\boldsymbol{e}_1) は Ax=bA\boldsymbol{x}=\boldsymbol{b} の厳密解であり、x0+Kd\boldsymbol{x}_0+\mathcal{K}_d の上で残差を最小にする(rd=0\boldsymbol{r}_d=\boldsymbol{0})。とくに厳密な算術では GMRES は d≤nd\le n 回以内に厳密解に達し、AA が対角化可能なら相異なる固有値の個数以内に達する。

証明(命題 3.3)

Arnoldi の関係式(定理 3.2)[Krylov 部分空間法 I] の 2 から AQd=QdHdAQ_d=Q_dH_d です。Hdy=0H_d\boldsymbol{y}=\boldsymbol{0} なら AQdy=0AQ_d\boldsymbol{y}=\boldsymbol{0}、AA は正則なので Qdy=0Q_d\boldsymbol{y}=\boldsymbol{0}、QdQ_d の列は一次独立なので y=0\boldsymbol{y}=\boldsymbol{0} です。よって HdH_d は正則です。x=x0+Qdy\boldsymbol{x}=\boldsymbol{x}_0+Q_d\boldsymbol{y} について b−Ax=Qd(βe1−Hdy)\boldsymbol{b}-A\boldsymbol{x}=Q_d(\beta\boldsymbol{e}_1-H_d\boldsymbol{y}) で、y=Hd−1βe1\boldsymbol{y}=H_d^{-1}\beta\boldsymbol{e}_1 とすれば 0 になります。残差のノルムは非負なのでこれが最小です。d≤nd\le n と、対角化可能なとき dd が相異なる固有値の個数以下であることは Krylov 部分空間の基本性質(命題 2.2)[Krylov 部分空間法 I] の 2・3 です。

止まること(breakdown)は失敗ではなく、成功です。共役勾配法と違い、GMRES の残差は単調非増加です(Kk⊂Kk+1\mathcal{K}_k\subset\mathcal{K}_{k+1} の上での最小化だから)。

補題 4.1(残差多項式)✓

1≤k≤d1\le k\le d について

∥rk∥=min⁡{∥p(A)r0∥:p∈Pk, p(0)=1}.\|\boldsymbol{r}_k\|=\min\bigl\{\|p(A)\boldsymbol{r}_0\|:p\in\mathcal{P}_k,\ p(0)=1\bigr\}.
証明(補題 4.1)

Krylov 部分空間の基本性質(命題 2.2)[Krylov 部分空間法 I] の 1 により x∈x0+Kk\boldsymbol{x}\in\boldsymbol{x}_0+\mathcal{K}_k は x=x0+q(A)r0\boldsymbol{x}=\boldsymbol{x}_0+q(A)\boldsymbol{r}_0(q∈Pk−1q\in\mathcal{P}_{k-1})と書け、b−Ax=r0−Aq(A)r0=p(A)r0\boldsymbol{b}-A\boldsymbol{x}=\boldsymbol{r}_0-Aq(A)\boldsymbol{r}_0=p(A)\boldsymbol{r}_0、p(t)=1−tq(t)p(t)=1-tq(t) です。逆に p∈Pkp\in\mathcal{P}_k、p(0)=1p(0)=1 なら p(t)−1p(t)-1 は定数項が 0 なので p(t)=1−tq(t)p(t)=1-tq(t)(q∈Pk−1q\in\mathcal{P}_{k-1})と書けます。したがって {b−Ax}\{\boldsymbol{b}-A\boldsymbol{x}\} と {p(A)r0}\{p(A)\boldsymbol{r}_0\} は同じ集合で、最小値(定理 3.2 と 命題 3.3 により存在する)は等しいです。

定理 4.2(正規行列での GMRES の収束)✓

AA が正規行列なら、1≤k≤d1\le k\le d について

∥rk∥∥r0∥≤min⁡p∈Pk, p(0)=1 max⁡λ∈σ(A)∣p(λ)∣.\frac{\|\boldsymbol{r}_k\|}{\|\boldsymbol{r}_0\|}\le\min_{p\in\mathcal{P}_k,\ p(0)=1}\ \max_{\lambda\in\sigma(A)}|p(\lambda)|.
証明(定理 4.2)

正規行列のスペクトル定理(定理 8.1)[スペクトル定理] により A=UDU∗A=UDU^{*}(UU はユニタリ、D=diag⁡(λ1,…,λn)D=\operatorname{diag}(\lambda_1,\ldots,\lambda_n))です。Aj=UDjU∗A^j=UD^jU^{*} なので p(A)=Up(D)U∗p(A)=Up(D)U^{*} で、UU と U∗U^{*} はノルムを保つ(ユニタリ行列の特徴づけ(命題 3.2)[スペクトル定理])から

∥p(A)r0∥=∥p(D)U∗r0∥=(∑i∣p(λi)∣2∣(U∗r0)i∣2)1/2≤max⁡i∣p(λi)∣ ∥r0∥\|p(A)\boldsymbol{r}_0\|=\|p(D)U^{*}\boldsymbol{r}_0\|=\Bigl(\sum_i|p(\lambda_i)|^2|(U^{*}\boldsymbol{r}_0)_i|^2\Bigr)^{1/2}\le\max_i|p(\lambda_i)|\,\|\boldsymbol{r}_0\|

です。補題 4.1 で pp について最小をとれば主張です。

系 4.3(対角化可能な行列での GMRES の収束)✓

A=VΛV−1A=V\Lambda V^{-1}(Λ\Lambda は対角)と対角化できるなら、1≤k≤d1\le k\le d について

∥rk∥∥r0∥≤κ(V)min⁡p∈Pk, p(0)=1 max⁡λ∈σ(A)∣p(λ)∣,κ(V)=∥V∥∥V−1∥.\frac{\|\boldsymbol{r}_k\|}{\|\boldsymbol{r}_0\|}\le\kappa(V)\min_{p\in\mathcal{P}_k,\ p(0)=1}\ \max_{\lambda\in\sigma(A)}|p(\lambda)|,\qquad\kappa(V)=\|V\|\|V^{-1}\|.
証明(系 4.3)

p(A)=Vp(Λ)V−1p(A)=Vp(\Lambda)V^{-1} なので ∥p(A)r0∥≤∥V∥∥p(Λ)∥∥V−1∥∥r0∥\|p(A)\boldsymbol{r}_0\|\le\|V\|\|p(\Lambda)\|\|V^{-1}\|\|\boldsymbol{r}_0\| で、対角行列では ∥p(Λ)z∥2=∑i∣p(λi)∣2∣zi∣2\|p(\Lambda)\boldsymbol{z}\|^2=\sum_i|p(\lambda_i)|^2|z_i|^2 から ∥p(Λ)∥=max⁡i∣p(λi)∣\|p(\Lambda)\|=\max_i|p(\lambda_i)| です。補題 4.1 で最小をとります。

系 4.4(固有値が円板に入るときの評価)✓

A=VΛV−1A=V\Lambda V^{-1} と対角化でき、すべての固有値が円板 ∣z−c∣≤ρ|z-c|\le\rho(0≤ρ<∣c∣0\le\rho<|c|)に入るなら、1≤k≤d1\le k\le d について ∥rk∥/∥r0∥≤κ(V)(ρ/∣c∣)k\|\boldsymbol{r}_k\|/\|\boldsymbol{r}_0\|\le\kappa(V)(\rho/|c|)^k。

証明(系 4.4)

p(z)=(1−z/c)kp(z)=(1-z/c)^k は Pk\mathcal{P}_k に属し p(0)=1p(0)=1 で、固有値 λ\lambda について ∣p(λ)∣=∣c−λ∣k/∣c∣k≤(ρ/∣c∣)k|p(\lambda)|=|c-\lambda|^k/|c|^k\le(\rho/|c|)^k です。系 4.3 に代入します。

前処理の目標は、この評価が効く形、すなわち「固有値が 0 から離れた小さな円板に集まり、κ(V)\kappa(V) も小さい」形に AA を変えることです。c=1c=1 の近くに固有値を集めるのが典型で、M≈AM\approx A なら M−1A≈IM^{-1}A\approx I です。

次の例のねらいは、固有値の位置が同じでも収束の速さが大きく違いうることを、数値で見ることです。gg は行列の「正規からのずれ」の強さを決める数で、κ(V)\kappa(V) は固有ベクトルを並べた行列の条件数です。上の収束の評価が κ(V)\kappa(V) を含んでいたことが、ここで効いてきます。

例 4.5(非正規行列では固有値の評価が役に立たない)

対角に 0.50.5 から 1.51.5 まで等間隔の 100 個の固有値を並べ、すぐ上の副対角に gg を置いた上三角行列 AgA_g を考えます。固有値は gg によらず円板 ∣z−1∣≤0.5|z-1|\le0.5 に入り、系 4.4 の (ρ/∣c∣)k=0.5k(\rho/|c|)^k=0.5^k に κ(V)\kappa(V) を掛けたものが評価です。g=0g=0 は対角(正規)行列です。b=(1,…,1)T\boldsymbol{b}=(1,\ldots,1)^{\mathsf{T}}、x0=0\boldsymbol{x}_0=\boldsymbol{0} で、再始動なしの GMRES の相対残差 ∥rk∥/∥r0∥\|\boldsymbol{r}_k\|/\|\boldsymbol{r}_0\| を記録します(-- は収束して停止した後)。

# Python 3.12.10 / NumPy 2.5.2 / SciPy 1.18.1
import numpy as np, scipy.sparse.linalg as sla
n = 100
lam = np.linspace(0.5, 1.5, n) # 固有値は円板 |z-1| <= 0.5 の中
b = np.ones(n)
gs = (0.0, 1.0, 2.0)
hist = {}
for g in gs: # 上の副対角 g が非正規性の強さ
A = np.diag(lam) + g * np.eye(n, k=1)
res = [] # 相対残差 |r_k|/|r_0| の履歴
sla.gmres(A, b, rtol=1e-13, restart=n, maxiter=1,
callback=res.append, callback_type="pr_norm")
hist[g] = res
fmt = lambda r, k: f"{r[k-1]:.1e}" if k <= len(r) else " -- "
print(" k 0.5^k g=0 g=1 g=2")
for k in (5, 10, 20, 40, 60, 80):
row = " ".join(fmt(hist[g], k) for g in gs)
print(f"{k:3d} {0.5**k:.1e} {row}")
k 0.5^k g=0 g=1 g=2
5 3.1e-02 1.6e-03 6.0e-03 4.2e-02
10 9.8e-04 2.4e-06 9.3e-04 4.1e-02
20 9.5e-07 4.5e-12 3.8e-05 4.1e-02
40 9.1e-13 -- 6.2e-07 4.1e-02
60 8.7e-19 -- 1.8e-07 4.1e-02
80 8.3e-25 -- 1.7e-07 4.1e-02

固有ベクトル行列は上三角で、成分は閉じた形 vij=g vi+1,j/(λj−λi)v_{ij}=g\,v_{i+1,j}/(\lambda_j-\lambda_i) で書けます。浮動小数の eig ではこの条件数を正しく計算できないので、mpmath の 250 桁で計算します(列は単位ベクトルに正規化)。

# (続き)固有ベクトル行列の条件数を mpmath の 250 桁で計算
import mpmath as mp # mpmath 1.3.0
mp.mp.dps = 250
n = 100
lm = [mp.mpf(1) / 2 + mp.mpf(i) / (n - 1) for i in range(n)]
for g in (1, 2):
V = mp.zeros(n, n)
for j in range(n): # 上三角の固有ベクトル(閉じた形)
V[j, j] = 1
for i in range(j - 1, -1, -1):
V[i, j] = g * V[i + 1, j] / (lm[j] - lm[i])
nj = mp.norm(V[:, j])
for i in range(j + 1):
V[i, j] /= nj # 列を単位ベクトルに
s = mp.svd_r(V, compute_uv=False)
print(f"g={g}: kappa(V) =", mp.nstr(max(s) / min(s), 3))
g=1: kappa(V) = 7.35e+71
g=2: kappa(V) = 3.99e+101

g=0g=0 では残差は 0.5k0.5^k よりずっと速く減り、g=1g=1 では遅くなって k=60k=60 以降 1.7×10−71.7\times10^{-7} の付近で止まり、g=2g=2 では k=10k=10 以降 4×10−24\times10^{-2} で停滞します。g=1g=1 の停滞は丸め誤差のせいではなく、厳密な GMRES の性質です。GMRES を mpmath の 40 桁で計算しても k=40,60,80,90k=40,60,80,90 の相対残差は 6.2×10−76.2\times10^{-7}、1.8×10−71.8\times10^{-7}、1.73×10−71.73\times10^{-7}、1.73×10−71.73\times10^{-7} で、倍精度の表と一致しました。厳密な算術では残差は単調非増加で、k=d≤100k=d\le100 で 0 になる(命題 3.3)ので、停滞はその手前の長い区間で起きていることになります。κ(V)≈1072,10102\kappa(V)\approx10^{72},10^{102} を掛けた評価は意味を持ちません。固有値が同じでも、非正規性の強さで収束はまったく違います。

検算. (a) 既知値: g=0g=0 では固有値が実区間 [0.5,1.5][0.5,1.5] にあり、定理 4.2 に p(z)=Tk(2(1−z))/Tk(2)p(z)=T_k(2(1-z))/T_k(2)(TkT_k は Chebyshev 多項式、区間上で ∣Tk(2(1−z))∣≤1|T_k(2(1-z))|\le1)を入れると評価は 1/Tk(2)1/T_k(2) です。T5(2)=362T_5(2)=362、T10(2)=262087T_{10}(2)=262087、T20(2)=2T10(2)2−1≈1.37×1011T_{20}(2)=2T_{10}(2)^2-1\approx1.37\times10^{11} から評価は 2.8×10−32.8\times10^{-3}、3.8×10−63.8\times10^{-6}、7.3×10−127.3\times10^{-12} で、表の 1.6×10−31.6\times10^{-3}、2.4×10−62.4\times10^{-6}、4.5×10−124.5\times10^{-12} はその内側にあります。(b) 別精度: κ(V)\kappa(V) は mpmath の 250 桁で計算し、350 桁でも表示桁が一致することを確かめました。(c) 次数: g=0g=0 の残差の比 ∥r20∥/∥r10∥≈1.9×10−6\|\boldsymbol{r}_{20}\|/\|\boldsymbol{r}_{10}\|\approx1.9\times10^{-6} は、Chebyshev の評価の比 T10(2)/T20(2)≈1.9×10−6T_{10}(2)/T_{20}(2)\approx1.9\times10^{-6} とほぼ一致します。

注意 4.6

任意の収束曲線(主張のみ、定理環境にしない). 任意の非増加な列 1=f0≥f1≥⋯≥fn−1>01=f_0\ge f_1\ge\cdots\ge f_{n-1}>0 と、任意の nn 個の 0 でない複素数に対し、それらを固有値にもち、GMRES の相対残差がちょうど fkf_k になる行列と右辺が存在します(Greenbaum–Pták–Strakoš 1996)。固有値だけから GMRES の収束について何も言えない、という上の例の極端な形です。非正規行列の収束は、擬スペクトルや数値域で論じます(Greenbaum の教科書 Ch. 3)。この記事の証明では使いません。

注意 4.7

再始動と他の Krylov 法. 記憶と直交化の手間を抑えるため、mm 回ごとに xm\boldsymbol{x}_m を新しい初期値として最初からやり直すのが GMRES(mm) です。残差は単調非増加のままですが、部分空間を捨てるので停滞しうる(たとえば Ar0⊥r0A\boldsymbol{r}_0\perp\boldsymbol{r}_0 型の行列で 1 歩も進まない)ことが知られています。BiCGSTAB は短い漸化式で記憶を一定に保つ非対称向けの方法、MINRES は対称(不定値でもよい)な行列で GMRES と同じ最小残差の解を三項漸化式で計算する方法です(Saad の教科書 Ch. 6–7、Greenbaum の教科書 Ch. 2)。この記事では定理として扱いません。

定義 5.1(左前処理と右前処理)↗

正則な M∈Cn×nM\in\mathbb{C}^{n\times n}(前処理行列。M≈AM\approx A で、Mz=cM\boldsymbol{z}=\boldsymbol{c} が安く解けるもの)について、M−1Ax=M−1bM^{-1}A\boldsymbol{x}=M^{-1}\boldsymbol{b} に反復法を使うことを左前処理、AM−1u=bAM^{-1}\boldsymbol{u}=\boldsymbol{b} を解いて x=M−1u\boldsymbol{x}=M^{-1}\boldsymbol{u} とすることを右前処理という。

命題 5.2(右前処理の GMRES は元の残差を最小にする)✓

AM−1AM^{-1} と初期値 u0=Mx0\boldsymbol{u}_0=M\boldsymbol{x}_0 に GMRES を使った第 kk 近似解を uk\boldsymbol{u}_k とし、xk=M−1uk\boldsymbol{x}_k=M^{-1}\boldsymbol{u}_k とおく。このとき xk\boldsymbol{x}_k は

x0+Kk(M−1A, M−1r0)\boldsymbol{x}_0+\mathcal{K}_k(M^{-1}A,\ M^{-1}\boldsymbol{r}_0)

の中で ∥b−Ax∥\|\boldsymbol{b}-A\boldsymbol{x}\| を最小にする。一方、M−1AM^{-1}A、M−1bM^{-1}\boldsymbol{b}、x0\boldsymbol{x}_0 に GMRES を使う左前処理の第 kk 近似解は、同じ集合の中で ∥M−1(b−Ax)∥\|M^{-1}(\boldsymbol{b}-A\boldsymbol{x})\| を最小にする(kk はそれぞれの Krylov 部分空間の次数以下とする)。

証明(命題 5.2)

右前処理: 系 AM−1u=bAM^{-1}\boldsymbol{u}=\boldsymbol{b} の初期残差は b−AM−1u0=b−Ax0=r0\boldsymbol{b}-AM^{-1}\boldsymbol{u}_0=\boldsymbol{b}-A\boldsymbol{x}_0=\boldsymbol{r}_0 で、u\boldsymbol{u} の残差は b−AM−1u=b−A(M−1u)\boldsymbol{b}-AM^{-1}\boldsymbol{u}=\boldsymbol{b}-A(M^{-1}\boldsymbol{u}) です。GMRES は u∈u0+Kk(AM−1,r0)\boldsymbol{u}\in\boldsymbol{u}_0+\mathcal{K}_k(AM^{-1},\boldsymbol{r}_0) の中でこれを最小にします。u↦M−1u\boldsymbol{u}\mapsto M^{-1}\boldsymbol{u} は全単射で、jj についての帰納法で M−1(AM−1)j=(M−1A)jM−1M^{-1}(AM^{-1})^j=(M^{-1}A)^jM^{-1} なので

M−1(u0+Kk(AM−1,r0))=x0+span⁡{(M−1A)jM−1r0:j<k}=x0+Kk(M−1A,M−1r0)M^{-1}\bigl(\boldsymbol{u}_0+\mathcal{K}_k(AM^{-1},\boldsymbol{r}_0)\bigr)=\boldsymbol{x}_0+\operatorname{span}\{(M^{-1}A)^jM^{-1}\boldsymbol{r}_0:j<k\}=\boldsymbol{x}_0+\mathcal{K}_k(M^{-1}A,M^{-1}\boldsymbol{r}_0)

です。よって xk=M−1uk\boldsymbol{x}_k=M^{-1}\boldsymbol{u}_k は主張の集合の中で ∥b−Ax∥\|\boldsymbol{b}-A\boldsymbol{x}\| を最小にします。

左前処理: 系 M−1Ax=M−1bM^{-1}A\boldsymbol{x}=M^{-1}\boldsymbol{b} の初期残差は M−1r0M^{-1}\boldsymbol{r}_0、残差は M−1(b−Ax)M^{-1}(\boldsymbol{b}-A\boldsymbol{x}) で、GMRES の定義(定義 3.1)どおりこれを x0+Kk(M−1A,M−1r0)\boldsymbol{x}_0+\mathcal{K}_k(M^{-1}A,M^{-1}\boldsymbol{r}_0) の上で最小にします。

2 つは同じ部分空間を探しますが、最小にする量が違います。左前処理では、停止判定に使う残差 ∥M−1rk∥\|M^{-1}\boldsymbol{r}_k\| が小さくても、MM が悪条件なら元の残差 ∥rk∥\|\boldsymbol{r}_k\| は小さいとは限りません。右前処理では停止判定の残差がそのまま元の系の残差です。SciPy の gmres に M= を渡すと左前処理になる(前処理つき残差を最小にし、最後に元の残差で収束を確かめる)ので、右前処理にしたいときは AM−1AM^{-1} を LinearOperator として渡します。

例 5.3(移流拡散方程式:再始動と ILU 前処理)

単位正方形で −Δu+β(ux+uy)=1-\Delta u+\beta(u_x+u_y)=1、境界で u=0u=0 を、格子幅 h=1/(N+1)h=1/(N+1) の中心差分で離散化します。行列は非対称で、βh/2\beta h/2(格子 Péclet 数)が大きいほど非正規性が増します。相対残差 10−810^{-8} までの反復回数を、再始動なし(full)、GMRES(20)、spilu(しきい値つき不完全 LU、drop_tol=1e-3、fill_factor=5)を右前処理にした場合で比べます。参照解は spsolve の直接法です。

# Python 3.12.10 / NumPy 2.5.2 / SciPy 1.18.1
import numpy as np, scipy.sparse as sp, scipy.sparse.linalg as sla
def conv_diff(N, beta): # -Δu + beta (u_x + u_y)、中心差分
h = 1.0 / (N + 1); I = sp.eye(N)
T = sp.diags([-1.0, 2.0, -1.0], [-1, 0, 1], shape=(N, N)) / h**2
C = sp.diags([-1.0, 1.0], [-1, 1], shape=(N, N)) * beta / (2 * h)
return (sp.kron(I, T + C) + sp.kron(T + C, I)).tocsc()
def run(A, b, **kw): # 内側の反復回数を数える
it = [0]
cb = lambda r: it.__setitem__(0, it[0] + 1)
x, info = sla.gmres(A, b, rtol=1e-8, callback=cb,
callback_type="pr_norm", **kw)
return it[0], x
print(" N beta full GMRES(20) ILU-right fill err(right)")
for N, beta in ((32, 10.0), (32, 100.0), (64, 10.0), (64, 100.0)):
A = conv_diff(N, beta); n = N * N
b = np.ones(n); xs = sla.spsolve(A, b) # 参照解
k1 = run(A, b, restart=n, maxiter=1)[0]
k2 = run(A, b, restart=20, maxiter=500)[0]
ilu = sla.spilu(A, drop_tol=1e-3, fill_factor=5)
AM = sla.LinearOperator((n, n), matvec=lambda v: A @ ilu.solve(v))
k3, u = run(AM, b, restart=n, maxiter=1) # 右前処理
x = ilu.solve(u) # x = M^{-1} u
e = np.linalg.norm(x - xs) / np.linalg.norm(xs)
fill = (ilu.L.nnz + ilu.U.nnz) / A.nnz
print(f"{N:3d} {beta:5.0f} {k1:4d} {k2:9d} {k3:9d}"
f" {fill:4.1f} {e:.1e}")
N beta full GMRES(20) ILU-right fill err(right)
32 10 91 206 35 3.5 4.3e-10
32 100 71 217 20 3.3 5.9e-10
64 10 181 299 76 3.5 6.2e-10
64 100 131 224 40 3.2 1.4e-10

再始動なしの GMRES の反復回数は NN を 2 倍にするとほぼ 2 倍(h−1h^{-1} に比例)で、GMRES(20) は 1.6〜3.1 倍の反復を要します(1 反復の直交化は安い)。ILU の右前処理は、元の行列の 3〜3.5 倍の非零を使って反復回数をおよそ 0.3〜0.4 倍に減らします。

検算. (a) 既知値: 右辺と境界条件を固定した離散問題の厳密解(直接法の解)を参照値とし、右前処理の解との相対差は 10−1010^{-10} の程度で、相対残差 10−810^{-8} で止めた解として妥当な大きさです。(b) 別手法: 参照値は反復法と独立な疎 LU 分解(spsolve)で計算しました。(c) 次数: full GMRES の反復回数の比は β=10\beta=10 で 181/91≈1.99181/91\approx1.99、β=100\beta=100 で 131/71≈1.85131/71\approx1.85 と、h−1h^{-1} の増え方に近い値です。

対称正定値の系には、Cholesky 分解 A=LLTA=LL^{\mathsf{T}}(Cholesky 分解の存在(定理 2.1)[Cholesky 分解と帯行列・疎行列の直接法])の fill-in を捨てた近似 M=LLTM=LL^{\mathsf{T}} を共役勾配法の前処理に使うのが標準です。fill-in を捨てると正定値性が保たれる保証がなくなり、途中で平方根の中が負になって破綻しえます。ここでは、それが起きない行列のクラスを特定します。

定義 6.1(Z 行列と Stieltjes 行列)↗

非対角成分がすべて 00 以下の実正方行列を Z 行列という。正定値な対称 Z 行列を Stieltjes 行列(対称な M 行列)という。実行列 N,N′N,N' について N≥0N\ge0 や N′≤NN'\le N は成分ごとの不等式とする。

離散 Laplace 行列(2 次元・3 次元を含む)は Stieltjes 行列の代表例です。

次の補題は、成分を小さくした非負行列のスペクトル半径は大きくならない、という事実です。IC の算法で成分を捨てたあとも正定値のままか、を確かめる場面で使います。証明の方針は、N/tN/t の冪が 0 に近づくなら、それ以下の成分をもつ N′/tN'/t の冪も 0 に近づく、という比較です。

補題 6.2(非負行列のスペクトル半径の単調性)✓

N,N′∈Rn×nN,N'\in\mathbb{R}^{n\times n} が 0≤N′≤N0\le N'\le N を満たすなら ρ(N′)≤ρ(N)\rho(N')\le\rho(N)。

証明(補題 6.2)

t>ρ(N)t>\rho(N) を任意にとります。成分が非負の行列の積は各因子について成分ごとに単調なので、kk についての帰納法で 0≤(N′/t)k≤(N/t)k0\le(N'/t)^k\le(N/t)^k です。ρ(N/t)<1\rho(N/t)<1 なので 行列の冪の収束(系 5.3)[行列のノルムと線形方程式の条件数] により (N/t)k→0(N/t)^k\to0、はさみうちで (N′/t)k→0(N'/t)^k\to0、同じ系から ρ(N′/t)<1\rho(N'/t)<1、すなわち ρ(N′)<t\rho(N')<t です。t>ρ(N)t>\rho(N) は任意なので ρ(N′)≤ρ(N)\rho(N')\le\rho(N) です。

補題 6.3(Stieltjes 行列の特徴づけ)✓

AA を対称 Z 行列、s≥max⁡iaiis\ge\max_ia_{ii}、N=sI−AN=sI-A とすると N≥0N\ge0 で、AA が正定値   ⟺  ρ(N)<s\iff\rho(N)<s。

証明(補題 6.3)

NN の対角は s−aii≥0s-a_{ii}\ge0、非対角は −aij≥0-a_{ij}\ge0 です。NN は実対称なので、主軸定理(定理 6.3)[スペクトル定理] により実の正規直交固有ベクトルの基底があり、固有値 μ1≥⋯≥μn\mu_1\ge\cdots\ge\mu_n は実数、AA の固有値は s−μis-\mu_i です。同じ定理の 2 により AA が正定値   ⟺  \iff 全 ii で s−μi>0  ⟺  μ1<ss-\mu_i>0\iff\mu_1<s です。あとは μ1=ρ(N)\mu_1=\rho(N) を示します。Nx=μxN\boldsymbol{x}=\mu\boldsymbol{x}、x\boldsymbol{x} は実の単位ベクトルとすると、N≥0N\ge0 と Rayleigh 商の最大・最小(定理 7.1)[スペクトル定理] から

∣μ∣=∣xTNx∣≤∣x∣TN∣x∣≤μ1|\mu|=|\boldsymbol{x}^{\mathsf{T}}N\boldsymbol{x}|\le|\boldsymbol{x}|^{\mathsf{T}}N|\boldsymbol{x}|\le\mu_1

です(∣x∣|\boldsymbol{x}| も単位ベクトル)。よって ρ(N)≤μ1≤ρ(N)\rho(N)\le\mu_1\le\rho(N) です。

IC の算法(ねらい). Cholesky 分解を 1 列ずつ進めると、各段で「まだ分解していない部分」を表す小さな行列(Schur 補行列)が残ります。IC は、その行列の成分のうち、あらかじめ決めた非零パターンの外にあるものを 0 に捨てて次の段へ進みます。捨てると正定値性が壊れて平方根の中が負になりかねないので、次の定理は、Stieltjes 行列ならそれが起きないことを段ごとの帰納法で示します。

IC の算法. 非零パターン S⊂{1,…,n}2S\subset\{1,\ldots,n\}^2 を、対称((i,j)∈S⇒(j,i)∈S(i,j)\in S\Rightarrow(j,i)\in S)で対角を含み、AA の非零成分の位置をすべて含むものとします(SS を AA の非零パターンそのものにとるのが IC(0))。B(1)=AB^{(1)}=A とし、k=1,…,nk=1,\ldots,n について、n−k+1n-k+1 次の対称行列 B(k)B^{(k)}(添字は k,…,nk,\ldots,n)を

B(k)=(dkwkTwkCk),lkk=dk,lik=(wk)idk (i>k)B^{(k)}=\begin{pmatrix}d_k&\boldsymbol{w}_k^{\mathsf{T}}\\\boldsymbol{w}_k&C_k\end{pmatrix},\qquad l_{kk}=\sqrt{d_k},\quad l_{ik}=\frac{(\boldsymbol{w}_k)_i}{\sqrt{d_k}}\ (i>k)

と分け、Schur 補行列 Sk=Ck−wkwkT/dkS_k=C_k-\boldsymbol{w}_k\boldsymbol{w}_k^{\mathsf{T}}/d_k の (i,j)∉S(i,j)\notin S の成分を 00 に置き換えたものを B(k+1)B^{(k+1)} とします。置き換えの差を FkF_k(B(k+1)=Sk+FkB^{(k+1)}=S_k+F_k)とします。

定理 6.4(Stieltjes 行列の不完全 Cholesky 分解は破綻しない)✓

AA が Stieltjes 行列なら、上の算法のすべての段で dk>0d_k>0 であり、各 B(k)B^{(k)} は Stieltjes 行列である。得られる下三角行列 L=(lij)L=(l_{ij}) は対角成分が正で、(i,j)∉S(i,j)\notin S では lij=0l_{ij}=0 であり、

LLT=A+R,R=∑kFk (位置を埋め込んだ和) ≥0,(i,j)∈S で rij=0LL^{\mathsf{T}}=A+R,\qquad R=\sum_kF_k\ (\text{位置を埋め込んだ和})\ \ge0,\qquad(i,j)\in S\text{ で }r_{ij}=0

が成り立つ。とくに M=LLTM=LL^{\mathsf{T}} は正定値である(Meijerink–van der Vorst の対称な場合)。

証明(定理 6.4)

帰納法の主張. B(k)B^{(k)} は Stieltjes 行列で、(i,j)∉S(i,j)\notin S の成分は 0 である。k=1k=1 では仮定どおりです(SS は AA の非零パターンを含む)。

dk>0d_k>0. 正定値行列の対角成分は e1TB(k)e1>0\boldsymbol{e}_1^{\mathsf{T}}B^{(k)}\boldsymbol{e}_1>0 です。

Schur 補行列. 行と列の順序を入れ替えた (CkwkwkTdk)\begin{pmatrix}C_k&\boldsymbol{w}_k\\\boldsymbol{w}_k^{\mathsf{T}}&d_k\end{pmatrix} は B(k)B^{(k)} と置換行列で合同なので正定値です(xTPTBPx=(Px)TB(Px)\boldsymbol{x}^{\mathsf{T}}P^{\mathsf{T}}BP\boldsymbol{x}=(P\boldsymbol{x})^{\mathsf{T}}B(P\boldsymbol{x}))。Schur 補行列(定理 4.2)[行列の固有値評価と不等式] の 3(右下の dk>0d_k>0 は正定値)により Sk=Ck−wkdk−1wkTS_k=C_k-\boldsymbol{w}_kd_k^{-1}\boldsymbol{w}_k^{\mathsf{T}} は正定値です。非対角成分は、(wk)i,(wk)j≤0(\boldsymbol{w}_k)_i,(\boldsymbol{w}_k)_j\le0 から (wk)i(wk)j≥0(\boldsymbol{w}_k)_i(\boldsymbol{w}_k)_j\ge0 なので (Sk)ij≤(Ck)ij≤0(S_k)_{ij}\le(C_k)_{ij}\le0 です。よって SkS_k は Stieltjes 行列です。

捨てる操作. s=max⁡i(Sk)iis=\max_i(S_k)_{ii} とし、Sk=sI−NS_k=sI-N と書くと、補題 6.3 により N≥0N\ge0、ρ(N)<s\rho(N)<s です。B(k+1)B^{(k+1)} は SkS_k の非対角成分のいくつかを(対称に)0 に置き換えたものなので、対角は同じで B(k+1)=sI−N′B^{(k+1)}=sI-N'、0≤N′≤N0\le N'\le N です。補題 6.2 で ρ(N′)≤ρ(N)<s\rho(N')\le\rho(N)<s、ふたたび 補題 6.3 で B(k+1)B^{(k+1)} は正定値で、対称 Z 行列なので Stieltjes 行列です。(i,j)∉S(i,j)\notin S の成分が 0 であることは作り方のとおりで、帰納法が進みます。

分解の式. (wk)i(\boldsymbol{w}_k)_i は B(k)B^{(k)} の (i,k)(i,k) 成分なので、(i,k)∉S(i,k)\notin S なら 00 で、lik=0l_{ik}=0 です。lk=(lkk,…,lnk)T\boldsymbol{l}_k=(l_{kk},\ldots,l_{nk})^{\mathsf{T}} とおくと B(k)−lklkT=(00T0Sk)=(00T0B(k+1)−Fk)B^{(k)}-\boldsymbol{l}_k\boldsymbol{l}_k^{\mathsf{T}}=\begin{pmatrix}0&\boldsymbol{0}^{\mathsf{T}}\\\boldsymbol{0}&S_k\end{pmatrix}=\begin{pmatrix}0&\boldsymbol{0}^{\mathsf{T}}\\\boldsymbol{0}&B^{(k+1)}-F_k\end{pmatrix} です。これを n×nn\times n に埋め込んで k=1,…,nk=1,\ldots,n について足すと A=∑klklkT−∑kFk=LLT−RA=\sum_k\boldsymbol{l}_k\boldsymbol{l}_k^{\mathsf{T}}-\sum_kF_k=LL^{\mathsf{T}}-R です。FkF_k の 0 でない成分は (i,j)∉S(i,j)\notin S の位置にあり、値は −(Sk)ij≥0-(S_k)_{ij}\ge0 です。LL は対角が正の下三角なので正則で、xTLLTx=∥LTx∥2>0\boldsymbol{x}^{\mathsf{T}}LL^{\mathsf{T}}\boldsymbol{x}=\|L^{\mathsf{T}}\boldsymbol{x}\|^2>0(x≠0\boldsymbol{x}\ne\boldsymbol{0})です。

SS を全成分にとれば何も捨てないので、これは Cholesky 分解そのものです。正定値でも Z 行列でない行列では、IC(0) が破綻する例が知られています(Saad の教科書 Ch. 10)。

例 6.5(2 次元 Laplace 方程式での IC(0) 前処理)

2 次元の離散 Laplace 行列(tridiag⁡(−1,2,−1)\operatorname{tridiag}(-1,2,-1) の Kronecker 和、Stieltjes 行列)について、前処理なしの共役勾配法と、自作の IC(0)(上の算法を行ごとに並べ替えたもの)を前処理にした共役勾配法の反復回数を、相対残差 10−810^{-8} まで比べます。参照解は spsolve です。

行ごとの版が上の算法と同じ LL を与えることは、成分ごとに見ると分かります。(i,j)∈S(i,j)\in S(i≥ji\ge j)の成分は、第 k<jk<j 段の Schur 補行列で (wk)i(wk)j/dk=likljk(\boldsymbol{w}_k)_i(\boldsymbol{w}_k)_j/d_k=l_{ik}l_{jk} を引かれるだけなので(捨てる操作は SS の外の成分にしか触れない)、第 jj 段の B(j)B^{(j)} では aij−∑k<jlikljka_{ij}-\sum_{k<j}l_{ik}l_{jk} になっています。これを dj=ljj\sqrt{d_j}=l_{jj} で割ったもの(対角では平方根をとったもの)が lijl_{ij} なので

ljj=(ajj−∑k<jljk2)1/2,lij=1ljj(aij−∑k<jlikljk)((i,j)∈S, i>j)l_{jj}=\Bigl(a_{jj}-\sum_{k<j}l_{jk}^2\Bigr)^{1/2},\qquad l_{ij}=\frac1{l_{jj}}\Bigl(a_{ij}-\sum_{k<j}l_{ik}l_{jk}\Bigr)\quad((i,j)\in S,\ i>j)

で、(i,j)∉S(i,j)\notin S では lij=0l_{ij}=0 です(定理 6.4 の証明の「分解の式」)。下のコードはこの式を ii の小さい順、各行の中で jj の小さい順に計算するもので、右辺に現れる ll はすべて計算済みです。

# Python 3.12.10 / NumPy 2.5.2 / SciPy 1.18.1
import numpy as np, scipy.sparse as sp, scipy.sparse.linalg as sla
def ic0(A): # 下三角部分の非零パターンだけで分解
T = sp.tril(A, format="csr"); n = A.shape[0]
L = [dict() for _ in range(n)] # L[i] = {列: 値}
for i in range(n):
lo, hi = T.indptr[i], T.indptr[i + 1]
for j, a in sorted(zip(T.indices[lo:hi], T.data[lo:hi])):
s = a - sum(v * L[j].get(k, 0.0)
for k, v in L[i].items() if k < j)
L[i][j] = np.sqrt(s) if j == i else s / L[j][j]
t = [(i, k, x) for i in range(n) for k, x in L[i].items()]
r, c, v = zip(*t)
return sp.csr_matrix((v, (r, c)), shape=(n, n))
T1 = lambda N: sp.diags([-1.0, 2.0, -1.0], [-1, 0, 1], shape=(N, N))
print(" N CG CG+IC(0) ratio err(IC)")
for N in (16, 32, 64, 128):
I = sp.eye(N); A = (sp.kron(I, T1(N)) + sp.kron(T1(N), I)).tocsr()
b = np.ones(N * N); xs = sla.spsolve(A.tocsc(), b) # 参照解
L = ic0(A); Lt = L.T.tocsr()
sol = lambda r: sla.spsolve_triangular(
Lt, sla.spsolve_triangular(L, r, lower=True), lower=False)
M = sla.LinearOperator(A.shape, matvec=sol); cnt = []
for kw in ({}, {"M": M}):
it = [0]; cb = lambda x: it.__setitem__(0, it[0] + 1)
x, _ = sla.cg(A, b, rtol=1e-8, callback=cb, **kw)
cnt.append(it[0])
e = np.linalg.norm(x - xs) / np.linalg.norm(xs)
print(f"{N:4d} {cnt[0]:4d} {cnt[1]:7d} {cnt[0] / cnt[1]:5.2f}"
f" {e:.1e}")
N CG CG+IC(0) ratio err(IC)
16 28 17 1.65 2.1e-10
32 59 29 2.03 2.5e-10
64 119 52 2.29 2.7e-10
128 239 100 2.39 1.0e-10

前処理なしの反復回数は NN を 2 倍にするとほぼ 2 倍(κ∝h−1\sqrt{\kappa}\propto h^{-1})で、IC(0) でも増え方は h−1h^{-1} に近いまま(比 1.7→1.8→1.91.7\to1.8\to1.9)、反復回数が 0.4〜0.6 倍になるだけです。IC(0) は条件数の次数 h−2h^{-2} を変えず、定数を改善する前処理だということが読み取れます。

検算. (a) 既知値: 定理 6.4 のとおり、どの格子でも平方根の中は正で分解は最後まで進みました。前処理つきの解は spsolve の参照解と相対 10−1010^{-10} の程度で一致します。(b) 別手法: 前処理の有無で同じ解に収束しています。(c) 次数: 前処理なしの反復回数の比 59/28,119/59,239/11959/28,119/59,239/119 は 2.1,2.0,2.02.1,2.0,2.0 で、共役勾配法の評価(反復回数 ∝κ\propto\sqrt{\kappa})と ノルムの章 の κ≈4/(π2h2)\kappa\approx4/(\pi^2h^2) から予測される h−1h^{-1} の増え方に一致します。

注意 6.6

修正不完全 Cholesky と格子に依らない前処理. 捨てる成分を対角に足し戻す修正不完全 Cholesky 分解(MIC)は、モデル問題で κ(M−1A)\kappa(M^{-1}A) を O(h−1)O(h^{-1}) に下げ、反復回数を h−1/2h^{-1/2} に比例させます(Gustafsson 1978。Saad の教科書 Ch. 10)。多重格子法と領域分割法は、適切に構成すれば反復回数が格子幅に依らない前処理(あるいは解法)になります(Trottenberg–Oosterlee–Schüller)。どちらも理論が長いので、この記事では証明しません。

反復法が行列に要求するのは行列ベクトル積だけです。格納形式と演算量は Cholesky 分解と疎行列の直接法 の 疎行列の格納形式(定義 6.1)[Cholesky 分解と帯行列・疎行列の直接法] と 疎行列ベクトル積の演算量(命題 6.2)[Cholesky 分解と帯行列・疎行列の直接法] で扱いました。反復法の観点でまとめると次のとおりです(nnz\mathrm{nnz} は非零の個数、kk は反復回数)。

形式・道具記憶行列ベクトル積反復法での使いどころ
COO(coo_array)3 nnz3\,\mathrm{nnz}2 nnz2\,\mathrm{nnz}組み立て。計算の前に CSR・CSC に変換する
CSR(csr_array)2 nnz+n+12\,\mathrm{nnz}+n+12 nnz2\,\mathrm{nnz}AxA\boldsymbol{x} の標準。行ごとの処理(IC・ILU の行版)
CSC(csc_array)2 nnz+n+12\,\mathrm{nnz}+n+12 nnz2\,\mathrm{nnz}splu・spilu・spsolve の入力
LinearOperator関数だけ関数の手間行列を作らない演算子、AM−1AM^{-1} の合成、前処理 M−1M^{-1}
GMRES(再始動なし)O(nk)O(nk)kk 回直交化 O(nk2)O(nk^2)。kk が大きいと再始動か前処理が要る
共役勾配法O(n)O(n)kk 回正定値。短い漸化式で直交化は不要

LinearOperator((n, n), matvec=f) は、ベクトルを受け取って AvA\boldsymbol{v} を返す関数 f だけで行列の代わりになります。上の 例 5.3 では AM−1AM^{-1} を、例 6.5 では (LLT)−1(LL^{\mathsf{T}})^{-1} をこの形で渡しました。Jacobian を作らずに差分で JvJ\boldsymbol{v} を近似する Newton–Krylov 法や、FFT で畳み込みを計算する演算子も同じ形で反復法に渡せます。時間の計測値は環境に依存するので、比べるときは反復回数と、1 反復の演算量(2 nnz2\,\mathrm{nnz} と前処理の適用の手間)を掛けて見積もるのがよいと思います。

演習 8.1易

AA が対角化可能で、相異なる固有値が 2 つ λ1,λ2\lambda_1,\lambda_2(ともに 0 でない)しかないとき、GMRES は高々 2 回で厳密解に達することを、残差多項式を具体的に与えて示せ。

解答

p(z)=(1−z/λ1)(1−z/λ2)p(z)=(1-z/\lambda_1)(1-z/\lambda_2) は P2\mathcal{P}_2 に属し p(0)=1p(0)=1、p(λ1)=p(λ2)=0p(\lambda_1)=p(\lambda_2)=0 です。系 4.3 から ∥r2∥≤κ(V)⋅0=0\|\boldsymbol{r}_2\|\le\kappa(V)\cdot0=0(d≥2d\ge2 のとき)。d=1d=1 なら 命題 3.3 により 1 回で厳密解です。

演習 8.2標準

AA を巡回置換行列(Aei=ei+1A\boldsymbol{e}_i=\boldsymbol{e}_{i+1}、Aen=e1A\boldsymbol{e}_n=\boldsymbol{e}_1)、b=e1\boldsymbol{b}=\boldsymbol{e}_1、x0=0\boldsymbol{x}_0=\boldsymbol{0} とする。k<nk<n では ∥rk∥=1\|\boldsymbol{r}_k\|=1、k=nk=n で rn=0\boldsymbol{r}_n=\boldsymbol{0} となることを示せ。AA は正規行列だが、定理 4.2 と矛盾しないことを説明せよ。

解答

Kk(A,e1)=span⁡{e1,…,ek}\mathcal{K}_k(A,\boldsymbol{e}_1)=\operatorname{span}\{\boldsymbol{e}_1,\ldots,\boldsymbol{e}_k\} で、AKk=span⁡{e2,…,ek+1}A\mathcal{K}_k=\operatorname{span}\{\boldsymbol{e}_2,\ldots,\boldsymbol{e}_{k+1}\} は k<nk<n では e1\boldsymbol{e}_1 に直交します。よって x∈Kk\boldsymbol{x}\in\mathcal{K}_k について ∥e1−Ax∥2=1+∥Ax∥2≥1\|\boldsymbol{e}_1-A\boldsymbol{x}\|^2=1+\|A\boldsymbol{x}\|^2\ge1 で、最小は x=0\boldsymbol{x}=\boldsymbol{0}、∥rk∥=1\|\boldsymbol{r}_k\|=1 です。k=nk=n では x=en\boldsymbol{x}=\boldsymbol{e}_n で Ax=e1A\boldsymbol{x}=\boldsymbol{e}_1 です。AA はユニタリ(正規)で、固有値は 1 の nn 乗根 ωj\omega^j 全部です。p(0)=1p(0)=1、deg⁡p≤k<n\deg p\le k<n の多項式について、1n∑jp(ωj)=p(0)=1\frac1n\sum_j p(\omega^j)=p(0)=1(ωj\omega^j の冪の平均は定数項だけを残す)なので max⁡j∣p(ωj)∣≥1\max_j|p(\omega^j)|\ge1 で、評価の右辺は 1 です。停滞は評価と矛盾しません。

演習 8.3標準

(1) A=(1−2−21)A=\begin{pmatrix}1&-2\\-2&1\end{pmatrix} は対称 Z 行列だが、Cholesky 分解(SS を全成分にとった IC)の第 2 段で d2<0d_2<0 となることを確かめ、定理 6.4 のどの仮定が欠けているか答えよ。(2) 同じ AA について 補題 6.3 の NN と ρ(N)\rho(N) を求めよ。

解答

(1) d1=1d_1=1、w1=(−2)\boldsymbol{w}_1=(-2) で、d2=1−(−2)2/1=−3<0d_2=1-(-2)^2/1=-3<0 です。AA の固有値は 1±21\pm2、すなわち 3,−13,-1 で、正定値でありません。Stieltjes 行列の仮定のうち正定値性が欠けています。(2) s=1s=1 とすると N=I−A=(0220)N=I-A=\begin{pmatrix}0&2\\2&0\end{pmatrix}、固有値 ±2\pm2 で ρ(N)=2>s=1\rho(N)=2>s=1 となり、補題のとおり正定値でないことと対応します。

  • Y. Saad, Iterative Methods for Sparse Linear Systems, 2nd ed., SIAM, 2003 — Ch. 6(Arnoldi・GMRES)、Ch. 9–10(前処理、不完全分解)。
  • A. Greenbaum, Iterative Methods for Solving Linear Systems, SIAM, 1997 — Ch. 2–3(GMRES・MINRES と非正規行列での収束)。
  • Y. Saad and M. H. Schultz, “GMRES: A generalized minimal residual algorithm for solving nonsymmetric linear systems”, SIAM J. Sci. Stat. Comput. 7 (1986), 856–869.
  • J. A. Meijerink and H. A. van der Vorst, “An iterative solution method for linear systems of which the coefficient matrix is a symmetric M-matrix”, Math. Comp. 31 (1977), 148–162.
  • A. Greenbaum, V. Pták, and Z. Strakoš, “Any nonincreasing convergence curve is possible for GMRES”, SIAM J. Matrix Anal. Appl. 17 (1996), 465–469.
  • U. Trottenberg, C. W. Oosterlee, and A. Schüller, Multigrid, Academic Press, 2001.

このテーマの 100 本ノック(100 問)

執筆: Claude Code(Opus 5.5)、Claude Code(Sonnet 5.5)・監査 2 回(Claude Code)・最終 2026-10-12

この記事の誤りを報告する ・運営: 夢現技研合同会社 ・料金 ・利用条件 ・特定商取引法に基づく表記

© 2026 夢現技研合同会社 ・コード例は MIT ライセンスです。