Double integral in RcppNumerical

烂漫一生 提交于 2019-12-11 17:45:24

问题


I have to calculate the double integral of the function:

 > DIntegral <- function(x,y){res <- pnorm(x,1,0.1) * dexp(y-2,1.2)
                              return(res)
                              }

The upper limit for x and y are: 10 and Infinity respectively. The lower limit for x and y are: 1 and 2 respectively.

How can I do this double integration in RcppNumerical?

For one dimensional integration my C++ file looks like:

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



class PDF: public Func
 {
 private:

  double beta;
  double M0;

public:
  PDF( double beta_, double M0_): beta(beta_), M0(M0_) {};

  double operator()(const double& x) const
  { 
    return  R::dexp(x-M0,beta,0);

  }
};

// [[Rcpp::export]]
double integrate_test2( double beta, double M0, double upper, double      lower)
{

  PDF f( beta, M0);
  double err_est;
  int err_code;
  double res = integrate ( f, lower, upper,err_est,err_code);
  return(res);

}

Code for 2 dimensional integration with finite limits

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



class PDF: public MFunc
{
private:
  double mu;
  double sigma;
  double beta;
  double M0;

 public:
  PDF( double mu_, double sigma_, double beta_, double M0_): mu(mu_),     sigma(sigma_), beta(beta_), M0(M0_) {};

  double operator()(Constvec& x)
  { 
    return  R::pnorm(x[0],mu,sigma,1,0) * R::dexp(x[1]-M0,beta,0);

  }
};

// [[Rcpp::export]]
double integrate_test2( double mu, double sigma, double beta, double M0)
{
  Eigen::VectorXd lower(2);
  lower << 1, 2;
  Eigen::VectorXd upper(2);
  upper << 10, 50;

  PDF f( mu, sigma, beta, M0);
  double err_est;
  int err_code;
  double err_est2;
  int err_code2;
  double res = integrate ( f, lower, upper,err_est,err_code);
  return(res);

}

回答1:


I have updated your code to take the integration limits as arguments and to return the error code and estimate:

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

class PDF: public MFunc
{
private:
  double mu;
  double sigma;
  double beta;
  double M0;

public:
  PDF( double mu_, double sigma_, double beta_, double M0_): mu(mu_),     sigma(sigma_), beta(beta_), M0(M0_) {};

  double operator()(Constvec& x)
  { 
    return  R::pnorm(x[0],mu,sigma,1,0) * R::dexp(x[1]-M0,beta,0);

  }
};

// [[Rcpp::export]]
Rcpp::List integrate_test2( double mu, double sigma, double beta, double M0, Eigen::VectorXd lower, Eigen::VectorXd upper)
{
  PDF f( mu, sigma, beta, M0);
  double err_est;
  int err_code;
  double res = integrate ( f, lower, upper,err_est,err_code);
  return Rcpp::List::create(
    Rcpp::Named("result") = res,
    Rcpp::Named("error_estimate") = err_est,
    Rcpp::Named("error_code") = err_code
  );
}
/*** R
integrate_test2(1, 0.1, 1.2, 2, c(1, 2), c(10, 50))
integrate_test2(1, 0.1, 1.2, 2, c(1, 2), c(10, 1e4))
integrate_test2(1, 0.1, 1.2, 2, c(1, 2), c(10, 1e6))
integrate_test2(1, 0.1, 1.2, 2, c(1, 2), c(10, 1e8))
*/

Result:

> Rcpp::sourceCpp('2d_int.cpp')

> integrate_test2(1, 0.1, 1.2, 2, c(1, 2), c(10, 50))
$result
[1] 8.950068

$error_estimate
[1] 0.3570577

$error_code
[1] 1


> integrate_test2(1, 0.1, 1.2, 2, c(1, 2), c(10, 1e4))
$result
[1] 4.787999

$error_estimate
[1] 16.12484

$error_code
[1] 1


> integrate_test2(1, 0.1, 1.2, 2, c(1, 2), c(10, 1e6))
$result
[1] 1.605216e-314

$error_estimate
[1] 4.320299e-313

$error_code
[1] 0


> integrate_test2(1, 0.1, 1.2, 2, c(1, 2), c(10, 1e8))
$result
[1] 0

$error_estimate
[1] 0

$error_code
[1] 0

So for small values the upper limit of y, the integration does not converge. And when it does converge, the result is (nearly) zero. This does not change when one increases the upper limit up to about 1e307, i.e. almost .Machine$double.xmax. After that I get NaN.

However, if I use the cubature package the result is quite different:

library(cubature)
DIntegral <- function(x){
  res <- pnorm(x[1],1,0.1) * dexp(x[2]-2,1.2)
  return(res)
}
cubintegrate(f = DIntegral, lower = c(1, 2), upper = c(10, 50), method = "hcubature")
#> $integral
#> [1] 8.961023
#> 
#> $error
#> [1] 4.888071e-05
#> 
#> $neval
#> [1] 983
#> 
#> $returnCode
#> [1] 0
cubintegrate(f = DIntegral, lower = c(1, 2), upper = c(10, 1000), method = "hcubature")
#> $integral
#> [1] 8.960415
#> 
#> $error
#> [1] 7.145898e-05
#> 
#> $neval
#> [1] 1701611595
#> 
#> $returnCode
#> [1] 0
cubintegrate(f = DIntegral, lower = c(1, 2), upper = c(10, Inf), method = "hcubature")
#> $integral
#> [1] 8.960105
#> 
#> $error
#> [1] 8.515124e-05
#> 
#> $neval
#> [1] 1706522167
#> 
#> $returnCode
#> [1] 0

I am not sure what is going on here.



来源:https://stackoverflow.com/questions/53648355/double-integral-in-rcppnumerical

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!