一連の点して、を計算し 正確に。は、をノードとする点に関するラグランジュ多項式です。つまり、 これは次数多項式なので、十分な次数の古いガウス求積法を使用できます。これがあればうまく動作あまり大きくないが、大きなための丸め誤差により損なわれた結果につながる。 [ - 1 、1 ] ∫ 1 - 1 L I(X )L i x j x i L i(x )= ∏ j ≠ i x − x j
それらを回避する方法はありますか?
一連の点して、を計算し 正確に。は、をノードとする点に関するラグランジュ多項式です。つまり、 これは次数多項式なので、十分な次数の古いガウス求積法を使用できます。これがあればうまく動作あまり大きくないが、大きなための丸め誤差により損なわれた結果につながる。 [ - 1 、1 ] ∫ 1 - 1 L I(X )L i x j x i L i(x )= ∏ j ≠ i x − x j
それらを回避する方法はありますか?
回答:
任意のグリッドで定義された
ラグランジュ多項式の
は、次の2つのステップ:
のチェビシェフ極値グリッドでクレンショー-カーティスの求積法の重みをします
where for、それ以外の場合、及びのためのまたはそうでなければ、。詳細については、Waldvogel(2006)の論文を参照してください。
重みを変換グリッドを介して任意のグリッドに変換し、求められる重み、
を取得します
ここで、
原則として、これは任意のグリッドに関数値を持つClenshaw-Curtis求積法ですが、基底変換によって得られます(Clenshaw-Curtisの一般的なリファレンスについては、たとえばTrefethenの論文を参照してください)。
アルゴリズムは、特に@Kirillの回答で提供されているVandermondeアプローチと比較すると、非常に安定しているようです。同じ考え方に従っていますが、既知の基準で直交重みを生成してから、新しいグリッドに変換します-これVandermonde行列による変換は通常、非常に悪条件であるため、予想されたはずです。
例:Legendre-Lobatto求積重みの生成
Legendere-Lobatto求積法の例を検討し、精度を単項式アプローチと比較します。参考として、さまざまなに対してGolub-Welschアルゴリズムで取得した直交重みを使用して、累積誤差
結果は次のとおりです
。Clenshaw-Curtis求積法の重みは、考慮されたグリッドポイントの範囲全体で完全に安定しており、マシンの精度(までのルジャンドル重みを再現します。)。
例:ニュートンコーツ求積式の生成
等間隔のグリッド上でのニュートン-コーツ求積法の生成を検討します。繰り返しになりますが、多項式補間の場合、等間隔のグリッドは基本的に悪いので、条件が悪いと予想されます。
たとえば、最大50グリッドポイントまで、単項式とクレンショウカーティスアプローチの結果は一致します。その後、Clenshaw-Curtisはより価値のあるものになります。直接的な解釈は、等間隔に配置されたグリッドは、たとえば、すべてを台無しにするということです。ただし、付近では、ヴァンデルモンド行列の条件が逆戻りし、さらに悪い結果になります。
例:Guass-Patterson求積法
この例は、@NicoSchlömerによるものです。私はこれまでこれらのルールを知りませんでしたので、この実装から横座標を取り、ヴァンダーモンドと変換されたクレンショウカーティスアプローチの両方を適用しました(上記のように、ヴァンダーモンドアプローチはビョークペレイラアルゴリズムを使用しています)。
コメントで示唆されているように、定数関数の積分誤差を計算
しました。次の結果:
この図から、変換されたClenshaw-Curtisアプローチは、Vandermondeアプローチよりもはるかに効率的です(少なくとも有限精度の計算では)。それでも、Clenshaw-Curtisはインデックス7から分析を開始しているため、他の方法を使用する必要があります。
を評価しているため、Vandermondeシステムを解くためのBjörck-Pereyraアルゴリズムを使用してこれを評価できます。、そしてアルゴリズムは前方に安定していることが知られています(ニックハイアムによるヴァンダーモンドシステムを解くためのビョルクペレイラアルゴリズムのエラー分析、 http://www.maths.manchester.ac.uk/~higham/narep/narep108を参照)。 pdf)。、B = (2 、0 、2
注:この分析は、(が完全に正であることと同じ)のプロパティ、およびの要素が交互の符号を持っている(これにより壊滅的なことがないことを保証する)ことに依存しているようです以下の減算でのキャンセル)。この場合、エラーは条件番号に依存せず、がなくても、より一般的なケースで機能しますが、エラーの範囲は異なります。いずれにしても、時間かかり、の評価/統合の問題を回避するため、それでも価値があるかもしれませんが、この答えを書き始めたとき、私はこの点に気づいていませんでした。マッピングできるかもしれませんそれがあなたの問題にうまくいくなら。
これが実際に機能することを確認する小さなジュリアプログラムを作成しました。これにより、相対エラーが発生します。
module VandermondeInverse
using SpecialMatrices
function main(n=8)
X = Rational{BigInt}[k//(n-1) for k=0:n-1]
# X = convert(Vector{Rational{BigInt}}, linspace(-1, 1, n))
x = convert(Vector{Float64}, X)
A = convert(Matrix{Rational{BigInt}}, Vandermonde(X))
b = [i%2==0 ? 2//(i+1) : 0 for i=0:n-1]
println("Norm: ", norm(A, Inf))
println("Norm of inverse: ", norm(inv(A), Inf))
println("Condition number: ", cond(convert(Matrix{Float64}, A)))
ans = A'\b
println("True answer: ", ans)
B = convert(Matrix{Float64}, A)
c = convert(Vector{Float64}, b)
println("Linear solve: ", norm((B'\c - ans)./ans, Inf))
d = vec(c')
for k=1:n, l=n:-1:k+1
d[l] -= x[k]*d[l-1]
end
for k=n-1:-1:1, l=k:n
if l > k
d[l] /= x[l]-x[l-k]
end
if l < n
d[l] -= d[l+1]/(x[l+1] - x[l-k+1])
end
end
println("Neville elimination: ", norm((d-ans)./ans, Inf))
nothing
end
end
V = VandermondeInverse
出力:
julia> V.main(14)
Norm: 14.0
Norm of inverse: 1.4285962612120493e10
Condition number: 5.2214922998851654e10
True answer: Rational{Int64}[3202439130233//2916000,-688553801328731//52390800,19139253128382829//261954000,-196146528919726853//785862000,6800579086408939//11642400,-43149880138884259//43659000,32567483200938127//26195400,-7339312362348889//6237000,48767438804485271//58212000,-69618881108680969//157172400,44275410625421677//261954000,-2308743351566483//52390800,11057243346333379//1571724000,-209920276397//404250]
Linear solve: 1.5714609387747318e-8
Neville elimination: 1.3238218572356314e-15
X
このテストのようにが正でない場合、相対誤差は通常の線形解法と同じ次数のようです。
なぜですか?これは実際、すべてのタイプの多項式を処理するための非常に便利な共通のトリックですが、特にラグランジュ補間多項式を使用して、問題を行列形式に変換します。を定義する条件は、です。ましょうの係数であるすなわち、 およびは列ごとに配置された係数の行列全体です: の定義のため
最後に、、 したがって、、探している数値はで与えられます。ここで、はヴァンダーモンド行列の逆。N+1つのk=0...N(2、0、2
V.main(32)
を使用すると、ラップトップで(わずかなメモリのみを使用しながら)約1秒で実用的な答えが得られます。数字はそれほど大きくなく、最大の分子は54桁なので、他の問題が発生しているのではないかと思います。どのように失敗するか知りたいので、要旨を投稿できますか?
Float64
ために使用することを確認しましたd
:で確認してください@show typeof(d)
。さらに問題がある場合はお知らせください。