R中的发散积分在Wolfram中是可解的

时间:2014-09-07 18:46:33

标签: r integral integrate wolframalpha

我知道之前我曾问过同样的问题,但由于我在这里很新,所以这个问题被问得不好而且不可重复。所以我试着在这里做得更好。 (如果我只编辑旧的,可能没有人会读它)

我想要整合这个双积分:Here is a picture

enter image description here

ff<-function(g,t) exp((16)*g)*exp(-8*t-(-t-0.01458757)^2/(0.0001126501))

integrate(Vectorize(function(t) integrate(function(g) 
                                          ff(g,t), -2.5,0)$value), -2, 2)

在R中运行它会给出错误:

  the integral is probably divergent

当我尝试在Wolfram中运行sam函数时,它给了我一个合适的值:(我不得不切换g = x和t = y)

链接:

http://www.wolframalpha.com/input/?i=integration+[%2F%2Fmath%3Aexp%28%2816%29*x%29*exp%28-8*y-%28-y-0.01458757%29^2%2F%280.0001126501%29%29%2F%2F]+[%2F%2Fmath%3Adx+dy%2F%2F]+for+x+from+[%2F%2Fmath%3A-2.5%2F%2F]+to+[%2F%2Fmath%3A0%2F%2F]+for+y+from+[%2F%2Fmath%3A-2%2F%2F]+to+[%2F%2Fmath%3A2%2F%2F]

正如你所看到的那样得到了有限的结果,有人可以帮助我吗?

enter image description here

我在定义的区域上绘制了函数,但无法找到奇点问题。见:

library('Plot3D')
x <- seq(-2.5,0, by = 0.01) #to see the peak change to: seq(-0.2,0, by = 0.001)
y <- seq(-2,2, by = 0.01) #"": seq(-0.1,0.1, by = 0.001)
grid <- mesh(x,y) 
z <- with(grid,exp((16)*x)*
  exp(-8*y-(-0.013615734-y-0.001+0.5*0.007505^2*1)^2/(2*0.007505^2)))
persp3D(z = z, x = x, y = y)

感谢您的帮助,我希望问题的结构比旧的更好。

3 个答案:

答案 0 :(得分:2)

还值得注意的是,在integrate.c源文件中,错误消息的描述是

error messages
...
ier = 5 the integral is probably divergent, or
    slowly convergent. it must be noted that
    divergence can occur with any other value of ier.

所以尽管这个消息表明&#34;可能是分歧的&#34;你的代码似乎更容易慢慢收敛。

此外,您可以在收到此消息时继续运行,并在设置stop.on.error=FALSE

时解除错误
r <- integrate(Vectorize(function(t) 
    integrate(function(g) ff(g,t), -2.5,0)$value
), -2, 2, stop.on.error=FALSE); 
r$value

R并不声称自己是像Wolfhemat产品这样的数学解算器,如Mathematica。它没有做任何积分的象征性简化,而且这是Wolfram多年来一直在完善的东西。如果你只是想在数字上解决一堆双积分,像Mathematica或Maple这样的程序可能是更好的选择。这似乎并不是R花费其开发资源的地方。

答案 1 :(得分:2)

只有在y = 0附近的小范围内,您的被积函数才显着非零。来自?integrate

  

在无限间隔上进行积分时,请明确这样做,而不是仅使用大数字作为端点。这增加了正确答案的机会 - 任何在无限区间内积分有限的函数在该区间的大部分时间内必须接近于零。

虽然您没有严格地在无限区间内进行积分,但同样的数值问题也适用。事实上:

ff <- function(x, y)
exp(16*x - 8*y - (-y - 0.01458757)^2/0.0001126501)

f <- function(y)
integrate(ff, lower=-2.5, upper=0, y=y)$value

integrate(Vectorize(f), lower=-Inf, upper=Inf)
0.001323689 with absolute error < 4.4e-08

有趣的是,答案与Wolfram Alpha的答案不同。我不确定在这里信任谁;一方面我多次使用R integrate而且没有问题(我可以说);但是@MrFlick说R不是像Wolfram Alpha这样的专用数学解算器。

您还可以将rel.tol收敛参数设置为更严格的值,例如1e-7或1e-8。这在内积分中比在外积分中更重要,因为前者中的误差将传播到后者。在这种情况下,它对最终结果没有影响。

答案 2 :(得分:1)

对于双积分,最好使用cubature包。

library(cubature)
f <- function(x){
  exp(16*x[1] - 8*x[2] - (x[2] + 0.01458757)^2/0.0001126501)
}

hcubature函数给出的结果在减小公差时不稳定:

> hcubature(f, c(-2.5, -2), c(0,2))$integral
[1] 0.001285129
> hcubature(f, c(-2.5, -2), c(0,2), tol=1e-10)$integral
[1] 0.001293842

pcubature的结果相反,这是稳定的:

> pcubature(f, c(-2.5, -2), c(0,2))$integral
[1] 0.001323689
> pcubature(f, c(-2.5, -2), c(0,2), tol=1e-10)$integral
[1] 0.001323689
  

p自适应版本,pcubature,反复加倍的程度   正交规则直到达到收敛,并且基于a   Clenshaw-Curtis正交规则的张量积。这个算法是   通常优于h-自适应积分,以获得平滑的积分   几个(<= 3)尺寸,但是在更高尺寸或更高尺寸上是不好的选择   非光滑的被积函数。

接下来,RcppNumerical提供了强大的多重集成。

// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::depends(RcppNumerical)]]
#include <RcppNumerical.h>
#include <cmath>
using namespace Numer;

class ValegardIntegrand: public MFunc
{
public:    
  double operator()(Constvec& x)
  {
    return exp(16*x[0] - 8*x[1] - pow(-x[1] - 0.01458757,2)/0.0001126501);
  }
};    

// [[Rcpp::export]]
Rcpp::List Valegard()
{
  ValegardIntegrand f;  
  Eigen::VectorXd lower(2);
  lower << -2.5, -2;
  Eigen::VectorXd upper(2);
  upper << 0.0, 2.0;
  double err_est;
  int err_code;
  double res = integrate(f, lower, upper, err_est, err_code, 
                         10000000, 1e-14, 1e-14);
  return Rcpp::List::create(
    Rcpp::Named("approximate") = res,
    Rcpp::Named("error_estimate") = err_est,
    Rcpp::Named("error_code") = err_code
  );
}

它提供与pcubature相同的结果:

> Valegard()
$approximate
[1] 0.001323689

$error_estimate
[1] 9.893371e-14

$error_code
[1] 0

顺便说一下,与Mathematica 11的精确集成也提供了这个结果:

Integrate[E^(16 x - 8877.04 (0.0145876 + y)^2 - 8 y), {y, -2, 2}, {x, -2.5, 0}]
0.00132369