ラグランジュ多項式と多くのノードの統合、丸め


10

一連の点して、を計算し 正確に。は、をノードとする点に関するラグランジュ多項式です。つまり、 これは次数多項式なので、十分な次数の古いガウス求積法を使用できます。これがあればうまく動作あまり大きくないが、大きなための丸め誤差により損なわれた結果につながる。 [ - 1 1 ] 1 - 1 L IX {xj}j=1n[1,1]L i x j x i L ix = j i x x j

11Li(x)dx
Lixjxinnn
Li(x)=jixxjxixj.
nnn

それらを回避する方法はありますか?


3
これはの場所に依存しますが、が適切に動作していることを確認しましたか?最悪の場合、が均一に分散されると、ルンゲ現象(振動的で大きくなる)が発生します。この場合、問題を引き起こす丸め誤差ではありません。L i x j L ixjLixjLi
キリル

2
また、nitpick:小さい数で除算することは条件の整った操作であり、条件が悪く、数値が不安定になる、ほぼ等しい数の大きな引き算です。
キリル

を計算しようとしているようです。ここで、はのVandermonde行列です。の条件数は何と言えますか?VのxjはV(2,0,23,0,25,0,)V1VxjV
キリル

回答:


5

任意のグリッドで定義された ラグランジュ多項式の は、次の2つのステップ:

11Lk(x)dx
Lkxk,k=0,,n

  1. のチェビシェフ極値グリッドでクレンショー-カーティスの求積法の重みをします where for、それ以外の場合、及びのためのまたはそうでなければ、。詳細については、Waldvogel(2006)の論文を参照してください。wkccykk=0,,n

    yk=cos(kπn)wkcc=ckn(1j=1n/2bj4j21cos(2πjkn))
    bk:=1k=n/2bk:=2ck:=1k=0k=nck:=2

  2. 重みを変換グリッドを介して任意のグリッドに変換し、求められる重み、 を取得します ここで、 wkccxk,k=0,,nMwk

    wk=jMkjwjcc
    Mjk = Lj(yk).

原則として、これは任意のグリッドに関数値を持つClenshaw-Curtis求積法ですが、基底変換によって得られます(Clenshaw-Curtisの一般的なリファレンスについては、たとえばTrefethenの論文を参照してください)。xk

アルゴリズムは、特に@Kirillの回答で提供さているVandermondeアプローチと比較すると、非常に安定しているようです。同じ考え方に従っていますが、既知の基準で直交重みを生成してから、新しいグリッドに変換します-これVandermonde行列による変換は通常、非常に悪条件であるため、予想されたはずです。


例:Legendre-Lobatto求積重みの生成

Legendere-Lobatto求積法の例を検討し、精度を単項式アプローチと比較します。参考として、さまざまなに対してGolub-Welschアルゴリズムで取得した直交重みを使用して、累積誤差 結果は次のとおりです 。Clenshaw-Curtis求積法の重みは、考慮されたグリッドポイントの範囲全体で完全に安定しており、マシンの精度(までのルジャンドル重みを再現します。)。wkLegn

ϵn=k=1n(wkwkLeg)2
ここに画像の説明を入力してくださいϵ1015


例:ニュートンコーツ求積式の生成

等間隔のグリッド上でのニュートン-コーツ求積法の生成を検討します。繰り返しになりますが、多項式補間の場合、等間隔のグリッドは基本的に悪いので、条件が悪いと予想されます。

次の図では、重みの合計を計算しました。 i|wi|/Nここに画像の説明を入力してください

たとえば、最大50グリッドポイントまで、単項式とクレンショウカーティスアプローチの結果は一致します。その後、Clenshaw-Curtisはより価値のあるものになります。直接的な解釈は、等間隔に配置されたグリッドは、たとえば、すべてを台無しにするということです。ただし、付近では、ヴァンデルモンド行列の条件が逆戻りし、さらに悪い結果になります。n>10n=50


例:Guass-Patterson求積法

この例は、@NicoSchlömerによるものです。私はこれまでこれらのルールを知りませんでしたので、この実装から横座標を取り、ヴァンダーモンドと変換されたクレンショウカーティスアプローチの両方を適用しました(上記のように、ヴァンダーモンドアプローチはビョークペレイラアルゴリズムを使用しています)。

コメントで示唆されているように、定数関数の積分誤差を計算 しました。次の結果:

ϵ=1n|2i=1nwi|,

ここに画像の説明を入力してください この図から、変換されたClenshaw-Curtisアプローチは、Vandermondeアプローチよりもはるかに効率的です(少なくとも有限精度の計算では)。それでも、Clenshaw-Curtisはインデックス7から分析を開始しているため、他の方法を使用する必要があります。


興味深い答えをありがとう。少し遊んでみましたが、四捨五入が重要であることがわかりました。たとえば、の合計は常に2である必要があります。これはn <5までは当てはまりますが、n == 6の場合はすでに1.9999949955991916になり、7桁の小数部にエラーがあります。wk
NicoSchlömer19年

これがGauss-Pattersonポイントであるgithub.com/nschloe/quadpy/blob/master/quadpy/line_segment/…について言及するのを忘れていました
NicoSchlömer19年

@NicoSchlömer:わかりました、それは興味深いです。なぜなら、ジュリアの実装が提供するように見える任意精度の算術を除いて、バンダーモンドのアプローチがどのようにしてより正確であるかを推論することは困難です(バンダーモンドは、悪条件の行列)。質問を編集して、ガウスパターソン求積法を検討します。
davidhigh

このすべてを調べてくれたDavidに感謝します。本当に面白いです!適切な次数の通常のガウス・レジェンドル求積法との比較を含めることは、この投稿を追加する価値があると思います。クレンショウ・カーティスのアプローチと同じように機能すると思います。また、githubなどにコードを配置し、ここからリンクすると、将来これを検討する人にとって役に立ちます。上位投票の回答をリンクした場合、興味深い洞察のため、これを「正しい」回答にします。
NicoSchlömer

@NicoSchlömer:ありがとう。Gauss-Legendreと比較してどういう意味ですか?(ガウス・レジェンドルの重みは機械の精度で再現されるため)。レッグの比較。CCはTrefethenによって行われたため、CCの精度はほぼ同等です。実際に興味深いのは、さまざまなカスタムグリッドのパフォーマンスを調査し、それをルジャンドルまたはクレンショーカーティスと比較することです。さらに、私はトップ投票の回答をリンクしました。
davidhigh

10

を評価しているため、Vandermondeシステムを解くためのBjörck-Pereyraアルゴリズムを使用してこれを評価できます。、そしてアルゴリズムは前方に安定していることが知られています(ニックハイアムによるヴァンダーモンドシステムを解くためのビョルクペレイラアルゴリズムのエラー分析http://www.maths.manchester.ac.uk/~higham/narep/narep108を参照)。 pdf)。、B = 2 0 2bV1b=(2,0,23,0,25,0,)

注:この分析は、(が完全に正であることと同じ)のプロパティ、およびの要素が交互の符号を持っている(これにより壊滅的なことがないことを保証する)ことに依存しているようです以下の減算でのキャンセル)。この場合、エラーは条件番号に依存せず、がなくても、より一般的なケースで機能しますが、エラーの範囲は異なります。いずれにしても、時間かかり、の評価/統合の問題を回避するため、それでも価値があるかもしれませんが、この答えを書き始めたとき、私はこの点に気づいていませんでした。マッピングできるかもしれません0x1<x2<<xnVb0x1O(n2)Lix12(x+1)それがあなたの問題にうまくいくなら。

これが実際に機能することを確認する小さなジュリアプログラムを作成しました。これにより、相対エラーが発生します。O(ϵmach)

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このテストのようにが正でない場合、相対誤差は通常の線形解法と同じ次数のようです。

なぜですか?bV1これは実際、すべてのタイプの多項式を処理するための非常に便利な共通のトリックですが、特にラグランジュ補間多項式を使用して、問題を行列形式に変換します。を定義する条件は、です。ましょうの係数であるすなわち、 およびは列ごとに配置された係数の行列全体です: の定義のためLiLi(xj)=δijαjkLk

Lk(x)=j,kαj,kxj=(1,x,x2,,xn)(α0k,,αnk),
L
L=(α00α0nαn0αnn).
Lk上記のベクトル積として、左側のにを 乗算すると、 条件、これは そう、のVandermonde行列であり、さん。L(1,x,,xn)
(1,x,x2,,xn)L=(L0(x),L1(x),,Ln(x)).
Lk(xj)=δjk
(1x0x02x0n1xnxn2xnn)L=I,
L=V1Vxj

最後に、、 したがって、、探している数値はで与えられます。ここで、はヴァンダーモンド行列の逆。11xkdx=1+(1)kk+1N+1つのk=0...N202

11Lk(x)dx=jαjk1+(1)kk+1=(2,0,23,0,25,0,)(α0k,,αnk).
n+1k=0nL=V-1(2,0,23,0,)LL=V1

精巧な答えをありがとう!さらに明確にするために、問題をヴァンダーモンドの形にする方法を詳しく教えてください。
NicoSchlömer2017年

@NicoSchlömer確かに、編集を参照してください。質問をありがとう、私はこのアルゴリズムが存在することさえ知りませんでした。
キリル

これを少し遊んでみました。私のコンピュータのメモリはでジュリアの有理数によって使い果たされており、まだすべて問題ありません。リファレンスソリューションがもう1つありますが、残念ながらBjörck-Pereyraでも失敗します。残念!それがそもそもそのような正確な結果を提供することは非常に奇妙です。いずれにせよ、貴重なご意見ありがとうございます。n = 31n=16n=31
NicoSchlömer2017年

@NicoSchlömerうーん、それを再現することはできません。上記のコードV.main(32)を使用すると、ラップトップで(わずかなメモリのみを使用しながら)約1秒で実用的な答えが得られます。数字はそれほど大きくなく、最大の分子は54桁なので、他の問題が発生しているのではないかと思います。どのように失敗するか知りたいので、要旨を投稿できますか?
Kirill

1
@NicoSchlömer出力の相対エラーを出力するときにBigFloatの使用を開始する方法を意味している場合、ルールが何かはよくわかりません。しかし、私はそれが以下のFloat64ために使用することを確認しましたd:で確認してください@show typeof(d)。さらに問題がある場合はお知らせください。
Kirill

2

まず、分母と分母の積を計算し、次に1で割ります。2つの積は同じ桁でなければならないため、重大な丸め誤差は発生しません。また、浮動小数点計算の数が減るため、速度が向上するという利点もあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.