lsqr
に、係数行列 A
の代わりに A*x
および A'*x
を計算する関数ハンドルを与えて線形システムを解きます。
非対称の三重対角行列を作成します。行列をプレビューします。
A = 21×21
10 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 9 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 7 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 6 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 5 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 4 2 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 3 2 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 2 2 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 2 0 0 0 0 0 0 0 0 0 0
⋮
この三重対角行列は特殊な構造であるため、演算 A*x
を関数ハンドルで表すことができます。A
がベクトルを乗算する場合、結果のベクトルのほとんどの要素はゼロとなります。結果の非ゼロ要素は、A
の非ゼロの三重対角要素に対応します。
式 は次のようになります。
.
結果のベクトルは、3 つのベクトルの合計として記述できます。
=
同様に、 の式は次のようになります。
.
.
MATLAB® では、これらのベクトルを作成する関数を記述し、それらを合計して、フラグの入力に基づいて A*x
または A'*x
の値を与えるようにします。
function y = afun(x,flag)
if strcmp(flag,'notransp') % Compute A*x
y = [0; x(1:20)] ...
+ [(10:-1:0)'; (1:10)'].*x ...
+ 2*[x(2:end); 0];
elseif strcmp(flag,'transp') % Compute A'*x
y = 2*[0; x(1:20)] ...
+ [(10:-1:0)'; (1:10)'].*x ...
+ [x(2:end); 0];
end
end
(この関数は、ローカル関数として例の最後に保存されています)
ここで、lsqr
に A*x
および A'*x
を計算する関数ハンドルを与えて、線形システム を解きます。1e-6
の許容誤差と 25 回の反復を使用します。 の行の合計として を指定し、 の真の解が 1 のベクトルとなるようにします。
lsqr converged at iteration 21 to a solution with relative residual 5.4e-13.
x1 = 21×1
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
1.0000
⋮