固有値問題は与えられた行列の固有値および固有ベクトルを求めること。つまり、 $ \newcommand{\C}{\mathbb{C}} \newcommand{\IC}{\mathbb{IC}} \newcommand{\bX}{\bar{X}} $
$$ Ax=\lambda x,\quad A\in \C^{n\times n} $$を満たす $\lambda\in \C$, $x\in \C^{n}$ ($x\neq 0$) を求める問題を指す。
Juliaで固有値と固有ベクトルを求める際には、LinearAlgebra
パッケージに含まれている関数eigen
・eigvals
・eigvecs
で求めることができる。
関数 | 役割 |
---|---|
eigen() | 固有値・固有ベクトル両方 |
eigvals() | 固有値 |
eigvecs() | 固有ベクトル |
これらは行列の構造・サイズをみて適宜、Lapackの関数を呼び出している(はず)。
using LinearAlgebra
val, vec = eigen([1 2; 2 1])
Eigen{Float64, Float64, Matrix{Float64}, Vector{Float64}} values: 2-element Vector{Float64}: -1.0 3.0 vectors: 2×2 Matrix{Float64}: -0.707107 0.707107 0.707107 0.707107
val#固有値
2-element Vector{Float64}: -1.0 3.0
vec#固有ベクトル
2×2 Matrix{Float64}: -0.707107 0.707107 0.707107 0.707107
eigvals([1 2; 2 1])#固有値
2-element Vector{Float64}: -1.0 3.0
eigvecs([1 2; 2 1])#固有ベクトル
2×2 Matrix{Float64}: -0.707107 0.707107 0.707107 0.707107
密行列とは、行列内のほとんどの要素が $0$ でない行列のことを指す。ここでは、行列$A\in\C^{n\times n}$ $(i=1,2,\cdots,n)$ の全ての固有値に対する精度保証アルゴリズムを考える。
(1) ある行列 $A$ の全ての近似固有ベクトル $\bX\in\C^{n\times n}$ $(i=1,2,\cdots,n)$ を求める。
(2) $A\cdot\bX$ の包含 $C\in\IC^{n\times n}$ を求める。
(3) 区間連立1次方程式 $\bX G=C$ の解集合の包含 $G\supset \bX^{-1}\cdot C$ ($G\in\IC^{n\times n}$) を求める。
(4) $G\in\IC^{n\times n}$ に対してゲルシュゴリンの定理を適用することを考える。
行列 $A\in\C^{n\times n}$ $(i=1,2,\cdots,n)$ が対角化可能であるとするとき、$\lambda_i$ に対する固有ベクトル$x^{(i)}\in\C^{n}$ $(i=1,2,\cdots,n)$ を並べた行列
$$ X :=[x^{(1)},x^{(2)},\cdots,x^{(n)}]\in\C^{n\times n} $$によって、$A$ は
$$ X^{-1}AX = D = \rm{diag}(\lambda_1,\lambda_2,\cdots,\lambda_n) $$と対角化される。
using LinearAlgebra
n =100
A = randn(n,n)
λ, X = eigen(A);
λ #固有値
100-element Vector{ComplexF64}: -10.46069513716218 + 0.0im -10.332427260060538 - 1.3305979043569918im -10.332427260060538 + 1.3305979043569918im -8.62172856410618 + 0.0im -7.850981125047944 - 2.2020443523923525im -7.850981125047944 + 2.2020443523923525im -7.788869903357844 - 6.293325383131132im -7.788869903357844 + 6.293325383131132im -7.65768280235933 - 2.8969142058184167im -7.65768280235933 + 2.8969142058184167im -7.08618406487871 - 0.8208438106964657im -7.08618406487871 + 0.8208438106964657im -6.365077848473712 - 3.308771679884842im ⋮ 6.130143112206561 + 0.8922298732860742im 6.405369233447701 - 3.861702343148692im 6.405369233447701 + 3.861702343148692im 7.139062239318452 - 0.3029004107117722im 7.139062239318452 + 0.3029004107117722im 7.34401301837314 + 0.0im 7.989276415707945 - 3.662113106471019im 7.989276415707945 + 3.662113106471019im 8.046015532849413 - 2.8919388886595594im 8.046015532849413 + 2.8919388886595594im 8.588037932894704 - 1.0129460347546775im 8.588037932894704 + 1.0129460347546775im
X #固有ベクトル
100×100 Matrix{ComplexF64}: -0.0568209+0.0im -0.0977007-0.0100893im … -0.104123-0.0221368im -0.0376451+0.0im -0.0579138+0.0304205im -0.0398469+0.074825im 0.115565+0.0im 0.0568705+0.0422121im -0.116692-0.0812045im -0.184645+0.0im -0.0787611-0.00834375im 0.0635811+0.0788448im -0.156785+0.0im -0.130529-0.139914im 0.0157195-0.0232663im -0.0855958+0.0im -0.0300735-0.0722441im … -0.0305959-0.0634585im -0.0231174+0.0im -0.0450641+0.00867388im -0.11317-0.0511771im -0.0343123+0.0im 0.0516888-0.0333989im 0.0317976-0.0922403im -0.0349386+0.0im -0.0149801-0.0201468im -0.0522548-0.0547025im -0.0885859+0.0im -0.135616+0.015468im -0.00985551+0.0163939im 0.0211869+0.0im -0.0728861+0.0561883im … 0.0202325-0.100563im -0.0407464+0.0im 0.0311553-0.00311445im -0.0887832-0.0140635im 0.129046+0.0im 0.129642-0.01966im 0.0067243+0.122537im ⋮ ⋱ -0.0461702+0.0im -0.137273+0.0388028im 0.0385836+0.0496754im -0.0333646+0.0im -0.0155301-0.0233653im -0.00712201+0.0611024im -0.0528894+0.0im -0.0164411-0.0180522im … 0.0410771+0.0898472im -0.152761+0.0im -0.0123299-0.0466732im -0.0593931+0.0922398im 0.0529475+0.0im -0.00123308+0.0205674im -0.101616-0.0879992im -0.0361844+0.0im -0.053093-0.0842534im -0.105886-0.0278448im 0.0331642+0.0im -0.0437578-0.0926606im 0.00505868-0.0395177im 0.0838054+0.0im -0.0017521+0.0383357im … -0.0385882+0.00547157im 0.0899211+0.0im -0.0890205+0.0358813im 0.101108-0.0109041im 0.0367361+0.0im 0.071071-0.03361im -0.0223052+0.0255699im -0.0308346+0.0im -0.0718371+0.0929974im 0.0188328+0.00968194im 0.113441+0.0im 0.0270254+0.102903im -0.00426948-0.0168021im
しかし、実際のところ上記の数値計算で得られる固有ベクトル $X$ は近似の値 $\bX\in \C^{n\times n}$ (以下、近似固有ベクトルという) である。しかし、近似固有ベクトルを並べた行列を使って、対角化したものについては、対角優位性が期待できる。この行列を $G$ とすると、
$$ G := \bX^{-1}A\bX $$となり、行列 $G$ の対角成分は行列 $A$ の固有値の近似となる。
また、対角優位性とは、ある行列$A=(a_{ij})$について、
$$ \left|a_{i i}\right|>\sum_{j \neq i}\left|a_{i j}\right| \quad(i=1,2, \ldots, n) $$であること。つまり、行列のどの対角成分の絶対値も、それと同じ列にある非対角成分の和よりも大きい時。
G = inv(X)*A*X #G
norm(diag(G) - λ,Inf) # Gの対角成分は固有値λにほぼ一致する
1.2636503647561583e-13
方法1
各演算を区間演算に変更した方式(参考:interval_dot-mul.ipynb)、行列のサイズが小さい場合はこちらの方が早い(たぶん)
using IntervalArithmetic, BenchmarkTools
iA = map(Interval, A)
iX = map(Interval, X)
@btime C1 = $iA * $iX;
64.853 ms (24 allocations: 313.59 KiB)
@time C1 = iA*iX
max(maximum(radius,real(C1)),maximum(radius,imag(C1)))
0.067534 seconds (63 allocations: 316.188 KiB, 2.76% compilation time)
4.6629367034256575e-15
方法2
BLASを使う。IntervalFunctions.jl
の呼び出し。大きな行列に対してはこの方が早い。
include("IntervalFunctions.jl"); # int_mulを使用する
@time C = int_mul(A,X) # A, X: complex matrices (not interval)
@time C = int_mul(A,X) # A, X: complex matrices (not interval)
@time C = int_mul(A,X); # A, X: complex matrices (not interval)
1.004640 seconds (4.47 M allocations: 239.614 MiB, 4.62% gc time, 83.49% compilation time) 0.059460 seconds (232.84 k allocations: 10.744 MiB, 17.99% gc time) 0.048215 seconds (232.84 k allocations: 10.744 MiB)
max(maximum(radius,real(C)),maximum(radius,imag(C)))
9.060807659722059e-14
real(C)
100×100 Matrix{Interval{Float64}}: [0.594385, 0.594386] [0.99606, 0.996061] … [-0.871793, -0.871792] [0.393793, 0.393794] [0.638867, 0.638868] [-0.418001, -0.418] [-1.2089, -1.20889] [-0.531443, -0.531442] [-0.9199, -0.919899] [1.93151, 1.93152] [0.802691, 0.802692] [0.466171, 0.466172] [1.64008, 1.64009] [1.1625, 1.16251] [0.158566, 0.158567] [0.895391, 0.895392] [0.214604, 0.214605] … [-0.198479, -0.198478] [0.241824, 0.241825] [0.477163, 0.477164] [-0.920071, -0.92007] [0.35893, 0.358931] [-0.578512, -0.578511] [0.366513, 0.366514] [0.365481, 0.365482] [0.127973, 0.127974] [-0.393356, -0.393355] [0.92667, 0.926671] [1.42182, 1.42183] [-0.101246, -0.101245] [-0.22163, -0.221629] [0.827854, 0.827855] … [0.275621, 0.275622] [0.426235, 0.426236] [-0.326054, -0.326053] [-0.748229, -0.748228] [-1.34991, -1.3499] [-1.36568, -1.36567] [-0.0663745, -0.0663744] ⋮ ⋱ [0.482971, 0.482972] [1.46999, 1.47] [0.281038, 0.281039] [0.349016, 0.349017] [0.129373, 0.129374] [-0.123058, -0.123057] [0.55326, 0.553261] [0.145855, 0.145856] … [0.26176, 0.261761] [1.59799, 1.598] [0.0652942, 0.0652943] [-0.603505, -0.603504] [-0.553868, -0.553867] [0.0401076, 0.0401077] [-0.783541, -0.78354] [0.378513, 0.378514] [0.436472, 0.436473] [-0.881146, -0.881145] [-0.346921, -0.34692] [0.32883, 0.328831] [0.0834734, 0.0834735] [-0.876663, -0.876662] [0.0691128, 0.0691129] … [-0.33694, -0.336939] [-0.940638, -0.940637] [0.967541, 0.967542] [0.879364, 0.879365] [-0.384285, -0.384284] [-0.779058, -0.779057] [-0.21746, -0.217459] [0.322551, 0.322552] [0.865994, 0.865995] [0.151929, 0.15193] [-1.18668, -1.18667] [-0.142316, -0.142315] [-0.0196469, -0.0196468]
imag(C)
100×100 Matrix{Interval{Float64}}: [-2.22508e-308, 2.22508e-308] … [-0.295584, -0.295583] [-2.22508e-308, 2.22508e-308] [0.602237, 0.602238] [-2.22508e-308, 2.22508e-308] [-0.81559, -0.815589] [-2.22508e-308, 2.22508e-308] [0.741526, 0.741527] [-2.22508e-308, 2.22508e-308] [-0.183889, -0.183888] [-2.22508e-308, 2.22508e-308] … [-0.575977, -0.575976] [-2.22508e-308, 2.22508e-308] [-0.554146, -0.554145] [-2.22508e-308, 2.22508e-308] [-0.759955, -0.759954] [-2.22508e-308, 2.22508e-308] [-0.522719, -0.522718] [-2.22508e-308, 2.22508e-308] [0.130808, 0.130809] [-2.22508e-308, 2.22508e-308] … [-0.843141, -0.84314] [-2.22508e-308, 2.22508e-308] [-0.210711, -0.21071] [-2.22508e-308, 2.22508e-308] [1.05916, 1.05917] ⋮ ⋱ [-2.22508e-308, 2.22508e-308] [0.465697, 0.465698] [-2.22508e-308, 2.22508e-308] [0.517535, 0.517536] [-2.22508e-308, 2.22508e-308] … [0.81322, 0.813221] [-2.22508e-308, 2.22508e-308] [0.731997, 0.731998] [-2.22508e-308, 2.22508e-308] [-0.858672, -0.858671] [-2.22508e-308, 2.22508e-308] [-0.346389, -0.346388] [-2.22508e-308, 2.22508e-308] [-0.334256, -0.334255] [-2.22508e-308, 2.22508e-308] … [0.0079023, 0.00790231] [-2.22508e-308, 2.22508e-308] [0.00877223, 0.00877224] [-2.22508e-308, 2.22508e-308] [0.197001, 0.197002] [-2.22508e-308, 2.22508e-308] [0.102225, 0.102226] [-2.22508e-308, 2.22508e-308] [-0.148622, -0.148621]
function verifylss_iB(A,iB) # verify the solution element-wisely
B = mid.(real(iB)) + mid.(imag(iB))*im
X̄ = A\B
n = size(X̄,2)
R = inv(A)
#########
#C_mid, C_rad = mm_ufp(R,A);
# G = Matrix{Float64}(I, n, n) - int_mul(R,A);
G = Matrix{Float64}(I, n, n) - R*A
α = opnorm(G,Inf)# Interval arithmetic
#########
if α < 1
η = (abs.(G)*ones(n))/(1-α)
Err = map(Interval,zeros(n,n))
X̄ = map(Interval,X̄)
r = A*X̄ - iB # Interval arithmetic
Rr = R*r
for i = 1:n
Err[:,i] = abs.(Rr[:,i]) + supremum(norm(Rr[:,i],Inf))*η # Interval arithmetic
end
return (real(X̄) .± supremum.(Err)) + im*(imag(X̄) .± supremum.(Err))
else
println("Oh my way, verification is failed...")
return nan
end
end
verifylss_iB (generic function with 1 method)
# G = similar(C);
G = verifylss_iB(X,C)
real(G)
100×100 Matrix{Interval{Float64}}: [-10.4607, -10.4606] … [-1.13461e-12, 1.17785e-12] [-9.88873e-13, 1.00836e-12] [-1.5919e-12, 1.56642e-12] [-9.88873e-13, 1.00836e-12] [-1.56634e-12, 1.59198e-12] [-1.39304e-12, 1.39242e-12] [-1.54798e-12, 1.57787e-12] [-1.69716e-12, 1.69819e-12] [-2.71283e-12, 2.68772e-12] [-1.69716e-12, 1.69819e-12] … [-2.70712e-12, 2.68946e-12] [-7.35403e-13, 7.50889e-13] [-1.14863e-12, 1.15266e-12] [-7.35403e-13, 7.50889e-13] [-1.15028e-12, 1.14662e-12] [-1.28977e-12, 1.29019e-12] [-2.07362e-12, 2.07174e-12] [-1.28977e-12, 1.29019e-12] [-2.06506e-12, 2.07905e-12] [-1.60959e-12, 1.6063e-12] … [-2.5257e-12, 2.52927e-12] [-1.60959e-12, 1.6063e-12] [-2.51816e-12, 2.52526e-12] [-1.31844e-12, 1.31912e-12] [-2.03848e-12, 2.05733e-12] ⋮ ⋱ [-5.46478e-12, 5.50305e-12] [-8.36794e-12, 8.36321e-12] [-1.35754e-12, 1.35122e-12] [-2.13123e-12, 2.12379e-12] [-1.35754e-12, 1.35122e-12] … [-2.12726e-12, 2.13869e-12] [-1.00611e-11, 1.02274e-11] [-1.63382e-11, 1.65113e-11] [-1.00611e-11, 1.02274e-11] [-1.63153e-11, 1.64148e-11] [-1.38197e-11, 1.41357e-11] [-1.63442e-11, 1.65995e-11] [-1.6986e-12, 1.69751e-12] [-2.71621e-12, 2.67001e-12] [-1.6986e-12, 1.69751e-12] … [-2.72601e-12, 2.68662e-12] [-1.5841e-12, 1.61816e-12] [-2.5468e-12, 2.50033e-12] [-1.5841e-12, 1.61816e-12] [-2.53897e-12, 2.51341e-12] [-1.48212e-12, 1.48723e-12] [-2.38538e-12, 2.32675e-12] [-1.48212e-12, 1.48723e-12] [8.58803, 8.58804]
real(diag(G))
100-element Vector{Interval{Float64}}: [-10.4607, -10.4606] [-10.3325, -10.3324] [-10.3325, -10.3324] [-8.62173, -8.62172] [-7.85099, -7.85098] [-7.85099, -7.85098] [-7.78887, -7.78886] [-7.78887, -7.78886] [-7.65769, -7.65768] [-7.65769, -7.65768] [-7.08619, -7.08618] [-7.08619, -7.08618] [-6.36508, -6.36507] ⋮ [6.13014, 6.13015] [6.40536, 6.40537] [6.40536, 6.40537] [7.13906, 7.13907] [7.13906, 7.13907] [7.34401, 7.34402] [7.98927, 7.98928] [7.98927, 7.98928] [8.04601, 8.04602] [8.04601, 8.04602] [8.58803, 8.58804] [8.58803, 8.58804]
real(λ)
100-element Vector{Float64}: -10.46069513716218 -10.332427260060538 -10.332427260060538 -8.62172856410618 -7.850981125047944 -7.850981125047944 -7.788869903357844 -7.788869903357844 -7.65768280235933 -7.65768280235933 -7.08618406487871 -7.08618406487871 -6.365077848473712 ⋮ 6.130143112206561 6.405369233447701 6.405369233447701 7.139062239318452 7.139062239318452 7.34401301837314 7.989276415707945 7.989276415707945 8.046015532849413 8.046015532849413 8.588037932894704 8.588037932894704
行列 $A=(A_{ij})\in \C^{n\times n}$ について、$A$ の全ての固有値 $\lambda_i$ は、$\bigcup_{1\le i \le n} U_i$ の内部に存在する。
$$ A\subseteq\bigcup_{1\le i \le n} U_i $$ただし、
$$ U_i = \left\{z\in\mathbb{C}:|z-a_{ii}|\le \sum_{j\neq i}|a_{ij}|\right\} $$である。円盤領域 $U_i$ をゲルシュゴリン円板といい、$A$ が強い優対角性を持つとき、$A$ の対角成分が $A$ の固有値の良い近似となる。今回の場合、$G=(g_{ij})_{1\le i,j\le n}\in\IC^{n\times n}$ の対角成分 $(g_{ii})_{1\le i\le n}$ を $(c_{i})_{1\le i\le n}\in \IC^{n}$ とし、各成分の半径を $\mathrm{rad}(c_i)$ とすると、
$$ \begin{array}{ll} \mbox{ゲルシュゴリン円の中心:}&\mathrm{mid}(c_i)\\ \mbox{ゲルシュゴリン円の半径:}&r_i=\sum_{j\neq i}\rm{mag}(g_{ij})+\rm{rad}(c_{i})\\ \end{array} $$となる。
import IntervalArithmetic: mag, radius, mid
function mag(v::Complex{Interval{T}}) where T# mag function for complex interval vectors
abs_v = abs(v)
return max(abs_v.lo,abs_v.hi)
end
function radius(v::Complex{Interval{T}}) where T# mag function for complex interval vectors
return sqrt(interval(radius(real(v)))^2 + interval(radius(imag(v)))^2)
end
function mid(v::Complex{Interval{T}}) where T# mag function for complex interval vectors
return mid(real(v)) + mid(imag(v))*im
end
mid (generic function with 8 methods)
r = zeros(n)
c = diag(G)
for i = 1:n
for j = 1:n
if i != j
r[i] += mag(G[i,j])
end
end
r[i] += mag(radius.(c[i]))
end
λc = mid.(c);
iλ = (real(λc) .± r) + im*(imag(λc) .± r)
[real(iλ) imag(iλ)]
100×2 Matrix{Interval{Float64}}: [-10.4607, -10.4606] [-1.71449e-10, 1.71449e-10] [-10.3325, -10.3324] [-1.3306, -1.33059] [-10.3325, -10.3324] [1.33059, 1.3306] [-8.62173, -8.62172] [-2.33222e-10, 2.33221e-10] [-7.85099, -7.85098] [-2.20205, -2.20204] [-7.85099, -7.85098] [2.20204, 2.20205] [-7.78887, -7.78886] [-6.29333, -6.29332] [-7.78887, -7.78886] [6.29332, 6.29333] [-7.65769, -7.65768] [-2.89692, -2.89691] [-7.65769, -7.65768] [2.89691, 2.89692] [-7.08619, -7.08618] [-0.820844, -0.820843] [-7.08619, -7.08618] [0.820843, 0.820844] [-6.36508, -6.36507] [-3.30878, -3.30877] ⋮ [6.13014, 6.13015] [0.892229, 0.89223] [6.40536, 6.40537] [-3.86171, -3.8617] [6.40536, 6.40537] [3.8617, 3.86171] [7.13906, 7.13907] [-0.302901, -0.3029] [7.13906, 7.13907] [0.3029, 0.302901] [7.34401, 7.34402] [-2.36508e-09, 2.36516e-09] [7.98927, 7.98928] [-3.66212, -3.66211] [7.98927, 7.98928] [3.66211, 3.66212] [8.04601, 8.04602] [-2.89194, -2.89193] [8.04601, 8.04602] [2.89193, 2.89194] [8.58803, 8.58804] [-1.01295, -1.01294] [8.58803, 8.58804] [1.01294, 1.01295]
sum(λ .∈ iλ)
100
r = sup.(radius.(iλ))
100-element Vector{Float64}: 2.4246643888301506e-10 3.2140609077396755e-10 3.2136291323261956e-10 3.298246148902417e-10 5.502712460511843e-10 5.503158366762941e-10 2.3875139945319826e-10 2.386936200507189e-10 4.203332203366035e-10 4.2026036804652065e-10 5.165151217395349e-10 5.164079629294386e-10 4.2197773517747653e-10 ⋮ 1.71083892237902e-9 4.375580766634832e-10 4.374324692667885e-10 3.3050292386232667e-9 3.3046422893368323e-9 3.344774730977129e-9 5.537612475676292e-10 5.53648200910604e-10 5.200287531490478e-10 5.197806785398173e-10 4.833008363378041e-10 4.833664662018629e-10
以上により、全固有値( $n=100$ )の精度保証がゲルシュゴリンの包含定理と区間演算によって成功した。
using Plots
plot(real(λ), imag(λ),
xlabel = "real part", #X軸のラベル
ylabel = "imag part", #Y軸のラベル
seriestype = :scatter, #点プロットに
title = "Distribution of eigenvalues", #タイトル
size = (400,300), #プロットのサイズ
legend = false, #凡例は今回は消す
)
using Plots
plot!(mid.(real(iλ)), mid.(imag(iλ)),
seriestype = :scatter, #点プロットに
legend = false, #凡例は今回は消す
)
TODO 標準・一般化固有値問題を対象に非線形方程式の精度保証法を利用することで、一部の固有値を精度保証する方法(verifyeig
)を今後、紹介したい。
本資料は以下のような文献・Web ページ等を参考にこの文章は書いています.
大石進一編著, 精度保証付き数値計算の基礎, コロナ社, 2018.
精度保証付き数値計算の教科書、3.4.1章にある「密行列に対する精度保証法」を実装した。
齊藤宣一, 計算数理演習, (最終閲覧日 2020年12月9日).
2019年度に行われた、計算数理演習(東京大学理学部数学科,教養学部統合自然科学科)の講義資料.ゲルシュゴリンの包含定理について、MATLABで実装した例が掲載されている.