ガウス・ラゲール求積の評価点と重み
この例では、Symbolic Math Toolbox™ を使って多項方程式と方程式系を解き、その結果を処理する方法を説明します。
ガウス求積法は、和による積分の近似 です。ここで、 および は方式のパラメーターで、 に依存しますが、 には依存しません。これらは、選択した重み関数 から次のように得られます。重み関数には直交多項式族が関連しています。多項式の根は評価点 です。最後に、重み は、低次数の多項式の場合にこの方式が正しくなるという条件で決まります。区間 での重み関数 を考えます。これはガウス・ラゲール求積として知られています。
syms t
n = 4;
w(t) = exp(-t);
直交多項式族の最初の メンバーがわかっているとします。ここで考慮されている求積法の場合、これらがラゲール多項式であることがわかります。
F = laguerreL(0:n-1, t)
F =
次多項式である L
を考えます。係数は未定です。
X = sym('X', [1, n+1])
X =
L = poly2sym(X, t)
L =
ラゲール多項式 F
および L
の直交関係を方程式系 sys
で表現します。
sys = [int(F.*L.*w(t), t, 0, inf) == 0]
sys =
多項式のノルムが 1 であるという条件を追加します。
sys = [sys, int(L^2.*w(t), 0, inf) == 1]
sys =
L
の係数の解を求めます。
S = solve(sys, X)
S = struct with fields:
X1: [2x1 sym]
X2: [2x1 sym]
X3: [2x1 sym]
X4: [2x1 sym]
X5: [2x1 sym]
solve
は 2 つの解を構造体配列で返します。解を表示します。
structfun(@display, S)
ans =
ans =
ans =
ans =
ans =
最初の係数は正であるという追加の条件を追加して、解を一意にします。
sys = [sys, X(1)>0]; S = solve(sys, X)
S = struct with fields:
X1: 1/24
X2: -2/3
X3: 3
X4: -4
X5: 1
解を L
に代入します。
L = subs(L, S)
L =
予想どおり、この多項式は |n| 次のラゲール多項式です。
laguerreL(n, t)
ans =
評価点 は多項式 L
の根です。この評価点について L
を解きます。根は、関数 root
で表現されます。
x = solve(L)
x =
これらの解の形式は、何も成立していないことを示している場合もありますが、これらについてのさまざまな演算は利用可能です。vpa
を使用して浮動小数点近似を計算します。
vpa(x)
ans =
疑似的な虚数部が発生する可能性があります。根が実数であることをシンボリックに証明します。
isAlways(in(x, 'real'))
ans = 4x1 logical array
1
1
1
1
4 次以下の多項式の場合、MaxDegree
を使用して、root
ではなく入れ子にされた累乗根で解が得られます。ただし、この形式の結果に対するそれ以降の演算は遅くなります。
xradical = solve(L, 'MaxDegree', 4)
xradical =
重み は、多項式が 次未満の場合、求積法により必ず厳密な結果を得られるという条件で与えられます。これがこれらの多項式のベクトル空間の基底に当てはまる場合には、これで十分です。この条件は、4 変数の 4 つの方程式から成る系になります。
y = sym('y', [n, 1]); sys = sym(zeros(n)); for k=0:n-1 sys(k+1) = sum(y.*(x.^k)) == int(t^k * w(t), t, 0, inf); end sys
sys =
数値的およびシンボリックに系を解きます。解は重み の目的のベクトルです。
[a1, a2, a3, a4] = vpasolve(sys, y)
a1 =
a2 =
a3 =
a4 =
[alpha1, alpha2, alpha3, alpha4] = solve(sys, y)
alpha1 =
alpha2 =
alpha3 =
alpha4 =
また、出力引数を 1 つだけ指定することで、解を構造体として得ることもできます。
S = solve(sys, y)
S = struct with fields:
y1: -(root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 2)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 3) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 2)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 4) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 3)*root(...
y2: (root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 1)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 3) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 1)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 4) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 3)*root(z...
y3: (root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 1)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 2) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 1)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 4) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 2)*root(z...
y4: -(root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 1)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 2) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 1)*root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 3) + root(z^4 - 16*z^3 + 72*z^2 - 96*z + 24, z, 2)*root(...
structfun(@double, S)
ans = 4×1
0.6032
0.3574
0.0389
0.0005
構造体 S
をシンボリック配列に変換します。
Scell = struct2cell(S); alpha = transpose([Scell{:}])
alpha =
シンボリックな解は複雑に見えます。これを単純化し、浮動小数点ベクトルに変換します。
alpha = simplify(alpha)
alpha =
vpa(alpha)
ans =
alpha
に現れる根 x
を略語に置き換えて、可読性を高めます。
subs(alpha, x, sym('R', [4, 1]))
ans =
重みを合計して和が 1 であることを示します。
simplify(sum(alpha))
ans =
求積法の重みを求める別の方法は、式 を使用して計算することです。 でこれを行います。これは、次のように別の方法と同じ結果となります。
int(w(t) * prod((t - x(2:4)) ./ (x(1) - x(2:4))), t, 0, inf)
ans =
求積法では、 次以下のすべての多項式に対しても厳密な結果が得られますが、 に対しては得られません。
simplify(sum(alpha.*(x.^(2*n-1))) -int(t^(2*n-1)*w(t), t, 0, inf))
ans =
simplify(sum(alpha.*(x.^(2*n))) -int(t^(2*n)*w(t), t, 0, inf))
ans =
余弦に求積法を適用し、厳密な結果と比較します。
vpa(sum(alpha.*(cos(x))))
ans =
int(cos(t)*w(t), t, 0, inf)
ans =
余弦のべき乗では、奇数乗と偶数乗の間で誤差が振動します。
errors = zeros(1, 20); for k=1:20 errors(k) = double(sum(alpha.*(cos(x).^k)) -int(cos(t)^k*w(t), t, 0, inf)); end plot(real(errors))