NIntegrate-在这种情况下,为什么在Mathematica 8中速度要慢得多? [英] NIntegrate - why is it much slower in Mathematica 8 in this given case?

查看:150
本文介绍了NIntegrate-在这种情况下,为什么在Mathematica 8中速度要慢得多?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Mathematica代码,必须在数值上计算与此相似的数千个积分

I have a Mathematica code where I have to evaluate numerically thousands of integrals similar to this one

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}
] //AbsoluteTiming

被积数是一个很好的绝对可积函数,没有奇点,它在一个方向上呈指数衰减,而在另一个方向上呈1/y ^ 3衰减.

The integrand is a nice absolutely integrable function without singularities, which decays exponentially in one direction and as 1/y^3 in the other direction.

NIntegrate命令在Mathematica 7中运行正常,但是在最新版本8.0.4中,它的速度降低了两个数量级.我认为在新版本中它会尝试更好地控制错误,但要以时间的巨大增加为代价.我可以使用一些设置来使计算以与Mathematica 7相同的速度进行吗?

The NIntegrate command was working fine in Mathematica 7, but in the newest version 8.0.4 it slows down by two orders of magnitude. I assume in the new version it tries to better control the error, but at the expense of this tremendous increase in time. Are there some settings I could use so that the computation proceeds with the same speed as in Mathematica 7?

推荐答案

ruebenko 的答案以及 user1091201 Leonid 的评论结合以给出正确的答案.

ruebenko's answer and the comments from user1091201 and Leonid together combine to give the right answers.

ruebenko Edit 1 答案是针对这种情况的正确的第一个答案,即添加选项Method -> {"SymbolicPreprocessing", "OscillatorySelection" -> False} :

The Edit 1 answer by ruebenko is the right first answer for general situations like this, that is, add the option 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"接近于此特定问题的最快答案.

And user1091201's comment suggesting Method -> "GaussKronrodRule" is close to the fastest possible answer for this specific problem.

在此特定示例中,我将描述NIntegrate中发生的情况,并在此过程中提供一些技巧,以解决一般情况下显然相似的情况.

I'll describe what is happening in NIntegrate in this specific example and along the way give some tips on handling apparently similar situations in general.

方法选择

在此示例中,NIntegrate检查了expr,得出的结论是,多维"LevinRule"是此被集成物的最佳方法,并将其应用.但是,对于此特定示例,"LevinRule"比"MultiDimensionRule"要慢(尽管"LevinRule"获得了更令人满意的误差估计). "LevinRule"也比在两个维度上迭代的多个高斯型一维规则中的任何一个慢,例如 user1091201 发现的"GaussKronrodRule".

In this example, NIntegrate examines expr, comes to the conclusion that multidimensional "LevinRule" is the best method for this integrand, and applies it. However, for this particular example, "LevinRule" is slower than "MultidimensionalRule" (though "LevinRule" gets a more satisfactory error estimate). "LevinRule" is also slower than any of several Gauss-type one-dimensional rules iterated over the two dimensions, such as "GaussKronrodRule" which user1091201 found.

NIntegrate在对被积数进行一些符号分析后做出决定.有几种类型的符号预处理:设置Method -> {"SymbolicPreprocessing", "OscillatorySelection" -> False}会禁用一种类型的符号预处理.

NIntegrate makes its decision after performing some symbolic analysis of the integrand. There are several types of symbolic pre-processing applied; the setting Method -> {"SymbolicPreprocessing", "OscillatorySelection" -> False} disables one type of symbolic pre-processing.

基本上,在启用"OscillatorySelection"的情况下,NIntegrate选择"LevinRule".在禁用"OscillatorySelection"的情况下,NIntegrate选择"MultiDimensionRule",此方法对于此积分速度更快,尽管我们可能基于消息NIntegrate :: slwcon表示观察到异常慢的收敛结果而对结果不信任.

Essentially, with "OscillatorySelection" enabled, NIntegrate selects "LevinRule". With "OscillatorySelection" disabled, NIntegrate selects "MultidimensionalRule", which is faster for this integral, although we may distrust the result based the message NIntegrate::slwcon which indicates unusually slow convergence was observed.

这是Mathematica 8与Mathematica 7的不同之处:Mathematica 8在"OscillatorySelection"中添加了"LevinRule"和相关的方法选择启发式.

This is the part where Mathematica 8 differs from Mathematica 7: Mathematica 8 adds "LevinRule" and associated method selection heuristics into "OscillatorySelection".

除了使NIntegrate选择其他方法之外,禁用"OscillatorySelection"还可以节省执行实际符号处理所花费的时间,这在某些情况下可能非常重要.

Aside from causing NIntegrate to select a different method, disabling "OscillatorySelection" also saves the time spent doing the actual symbolic processing, which can be significant in some cases.

设置Method -> "GaussKronrodRule"会覆盖并跳过与方法选择相关的符号处理,而是使用二维笛卡尔乘积规则Method -> {"CartesianRule", Method -> {"GaussKronrodRule", "GaussKronrodRule"}}.对于这种积分,这恰好是一种非常快速的方法.

Setting Method -> "GaussKronrodRule" overrides and skips the symbolic processing associated with method selection, and instead uses the 2-D cartesian product rule Method -> {"CartesianRule", Method -> {"GaussKronrodRule", "GaussKronrodRule"}}. This happens to be a very fast method for this integral.

其他符号处理

ruebenko Method -> {"SymbolicPreprocessing", "OscillatorySelection" -> False} user1091201 Method -> "GaussKronrodRule"都不会禁用其他形式的符号处理,这通常是一件好事.有关符号类型的列表,请参见 NIntegrate高级文档的这一部分.可能适用的预处理.尤其是,"SymbolicPiecewiseSubdivision"对于由于分段函数的存在而在多个点上非解析的被积分非常有价值.

Both ruebenko's Method -> {"SymbolicPreprocessing", "OscillatorySelection" -> False} and user1091201's Method -> "GaussKronrodRule" do not disable other forms of symbolic processing, and this is generally a good thing. See this part of the NIntegrate advanced documentation for a list of types of symbolic preprocessing that may be applied. In particular, "SymbolicPiecewiseSubdivision" is very valuable for integrands that are non-analytic at several points due to the presence of piecewise functions.

要禁用 all 符号处理并仅使用默认方法选项获取默认方法,请使用Method -> {Automatic, "SymbolicProcessing" -> 0}.对于一维积分,当前为这些方法的所有参数的某些默认设置(规则中插值点的数量,全局自适应策略的奇异处理类型等)为Method -> {"GlobalAdaptive", Method -> "GaussKronrodRule"}.对于多维积分,当前值为Method -> {"GlobalAdaptive", Method -> "MultidimensionalRule"},同样具有某些默认参数值.对于高维积分,将使用蒙特卡洛方法.

To disable all symbolic processing and get only default methods with default method options, use Method -> {Automatic, "SymbolicProcessing" -> 0}. For one-dimensional integrals this currently amounts to Method -> {"GlobalAdaptive", Method -> "GaussKronrodRule"} with certain default settings for all parameters of those methods (number of interpolation points in the rule, type of singularity handling for the global-adaptive strategy, etc). For multi-dimensional integrals, it currently amounts to Method -> {"GlobalAdaptive", Method -> "MultidimensionalRule"}, again with certain default parameter values. For high-dimensional integrals, a monte-carlo method will be used.

我不建议直接转换为Method -> {Automatic, "SymbolicProcessing" -> 0}作为NIntegrate的第一步优化,但是在某些情况下它可能会有用.

I don't recommend switching straight to Method -> {Automatic, "SymbolicProcessing" -> 0} as a first optimization step for NIntegrate, but it can be useful in some cases.

最快的方法

几乎总是有某种方式,至少有一点,有时很多,可以加快数值积分的速度,因为启发式选择了太多的参数,您可能会从调整中受益. (请查看"LevinRule"方法的不同选项和参数,或者"GlobalAdaptive"策略包括其所有子方法等. )

There is just about always some way to speed up a numerical integration at least a bit, sometimes a lot, since there are so many parameters that are chosen heuristically that you may benefit from tweaking. (Look at the different options and parameters that the "LevinRule" method or the "GlobalAdaptive" strategy has, including all their sub-methods etc.)

也就是说,这是我找到此特定积分最快的方法:

That said, here is the fastest method I found for this particular integral:

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禁用奇点处理转换.)

(The setting "SingularityDepth" -> Infinity disables singularity handling transformations.)

集成范围

顺便说一句,您想要的集成范围是{x, 0, 100}, {y, 0, 100}还是{x, 0, Infinity}, {y, 0, Infinity}您的应用程序真正的集成范围?

By the way, is your desired integration range really {x, 0, 100}, {y, 0, 100}, or is {x, 0, Infinity}, {y, 0, Infinity} the true desired integration range for your application?

如果您确实需要{x, 0, Infinity}, {y, 0, Infinity},建议您改用它.对于无限长的积分范围,NIntegrate将被积分体压缩为有限范围,并以几何间隔方式对其进行有效采样.通常,这要比用于有限积分范围的线性(均匀)间隔样本要高效得多.

If you really require {x, 0, Infinity}, {y, 0, Infinity}, I suggest using that instead. For infinite-length integration ranges, NIntegrate compactifies the integrand to a finite range, effectively samples it in a geometrically-spaced way. This is usually much more efficient than linear (evenly) spaced samples that are used for finite integration ranges.

这篇关于NIntegrate-在这种情况下,为什么在Mathematica 8中速度要慢得多?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆