1

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?

Leigh K
  • 561
  • 6
  • 20
  • I may be missing a detail but right now I think you have a design thinko here. If `objfun` is an R function then it does not become a C++ function "just like that" by you calling from C++ via RInside. It is however possible to pass user-defined C++ functions via R to C++ optimisers. I have an example in the package RcppDE and on the Rcpp Gallery. – Dirk Eddelbuettel Dec 12 '18 at 15:51
  • Thanks for the response Dirk. The post above is a minimal example. In my actual implementation, objfun is not an R function, it is a C++ function that calls a routine to solve differential equations. It needs to remain a C++ function because of performance concerns. What I need to do is be able to pass that C++ function to the R cma_es function, so it needs to be wrapped in such a way as to be accepted by the cma_es function call. In regards to the minimal RInside example above, how do I wrap the C++ objfun function to be accepted by the RInside call to cma_es? – Leigh K Dec 12 '18 at 15:58
  • 1
    You take a C++ functon and pass it R to be passed to C++ library as a C++ function. "In theory" I am sure it can be made to work. In practice ... well I am not sure I'd start there. As for the *narrow answer* to your quesiton: no, there is no canned solution within RInside for this. – Dirk Eddelbuettel Dec 12 '18 at 16:14
  • Anyway: if you want to go that route see existing examples about the external pointer interface in R itself, and the `Rcpp::XPtr` class. It allows you to wrap your function (via clever function pointers wrapped in a SEXP) along the SEXP interface used by Rcpp and RInside. – Dirk Eddelbuettel Dec 12 '18 at 16:21

0 Answers0