Ответ 1
ruebenko и комментарии от user1091201 и Leonid вместе, чтобы дать правильные ответы.
Ответ Редактировать 1 ruebenko - это правильный первый ответ для общих ситуаций, подобных этому, то есть добавьте опцию 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" работает медленнее, чем "Многомерное правило" (хотя "LevinRule" получает более удовлетворительную оценку ошибки). "LevinRule" также медленнее любого из нескольких одномерных правил Гаусса, которые повторяются в двух измерениях, таких как "GaussKronrodRule", который был найден user1091201.
NIntegrate принимает свое решение после выполнения некоторого символического анализа подынтегрального выражения. Существует несколько типов символической предварительной обработки; параметр Method -> {"SymbolicPreprocessing", "OscillatorySelection" -> False}
отключает один тип символической предварительной обработки.
По существу, с включенным "Осцилляционным выбором", NIntegrate выбирает "LevinRule" . При отключенном "OscillatorySelection" NIntegrate выбирает "MultidimensionalRule", который быстрее для этого интеграла, хотя мы можем не доверять результату на основе сообщения NIntegrate:: slwcon, которое указывает на необычно медленную конвергенцию.
Это та часть, где Mathematica 8 отличается от Mathematica 7: Mathematica 8 добавляет "LevinRule" и связанные с ней методы выбора эвристики в "Осцилляторный выбор".
Помимо того, что NIntegrate выбирает другой метод, отключение "OscillatorySelection" также экономит время, затрачиваемое на фактическую символическую обработку, что может быть значительным в некоторых случаях.
Настройка Method -> "GaussKronrodRule"
переопределяет и пропускает символическую обработку, связанную с выбором метода, и вместо этого использует двумерное декартово правило продукта Method -> {"CartesianRule", Method -> {"GaussKronrodRule", "GaussKronrodRule"}}
. Это очень быстрый метод для этого интеграла.
Другая символьная обработка
Оба ruebenko Method -> {"SymbolicPreprocessing", "OscillatorySelection" -> False}
и user1091201 Method -> "GaussKronrodRule"
не отключают другие формы символической обработки, и это вообще хорошо. См. эту часть расширенной документации NIntegrate для списка типов символической предварительной обработки, которые могут быть применены. В частности, "SymbolicPiecewiseSubdivision" очень ценно для подынтегральных функций, которые неаналитичны в нескольких точках из-за наличия кусочных функций.
Чтобы отключить всю символическую обработку и получить только методы по умолчанию с опциями метода по умолчанию, используйте Method -> {Automatic, "SymbolicProcessing" -> 0}
. Для одномерных интегралов это в настоящее время составляет Method -> {"GlobalAdaptive", Method -> "GaussKronrodRule"}
с определенными настройками по умолчанию для всех параметров этих методов (количество точек интерполяции в правиле, тип обработки сингулярностей для глобальной адаптивной стратегии и т.д.). Для многомерных интегралов он в настоящее время равен Method -> {"GlobalAdaptive", Method -> "MultidimensionalRule"}
, снова с определенными значениями параметров по умолчанию. Для высокоразмерных интегралов будет использоваться метод monte-carlo.
Я не рекомендую переключаться прямо на Method -> {Automatic, "SymbolicProcessing" -> 0}
в качестве первого шага оптимизации для NIntegrate, но в некоторых случаях это может быть полезно.
Самый быстрый метод
Существует примерно всегда, чтобы ускорить численное интегрирование, по крайней мере, немного, иногда много, так как существует так много параметров, которые выбраны эвристически, что вы можете извлечь выгоду из настройки. (Посмотрите на различные параметры и параметры, которые "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 компактифицирует подынтегральное выражение в конечном диапазоне, эффективно сэмплирует его геометрически разнесенным способом. Обычно это намного эффективнее линейных (равномерно) интервальных выборок, которые используются для конечных диапазонов интеграции.