ruebenkoの回答と、user1091201とLeonidからのコメントを組み合わせて、正しい回答を提供します。
ruebenkoによる編集 1の回答は、このような一般的な状況に対する正しい最初の回答です。つまり、オプションを追加します。Method -> {"SymbolicPreprocessing", "OscillatorySelection" -> False}
expr = (Pi*
Cos[(Pi*(-2*x + y))/(1 + y)] + (1 + y)*(-Sin[(2*Pi*x)/(1 + y)] +
Sin[(Pi*(-2*x + y))/(1 + y)]))/(E^x*(1 + y));
NIntegrate[expr, {x, 0, 100}, {y, 0, 100},
Method -> {"SymbolicPreprocessing",
"OscillatorySelection" -> False}] // AbsoluteTiming
そして、user1091201のコメントは、この特定の問題Method -> "GaussKronrodRule"
に対する最速の回答に近いことを示唆しています。
この特定の例では、NIntegrate で何が起こっているかを説明し、その過程で、明らかに似たような状況を一般的に処理するためのヒントをいくつか紹介します。
方法の選択
この例では、NIntegrate は を調べexpr
、多次元の "LevinRule" がこの被積分関数に最適な方法であるという結論に達し、それを適用します。ただし、この特定の例では、"LevinRule" は "MultidimensionalRule" よりも低速です (ただし、"LevinRule" の方が満足のいくエラー推定値が得られます)。また、「LevinRule」は、 user1091201が見つけた「GaussKronrodRule」など、2 次元で反復されるいくつかのガウス型 1 次元ルールのいずれよりも低速です。
NIntegrate は、被積分関数の記号解析を実行した後に決定を下します。適用されるシンボリック前処理にはいくつかのタイプがあります。この設定 は、 Method -> {"SymbolicPreprocessing", "OscillatorySelection" -> False}
1 つのタイプのシンボリック前処理を無効にします。
基本的に、「OscillatorySelection」を有効にすると、NIntegrate は「LevinRule」を選択します。「OscillatorySelection」を無効にすると、NIntegrate はこの積分に対してより高速な「MultidimensionalRule」を選択しますが、異常に遅い収束が観察されたことを示すメッセージ NIntegrate::slwcon に基づく結果を信用できないかもしれません。
これが Mathematica 8 が Mathematica 7 と異なる部分です。Mathematica 8 は「LevinRule」と関連するメソッド選択ヒューリスティックを「OscillatorySelection」に追加します。
NIntegrate に別のメソッドを選択させるだけでなく、「OscillatorySelection」を無効にすると、実際のシンボリック処理に費やされる時間も節約されます。これは場合によっては重要です。
設定Method -> "GaussKronrodRule"
はメソッド選択に関連するシンボリック処理をオーバーライドしてスキップし、代わりに 2-D デカルト積規則 を使用しMethod -> {"CartesianRule", Method -> {"GaussKronrodRule", "GaussKronrodRule"}}
ます。これはたまたまこの積分の非常に高速な方法です。
その他のシンボリック処理
ruebenkoMethod -> {"SymbolicPreprocessing", "OscillatorySelection" -> False}
と user1091201はどちらも他の形式のMethod -> "GaussKronrodRule"
シンボリック処理を無効にしません。これは一般的には良いことです。適用できるシンボリック前処理のタイプのリストについては、NIntegrate の詳細ドキュメントのこの部分を参照してください。特に、"SymbolicPiecewiseSubdivision" は、区分関数が存在するためにいくつかの点で非解析的である被積分関数に対して非常に価値があります。
すべてのシンボリック処理を無効にし、既定のメソッド オプションを使用して既定のメソッドのみを取得するには、 を使用しますMethod -> {Automatic, "SymbolicProcessing" -> 0}
。1 次元積分の場合、これは現在Method -> {"GlobalAdaptive", Method -> "GaussKronrodRule"}
、これらのメソッドのすべてのパラメーターの特定のデフォルト設定 (ルール内の補間点の数、グローバル適応戦略の特異点処理のタイプなど) に相当します。多次元積分の場合、現在のところ、これもMethod -> {"GlobalAdaptive", Method -> "MultidimensionalRule"}
特定のデフォルト パラメータ値で になります。高次元の積分では、モンテカルロ法が使用されます。
NIntegrate の最初の最適化ステップとして直接切り替えることはお勧めしませんMethod -> {Automatic, "SymbolicProcessing" -> 0}
が、場合によっては便利です。
最速の方法
ヒューリスティックに選択された非常に多くのパラメーターがあり、調整することで恩恵を受ける可能性があるため、数値積分を少なくとも少し、場合によっては大幅に高速化する方法はほぼ常にあります。( 「LevinRule」メソッドまたは「GlobalAdaptive」戦略が持つさまざまなオプションとパラメーターを見てください。すべてのサブメソッドなども含まれます。)
とはいえ、この特定の積分に対して私が見つけた最速の方法は次のとおりです。
NIntegrate[(Pi*
Cos[(Pi*(-2*x + y))/(1 + y)] + (1 + y)*(-Sin[(2*Pi*x)/(1 + y)] +
Sin[(Pi*(-2*x + y))/(1 + y)]))/(E^x*(1 + y)), {x, 0,
100}, {y, 0, 100},
Method -> {"GlobalAdaptive", Method -> "GaussKronrodRule",
"SingularityDepth" -> Infinity}] // AbsoluteTiming
(この設定により、"SingularityDepth" -> Infinity
特異点処理の変換が無効になります。)
積分範囲
ところで、あなたの希望する積分範囲は本当にですか、{x, 0, 100}, {y, 0, 100}
それとも{x, 0, Infinity}, {y, 0, Infinity}
アプリケーションにとって本当に望ましい積分範囲ですか?
本当に必要な場合は{x, 0, Infinity}, {y, 0, Infinity}
、代わりにそれを使用することをお勧めします。無限長の積分範囲の場合、NIntegrate は被積分関数を有限範囲に圧縮し、幾何学的に間隔を空けた方法で効果的にサンプリングします。これは通常、有限の積分範囲に使用される線形 (等間隔) のサンプルよりもはるかに効率的です。