文献に書いてあることを理解して要約すべきだと思うが… MATLAB 時代の良いことは試すことは簡単にできるということだ。
| compare.m |
1 function compare(n)
2 a=rand(n,n);
3 %% qr()
4 fprintf('MATLAB の qr()\n');
5 tic
6 [q0 r0]=qr(a);
7 toc
8 fprintf('||Q R-A||=%e\n\n', norm(q0*r0-a));
9 %%
10 fprintf('普通の Gram-Schmidt\n');
11 tic
12 [q1 r1]=GramSchmidt(a);
13 toc
14 fprintf('MATLABの関数の結果との差: %e %e\n', norm(q1-q0), norm(r1-r0));
15 fprintf('||Q R-A||=%e\n\n', norm(q1*r1-a));
16 %%
17 fprintf('修正 Gram-Schmidt\n');
18 tic
19 [q2 r2]=ModifiedGramSchmidt(a);
20 toc
21 fprintf('MATLABの関数の結果との差: %e %e\n', norm(q2-q0), norm(r2-r0));
22 fprintf('||Q R-A||=%e\n\n', norm(q2*r2-a));
23 %%
24 fprintf('Givens 変換による QR 分解\n');
25 tic
26 [q3 r3]=QR_Givens(a);
27 toc
28 fprintf('MATLABの関数の結果との差: %e %e\n', norm(q3-q0), norm(r3-r0));
29 fprintf('||Q R-A||=%e\n\n', norm(q3*r3-a));
30 %%
31 fprintf('Householde 変換による QR 分解\n');
32 tic
33 [q4 r4]=qrhouse(a);
34 toc
35 fprintf('MATLABの関数の結果との差: %e %e\n', norm(q4-q0), norm(r4-r0));
36 fprintf('||Q R-A||=%e\n\n', norm(q4*r4-a));
|
ここでは手抜きをして、 誤差と言うよりも残差を計算している。 そのうち誤差を計算できるようにしてみたいが、 分解の一意性がないのでこまったな…
| qr() | Gram-Schmidt | Gram-Schmidt | Givens | Householder | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
少なくともこの実験結果だけからは、 Gram-Schmidt の直交化法、修正 Gram-Schmidt の直交化法による結果は 他の方法による結果よりも精度が良さそうである。 MATLAB の qr() による結果はそれよりも悪い。 MATLAB の qr() による結果は Householder 法による結果に近い。
Gram-Schmidt の直交化法と 修正 Gram-Schmidt の直交化法による結果の差は少ない。 その二つの差よりも、 Givens 変換や Householder 変換を用いた方法との差の方がずっと大きい。 普通の Gram-Schmidt の直交化法ではうまく解けないような条件の悪い問題を作って、 それについて実験しないといけないのか? 考え込まされる結果である。