ruebenko ответ и комментарии user1091201 и Leonid вместе объединяются, чтобы дать правильные ответы.
Ответ Edit 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
Комментарий
And user1091201 о том, что Method -> "GaussKronrodRule"
близок к самому быстрому решению для этой конкретной проблемы .
Я опишу, что происходит в NIntegrate, в этом конкретном примере и покажу несколько советов по работе с внешне похожими ситуациями в целом.
Выбор метода
В этом примере NIntegrate исследует expr
, приходит к выводу, что многомерный метод «LevinRule» является лучшим методом для этого подынтегрального выражения, и применяет его. Однако для этого конкретного примера «LevinRule» медленнее, чем «MultidimensionalRule» (хотя «LevinRule» получает более удовлетворительную оценку ошибки). «LevinRule» также медленнее, чем любое из нескольких одномерных правил типа Гаусса, повторяемых в двух измерениях, таких как «GaussKronrodRule», которое user1091201 найдено.
NIntegrate принимает решение после некоторого символического анализа подынтегрального выражения. Существует несколько типов символической предварительной обработки; настройка Method -> {"SymbolicPreprocessing", "OscillatorySelection" -> False}
отключает один тип символьной предварительной обработки.
По сути, с включенным «OscillatorySelection» NIntegrate выбирает «LevinRule». При отключенном «OscillatorySelection» NIntegrate выбирает «MultidimensionalRule», что является более быстрым для этого интеграла, хотя мы можем не доверять результату на основе сообщения NIntegrate :: slwcon, которое указывает на необычно медленную конвергенцию.
Это та часть, в которой Mathematica 8 отличается от Mathematica 7: Mathematica 8 добавляет «LevinRule» и связанные с ним эвристики выбора метода в «OscillatorySelection».
Помимо того, что 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"}
, опять же с определенными значениями параметров по умолчанию. Для многомерных интегралов будет использоваться метод Монте-Карло.
Я не рекомендую переходить прямо к 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 уплотняет подынтегральное выражение до конечного диапазона, эффективно отбирая его геометрически разнесенным способом. Это обычно намного эффективнее, чем линейные (равномерно) разнесенные выборки, которые используются для конечных диапазонов интегрирования.