ruebenko的回答和评论用户1091201 and Leonid结合起来给出正确的答案。
The Edit 1回答者ruebenko是正确的第一个答案general像这样的情况,即添加选项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 用户1091201的评论建议Method -> "GaussKronrodRule"
接近最快的答案这个具体的问题。
我将在这个特定示例中描述 NIntegrate 中发生的情况,并在此过程中提供一些有关处理一般情况下明显相似情况的提示。
方法选择
在此示例中,NIntegrate 检查expr
,得出多维“LevinRule”是该被积函数的最佳方法的结论,并应用它。然而,对于这个特定的示例,“LevinRule”比“MultiDimensionalRule”慢(尽管“LevinRule”获得了更令人满意的误差估计)。 “LevinRule”也比任何在二维上迭代的高斯型一维规则慢,例如“GaussKronrodRule”用户1091201 found.
NIntegrate 在对被积函数执行一些符号分析后做出决定。应用了多种类型的符号预处理;那个设定Method -> {"SymbolicPreprocessing", "OscillatorySelection" -> False}
禁用一种类型的符号预处理。
本质上,启用“OscillatorySelection”后,NIntegrate 选择“LevinRule”。禁用“OscillatorySelection”后,NIntegrate 选择“MultiDimensionalRule”,对于该积分来说速度更快,尽管我们可能不信任基于消息 NIntegrate::slwcon 的结果,该消息表明观察到异常缓慢的收敛。
这是 Mathematica 8 与 Mathematica 7 不同的部分:Mathematica 8 在“OscillatorySelection”中添加了“LevinRule”和相关的方法选择启发式。
除了使 NIntegrate 选择不同的方法之外,禁用“OscillatorySelection”还可以节省实际符号处理所花费的时间,这在某些情况下可能很重要。
Setting Method -> "GaussKronrodRule"
覆盖并跳过与方法选择相关的符号处理,而是使用二维笛卡尔积规则Method -> {"CartesianRule", Method -> {"GaussKronrodRule", "GaussKronrodRule"}}
。对于这个积分来说,这恰好是一种非常快速的方法。
其他符号处理
Both ruebenko's Method -> {"SymbolicPreprocessing", "OscillatorySelection" -> False}
and 用户1091201's Method -> "GaussKronrodRule"
不要禁用其他形式的符号处理,这通常是一件好事。看NIntegrate 高级文档的这一部分 http://reference.wolfram.com/mathematica/tutorial/NIntegrateIntroduction.html#118305364有关可应用的符号预处理类型的列表。特别是,“SymbolicPiecewiseSubdivision”对于由于分段函数的存在而在多个点上不可解析的被积函数非常有价值。
禁用all符号处理并仅获取具有默认方法选项的默认方法,请使用Method -> {Automatic, "SymbolicProcessing" -> 0}
。对于一维积分,目前相当于Method -> {"GlobalAdaptive", Method -> "GaussKronrodRule"}
这些方法的所有参数都有某些默认设置(规则中的插值点数量、全局自适应策略的奇点处理类型等)。对于多维积分,目前相当于Method -> {"GlobalAdaptive", Method -> "MultidimensionalRule"}
,再次使用某些默认参数值。对于高维积分,将使用蒙特卡罗方法。
我不建议直接切换到Method -> {Automatic, "SymbolicProcessing" -> 0}
作为 NIntegrate 的第一个优化步骤,但它在某些情况下可能很有用。
最快的方法
大约有always某种方法可以至少稍微加快数值积分的速度,有时甚至加快很多,因为有很多参数是启发式选择的,您可能会从调整中受益。 (看看不同的选项和参数“莱文规则”法 http://reference.wolfram.com/mathematica/tutorial/NIntegrateIntegrationRules.html#32844337 or the “全球适应性”战略 http://reference.wolfram.com/mathematica/tutorial/NIntegrateIntegrationStrategies.html#137878679有,包括它们的所有子方法等)
也就是说,这是我为这个特定积分找到的最快方法:
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}
, or is {x, 0, Infinity}, {y, 0, Infinity}
您的应用真正所需的集成范围?
如果你确实需要{x, 0, Infinity}, {y, 0, Infinity}
,我建议改用它。对于无限长度的积分范围,NIntegrate 将被积函数压缩到有限范围,以几何间隔的方式有效地对其进行采样。这通常比用于有限积分范围的线性(均匀)间隔样本要高效得多。