I know that I asked the same question before, but as I am pretty new here the question was asked poorly and not reproducible. Therefore I try to do it better here. (If I only ed
For double integrals, it is better to use the cubature package.
library(cubature)
f <- function(x){
exp(16*x[1] - 8*x[2] - (x[2] + 0.01458757)^2/0.0001126501)
}
The hcubature function gives a result which is not stable when one decreases the tolerance:
> 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
Contrary to the result of pcubature, which is stable:
> 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
The p-adaptive version, pcubature, repeatedly doubles the degree of the quadrature rules until convergence is achieved, and is based on a tensor product of Clenshaw-Curtis quadrature rules. This algorithm is often superior to h-adaptive integration for smooth integrands in a few (<=3) dimensions, but is a poor choice in higher dimensions or for non-smooth integrands.
Next, RcppNumerical provides a powerful multiple integration.
// [[Rcpp::depends(RcppEigen)]]
// [[Rcpp::depends(RcppNumerical)]]
#include
#include
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
);
}
It gives the same result as pcubature:
> Valegard()
$approximate
[1] 0.001323689
$error_estimate
[1] 9.893371e-14
$error_code
[1] 0
By the way, an exact integration with Mathematica 11 also provides this result:
Integrate[E^(16 x - 8877.04 (0.0145876 + y)^2 - 8 y), {y, -2, 2}, {x, -2.5, 0}]
0.00132369