I am looking to employ the R library cmaes (Covariance Matrix Adaptation Evolutionary Strategy) in a C++ program using RInside.
https://www.rdocumentation.org/packages/cmaes/versions/1.0-11/topics/cma_es
There is a C++ implementation of the same algorithm (libcmaes) but the way that constraints are handled (which is not an inherent part of the algorithm) is not the same as the R implementation. I haven't used RInside before so I am utilizing the examples distributed with the library as a reference point:
https://github.com/eddelbuettel/rinside/tree/master/inst/examples/standard
As a minimal example, the R script which I am attempting to integrate into C++ is shown below:
library(cmaes)
seednum<-100
set.seed(seednum, kind="Mersenne-Twister")
ctl_list[["stop.tolx"]]<-0.001
initpar<-c(7.488549, 3.403088, 7.773092, 4.331335, 1.881067)
objfun<-function(pop){
val<-0
for (element in pop)
{
val<-val+(element*element)
}
val
}
res<-cma_es(initpar, objfun, lower=-10, upper=10, control=ctl_list)
print(res)
The issue I am facing is that my objective function (which is a function argument to cma_es) is written in C++ (and must remain in C++ for performance reasons), therefore it has to be wrapped in such a way that the R function accepts it. I do not see anything in the examples to achieve such a thing. The C++ code that I have so far is below:
#include <RInside.h> // for the embedded R via RInside
double objfun (std::vector<double> x)
{
double val = 0.0;
for (unsigned i = 0; i < x.size(); i++)
val += x[i]*x[i];
return val;
}
int main(int argc, char *argv[])
{
try
{
RInside R(argc, argv); // create an embedded R instance
std::string load_str = "suppressMessages(library(cmaes))";
R.parseEvalQ(load_str); // load library, no return value
std::vector<double> initpar = {7.480042, 2.880649, 8.380858, 4.620689, 1.910938};
R["initpar"] = initpar; // or R.assign(initpar, "initpar");
std::string seed_str = "seednum<-100; set.seed(seednum, kind='Mersenne-Twister')";
R.parseEval(seed_str); // Parse and evaluate, nothing to return
std::string list = "ctl_list<-list()";
R.parseEval(list);
R.parseEvalQ("ctl_list[['stop.tolx']]<-0.001");
std::string cmd = "cma_es(initpar, objfun, lower=-10, upper=10, control=ctl_list)";
Rcpp::CharacterVector res = R.parseEval(cmd); // parse, eval + return result
for (int i = 0; i < res.size(); i++) // loop over vector and output
{
std::cout << res[i];
}
std::cout << std::endl;
}
catch(std::exception& ex)
{
std::cerr << "Exception caught: " << ex.what() << std::endl;
}
catch(...)
{
std::cerr << "Unknown exception caught" << std::endl;
}
exit(0);
}
If the C++ function were being passed to R using Rcpp then // [[Rcpp::export]]
would be used to pass it, but the same does not apply here. The above clearly fails to execute with the following error:
Error in FUN(newX[, i], ...) : object 'objfun' not found
Exception caught: Error evaluating: cma_es(initpar, objfun, lower=-10, upper=10, control=ctl_list)
So the question is simply, how do I wrap a C++ function using RInside in such a way that it can be passed to an R function?