How to calculate integral, numerically, in Rcpp

匆匆过客 提交于 2019-12-07 03:35:28

You can code your function in C and call it, for instance, via the sourceCpp function and then integrate it in R. In alternative, you can call the integrate function of R within your C code by using the Function macro of Rcpp. See Dirk's book (Seamless R and C++ Integration with Rcpp) on page 56 for an example of how to call R functions from C. Another alternative (which I believe is the best for most cases) is to integrate your function written in C , directly in C, using the RcppGSL package.

As about the huge normalizing constant, sometimes it is better to scale the function at the mode before integrating it (you can find modes with, e.g., nlminb, optim, etc.). Then, you integrate the rescaled function and to recover the original nroming constant multiply the resulting normalizing constant by the rescaling factor. Hope this may help!

after reading your @utobi advice, I felt programming by my own maybe easier. I simply use Simpson formula to approximate the integral:

// [[Rcpp::export]]
double den_cpp (double x, double theta){
return(2*x/theta*(x<=theta)+2*(1-x)/(1-theta)*(theta<x));
}
// [[Rcpp::export]]
double joint_cpp ( double theta,int n,NumericVector x, double a, double b){
double val = 1.0;
NumericVector d(n);
for (int i = 0; i < n; i++){
double tmp = den_cpp(x[i],theta);
val = val*tmp;
}
val=val*R::dbeta(theta,a,b,0);
return(val);
}
// [[Rcpp::export]]
List Cov_rate_raw ( double theta_true,  int n, double a, double b,NumericVector x){
//This function is used to test, not used in the fanal one
int steps = 1000;
double s = 0;
double start = 1.0e-4;
std::cout<<start<<" ";
double end = 1-start;
std::cout<<end<<" ";
double h = (end-start)/steps;
std::cout<<"1st h ="<<h<<" ";
double area = 0;
double margin = 0;
for (int i = 0; i < steps ; i++){
double at_x = start+h*i;
double f_val = (joint_cpp(at_x,n,x,a,b)+4*joint_cpp(at_x+h/2,n,x,a,b)+joint_cpp(at_x+h,n,x,a,b))/6;
s = s + f_val;
}
margin = h*s;
s=0;
h=(theta_true-start)/steps;
std::cout<<"2nd h ="<<h<<" ";
for (int i = 0; i < steps ; i++){
double at_x = start+h*i;
double f_val = (joint_cpp(at_x,n,x,a,b)+4*joint_cpp(at_x+h/2,n,x,a,b)+joint_cpp(at_x+h,n,x,a,b))/6;
s = s + f_val;
}
area = h * s;
double r = area/margin;
int cover = (r>=0.025)&&(r<=0.975);
List ret;
ret["s"] = s;
ret["margin"] = margin;
ret["area"] = area;
ret["ratio"] = r;
ret["if_cover"] = cover;
return(ret);
}

I'm not that good at c++, so the two for loops like kind of silly.

It generally works, but there are still several potential problems:

  1. I don't really know how to choose the steps, or how many sub intervals do I need to approximate the integrals. I've taken numerical analysis when I was an undergraduate, I think maybe I need to check my book about the expression of the error term, to decide the step length.
  2. I compared my results with those from R. the integrate() function in R can take care of the integral over the interval [0,1]. That helps me because my function is undefined at 0 or 1, which takes infinite value. In my C++ code, I can only make my interval from [1e-4, 1-1e-4]. I tried different values like 1e-7, 1e-10, however, 1e-4 was the one most close to R's results....What should I do with it?
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!