Rcpp中的双积分

时间:2018-12-06 09:36:40

标签: r rcpp numerical-integration

我必须计算函数的双积分:

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

x和y的上限分别为:10Infinity。 x和y的下限分别是:12

如何在RcppNumerical中进行这种双重集成?

对于一维集成,我的C ++文件如下所示:

    // [[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);

}

具有有限限制的二维积分代码

// [[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 个答案:

答案 0 :(得分:0)

我已经更新了您的代码,以将积分限制作为参数并返回错误代码并进行估算:

// [[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))
*/

结果:

> 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

因此对于较小的y上限,积分不会收敛。并且当它收敛时,结果(几乎)为零。当人们将上限提高到大约1e307,即几乎.Machine$double.xmax时,这种情况不会改变。之后,我得到NaN

但是,如果我使用cubature包,结果将大不相同:

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

我不确定这是怎么回事。