Hi Christoph,

On 30 April 2013 at 10:20, Christoph Bergmeir wrote:
| Hi Dirk (and the rest of the list),
| 
| I think I have it working; attached is a patch that adds this 
| functionality to RcppDE. I also came along something which is probably a 
| bug: The passed environment is never used. In line 75 of DEoptim.R you 
| just create one. I changed this to
| 
| if(!hasArg(env)) env <- new.env()

>From the look of it, this seems right.  

I remember checking a few things with Josh regarding the use of the
environment.  As DEoption does not permit compiled functions, we may not have
tested this variant.  I need to get a few things off my plate and get back to
this. 
 
| Now you can use it like this:
| 
| #--------------------------
| # RcppDE example
| #--------------------------
| library(inline)
| library(RcppDE)
| 
| inc <- 'double rastrigin(SEXP xs, SEXP env) {
|    Rcpp::NumericVector x(xs);
|    Rcpp::Environment e(env);
| 
|    std::vector<double> param = e["x"];
| 
|    int n = x.size();
|    double sum = 20.0;
|    for (int i=0; i<n; i++) {
|    sum += x[i]+2 - 10*cos(2*M_PI*x[i]);
| 
|    Rprintf("ap: %f\\n", param[0]);
| }
| return(sum);
| }
| '
| 
| ## now via a class returning external pointer
| src.xptr <- '
|      typedef double (*funcPtr)(SEXP, SEXP);
|      return(XPtr<funcPtr>(new funcPtr(&rastrigin)));
|      '
| create_xptr <- cxxfunction(signature(), body=src.xptr, inc=inc, 
| plugin="Rcpp")
| 
| n <- 10
| maxIt <- 100
| 
| env <- new.env()
| env[["x"]] <- 1:4
| 
| res <- RcppDE::DEoptim(fn=create_xptr(), env=env, lower=rep(-25, n), 
| upper=rep(25, n),
|        control=list(NP=10*n, itermax=maxIt, trace=FALSE))
| 
| res$optim
| #------------------------------------------------
| 
| Regards and thanks for the help,

Thanks for the example.  Maybe I'll make this another demo...

Are you all set on your side of things then?

Dirk



| Christoph
| 
| 
| On 04/29/2013 02:41 PM, Dirk Eddelbuettel wrote:
| >
| > On 29 April 2013 at 14:22, Christoph Bergmeir wrote:
| > | Hi,
| > |
| > | ok, that's exactly the file I was looking at right now. The problem is
| > | that my objective function is implemented in C++, and passed as an
| > | external pointer. So in evaluate.h, instead of in the EvalStandard case
| > | I'm in the EvalCompiled case, where the environment is not used. My
| > | question now is if I can include it there somehow..
| >
| > Right.  Just how EvalBase and EvalStandard extend the basic interface, we
| > "just" need to create something that lets an XPtr be evaluation along with 
an
| > environment.
| >
| > Anyway, past bedtime here so no more from me...
| >
| > Dirk
| >
| > | Regards,
| > | Christoph
| > |
| > | On 04/29/2013 02:16 PM, Dirk Eddelbuettel wrote:
| > | >
| > | > On 29 April 2013 at 13:55, Christoph Bergmeir wrote:
| > | > | Hi,
| > | > |
| > | > | thanks Dirk for the prompt reply. Ok, this was also the solution I had
| > | > | in mind. I'll try to find the code in RcppDE or try to implement it
| > | > | myself..I'll keep you posted with any advances.
| > | >
| > | > I think this may do the trick:  demo/environment.R in the RcppDE 
package:
| > | >
| > | >
| > | > suppressMessages(library(RcppDE))
| > | >
| > | > ## somewhat pathodological example with nuisance parameter mul
| > | > Rastrigin <- function(x) {
| > | >      mul * (sum(x+2 - 10 * cos(2*pi*x)) + 20)
| > | > }
| > | >
| > | > ## create a new environment associated with the function
| > | > funenv <- environment(fun=Rastrigin)
| > | > assign("mul", 2, envir=funenv)        ## set value
| > | >
| > | > out <- DEoptim(Rastrigin, -25, 25,
| > | >                 control=list(NP=10, trace=0),
| > | >                 env=funenv)
| > | > summary(out)
| > | >
| > | >
| > | >
| > | > Hth,  Dirk
| > | >
| > | > |
| > | > | Regards,
| > | > | Christoph
| > | > |
| > | > | On 04/29/2013 01:44 PM, Dirk Eddelbuettel wrote:
| > | > | >
| > | > | > On 29 April 2013 at 12:37, Christoph Bergmeir wrote:
| > | > | > | Dear list,
| > | > | > |
| > | > | > | I'm looking for some advice on a specific problem. Using RcppDE 
there is
| > | > | > | the possibility to give the optimizer directly an external 
pointer to
| > | > | > | the C++ function it will use as the objective function. I found 
this
| > | > | > | mechanism pretty useful as it may speed up things quite a lot (I 
have a
| > | > | > | problem where the speedup is from 17 minutes to some seconds), so 
that I
| > | > | > | use the same mechanism as RcppDE in our package Rmalschains and 
in the
| > | > | > | Rdonlp2 package, which is available from Rmetrics on Rforge.
| > | > | > |
| > | > | > | The problem that this mechanism has is that it cannot handle 
additional
| > | > | > | parameters to the objective function. Having additional 
parameters is
| > | > | >
| > | > | > I think it can. The DEoptim folks, particularly Josh, pointed this 
out and
| > | > | > the best general way is to assign all you need in a new environment 
-- which
| > | > | > you can assign to from R and (thanks to Rcpp) from C++.  Then pass 
that down.
| > | > | >
| > | > | > I think I have an example of that in the package but I don't have 
time right
| > | > | > now to chase this.
| > | > | >
| > | > | > But yes, this _is_ a very neat feature and something that needs 
broader
| > | > | > exposure.
| > | > | >
| > | > | > Maybe I can help in a few days.
| > | > | >
| > | > | > Dirk
| > | > | >
| > | > | > | often essential, because if you fit a model to data you need the 
data
| > | > | > | available in the target function. I illustrate the problem with an
| > | > | > | example I took from the RcppDE tests:
| > | > | > |
| > | > | > | #-----------------------------------------
| > | > | > |
| > | > | > | library(inline)
| > | > | > | library(RcppDE)
| > | > | > |
| > | > | > | inc <- 'double rastrigin(SEXP xs) { //here I want to give it an
| > | > | > | additional parameter: SEXP additional_parameter
| > | > | > |
| > | > | > |    //Do something with the parameter, e.g. use it for result
| > | > | > | calculation. Here we just want to print it
| > | > | > |    //double my_additional_parameter =
| > | > | > | Rcpp::as<double>(additional_parameter);
| > | > | > |    //Rprintf("ap: %f\\n", my_additional_parameter);
| > | > | > |
| > | > | > |    Rcpp::NumericVector x(xs);
| > | > | > |    int n = x.size();
| > | > | > |    double sum = 20.0;
| > | > | > |    for (int i=0; i<n; i++) {
| > | > | > |    sum += x[i]+2 - 10*cos(2*M_PI*x[i]);
| > | > | > |
| > | > | > | }
| > | > | > | return(sum);
| > | > | > | }
| > | > | > | '
| > | > | > |
| > | > | > | src.xptr <- '
| > | > | > |      typedef double (*funcPtr)(SEXP);
| > | > | > |      return(XPtr<funcPtr>(new funcPtr(&rastrigin)));
| > | > | > |      '
| > | > | > | create_xptr <- cxxfunction(signature(), body=src.xptr, inc=inc,
| > | > | > | plugin="Rcpp")
| > | > | > |
| > | > | > | n <- 10
| > | > | > | maxIt <- 100
| > | > | > |
| > | > | > | res <- RcppDE::DEoptim(fn=create_xptr(), lower=rep(-25, n),
| > | > | > | upper=rep(25, n),
| > | > | > |        control=list(NP=10*n, itermax=maxIt, trace=FALSE)) #,
| > | > | > | additional_paramater=25)
| > | > | > |
| > | > | > | res$optim
| > | > | > |
| > | > | > | #-----------------------------------------
| > | > | > |
| > | > | > | I currently get around this by having a global singleton object 
which
| > | > | > | holds these parameters. This works but of course is not very nice 
when
| > | > | > | it comes to parallelization. The code is more or less like this:
| > | > | > |
| > | > | > | //----------------------------------------------
| > | > | > | class TargetFunction {
| > | > | > |
| > | > | > |    private:
| > | > | > |
| > | > | > |    static TargetFunction *TargetFunctionSingleton;
| > | > | > |    std::vector<double> param;
| > | > | > |    double objval;
| > | > | > |
| > | > | > |    public:
| > | > | > |
| > | > | > |    void eval(const double* x, int n) {
| > | > | > |      double sum = 20.0;
| > | > | > |      for (int i=0; i<n; i++) {
| > | > | > |        sum += x[i]+2 - 10*cos(2*M_PI*x[i]);
| > | > | > |      };
| > | > | > |
| > | > | > | //here I can use the parameter now!!
| > | > | > |      Rprintf("ap: %f\\n", param[0]);
| > | > | > |
| > | > | > |      this->objval = sum;
| > | > | > |    };
| > | > | > |
| > | > | > |    void init(std::vector<double> & p_param) {
| > | > | > |     this->param = p_param;
| > | > | > |    };
| > | > | > |
| > | > | > |    static TargetFunction* getTargetFunctionSingleton() {
| > | > | > |     if( TargetFunctionSingleton == 0 )
| > | > | > |             TargetFunctionSingleton = new TargetFunction();
| > | > | > |     return TargetFunctionSingleton;
| > | > | > |    };
| > | > | > |
| > | > | > |    static void deleteTargetFunctionSingleton(){
| > | > | > |     if( TargetFunctionSingleton == 0 ) return;
| > | > | > |     else {
| > | > | > |             delete TargetFunctionSingleton;
| > | > | > |             TargetFunctionSingleton = 0;
| > | > | > |     }
| > | > | > |     return;
| > | > | > |    };
| > | > | > |
| > | > | > |    double getObjVal() {
| > | > | > |      return(objval);
| > | > | > |    };
| > | > | > |
| > | > | > |
| > | > | > | };
| > | > | > |
| > | > | > | TargetFunction* TargetFunction::TargetFunctionSingleton = 0;
| > | > | > |
| > | > | > | RcppExport SEXP targetFunction(SEXP p_par)
| > | > | > | {
| > | > | > |   Rcpp::NumericVector par(p_par);
| > | > | > |
| > | > | > |   TargetFunction* sp = 
TargetFunction::getTargetFunctionSingleton();
| > | > | > |
| > | > | > |   sp->eval(par.begin(), par.size());
| > | > | > |
| > | > | > |   return Rcpp::wrap(sp->getObjVal());
| > | > | > |
| > | > | > | }
| > | > | > |
| > | > | > | RcppExport SEXP targetFunctionInit(SEXP p_param) {
| > | > | > |
| > | > | > |   TargetFunction::deleteTargetFunctionSingleton();
| > | > | > |
| > | > | > |   TargetFunction* sp = 
TargetFunction::getTargetFunctionSingleton();
| > | > | > |
| > | > | > |    std::vector<double> param = Rcpp::as< std::vector<double> 
>(p_param);
| > | > | > |
| > | > | > |   sp->init(param);
| > | > | > |
| > | > | > |   return R_NilValue;
| > | > | > |
| > | > | > | }
| > | > | > |
| > | > | > | RcppExport SEXP GetTargetFunctionPtr() {
| > | > | > |
| > | > | > |   typedef SEXP (*funcPtr)(SEXP);
| > | > | > |
| > | > | > |   return (Rcpp::XPtr<funcPtr>(new funcPtr(&targetFunction)));
| > | > | > | }
| > | > | > | //-----------------------------------------------------
| > | > | > |
| > | > | > | Now, before doing the optimization, I call targetFunctionInit and 
set
| > | > | > | the additional parameters. Afterwards, everything is as in the 
example
| > | > | > | above, and I have the additional parameters available in the 
target
| > | > | > | function. Now the question is how I could solve this more 
elegantly, or
| > | > | > | more R like. The first thing that comes to mind is to use an R
| > | > | > | environment instead of the singleton.  However, how can I do 
this? I
| > | > | > | could have a singleton list of objects and then use the address 
of the R
| > | > | > | environment as a hash to find the right object in the list. But 
this is
| > | > | > | probably not really the way R environments should be used, and I 
wonder
| > | > | > | if this will cause any trouble.
| > | > | > |
| > | > | > | Any advise is highly appreciated.
| > | > | > |
| > | > | > | Regards,
| > | > | > | Christoph
| > | > | > |
| > | > | > | --
| > | > | > | Christoph Bergmeir
| > | > | > | e-mail: c.bergm...@decsai.ugr.es
| > | > | > | Grupo SCI2S, DiCITS Lab          (http://sci2s.ugr.es/DiCITS)
| > | > | > | Dpto. de Ciencias de la Computacion e Inteligencia Artificial
| > | > | > | E.T.S. Ingenierias de Informatica y Telecomunicacion
| > | > | > | Universidad de Granada
| > | > | > | 18071 - GRANADA (Spain)
| > | > | > | _______________________________________________
| > | > | > | Rcpp-devel mailing list
| > | > | > | Rcpp-devel@lists.r-forge.r-project.org
| > | > | > | 
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
| > | > | >
| > | > |
| > | > | --
| > | > | Christoph Bergmeir
| > | > | e-mail: c.bergm...@decsai.ugr.es
| > | > | Grupo SCI2S, DiCITS Lab          (http://sci2s.ugr.es/DiCITS)
| > | > | Dpto. de Ciencias de la Computacion e Inteligencia Artificial
| > | > | E.T.S. Ingenierias de Informatica y Telecomunicacion
| > | > | Universidad de Granada
| > | > | 18071 - GRANADA (Spain)
| > | >
| > |
| > | --
| > | Christoph Bergmeir
| > | e-mail: c.bergm...@decsai.ugr.es
| > | Grupo SCI2S, DiCITS Lab          (http://sci2s.ugr.es/DiCITS)
| > | Dpto. de Ciencias de la Computacion e Inteligencia Artificial
| > | E.T.S. Ingenierias de Informatica y Telecomunicacion
| > | Universidad de Granada
| > | 18071 - GRANADA (Spain)
| >
| 
| -- 
| Christoph Bergmeir
| e-mail: c.bergm...@decsai.ugr.es
| Grupo SCI2S, DiCITS Lab          (http://sci2s.ugr.es/DiCITS)
| Dpto. de Ciencias de la Computacion e Inteligencia Artificial
| E.T.S. Ingenierias de Informatica y Telecomunicacion
| Universidad de Granada
| 18071 - GRANADA (Spain)
| 
| ----------------------------------------------------------------------
| diff -rupN RcppDE_orig/R/DEoptim.R RcppDE/R/DEoptim.R
| --- RcppDE_orig/R/DEoptim.R   2012-04-09 05:43:24.000000000 +1000
| +++ RcppDE/R/DEoptim.R        2013-04-30 10:01:44.686949637 +1000
| @@ -72,7 +72,7 @@ DEoptim <- function(fn, lower, upper, co
|    else
|      nam <- paste("par", 1:length(lower), sep = "")
|  
| -  env <- new.env()
| +  if(!hasArg(env)) env <- new.env()
|  
|    ctrl <- do.call(DEoptim.control, as.list(control))
|    ctrl$npar <- length(lower)
| Binary files RcppDE_orig/src/deoptim.o and RcppDE/src/deoptim.o differ
| diff -rupN RcppDE_orig/src/devol.cpp RcppDE/src/devol.cpp
| --- RcppDE_orig/src/devol.cpp 2012-04-09 06:24:02.000000000 +1000
| +++ RcppDE/src/devol.cpp      2013-04-29 14:52:15.434839798 +1000
| @@ -26,7 +26,7 @@ void devol(double VTR, double f_weight,
|      //ProfilerStart("/tmp/RcppDE.prof");
|      Rcpp::DE::EvalBase *ev = NULL;           // pointer to abstract base 
class
|      if (TYPEOF(fcall) == EXTPTRSXP) {                // non-standard mode: 
we are being passed an external pointer
| -     ev = new Rcpp::DE::EvalCompiled(fcall); // so assign a pointer using 
external pointer in fcall SEXP
| +     ev = new Rcpp::DE::EvalCompiled(fcall, rho); // so assign a pointer 
using external pointer in fcall SEXP
|      } else {                                 // standard mode: env_ is an 
env, fcall_ is a function 
|       ev = new Rcpp::DE::EvalStandard(fcall, rho);    // so assign R function 
and environment
|      }
| Binary files RcppDE_orig/src/devol.o and RcppDE/src/devol.o differ
| diff -rupN RcppDE_orig/src/evaluate.h RcppDE/src/evaluate.h
| --- RcppDE_orig/src/evaluate.h        2012-04-09 06:24:02.000000000 +1000
| +++ RcppDE/src/evaluate.h     2013-04-29 14:56:38.735580878 +1000
| @@ -13,7 +13,7 @@
|  namespace Rcpp {
|      namespace DE {
|  
| -     double genrose(SEXP xs) {       // genrose function in C++
| +     double genrose(SEXP xs, SEXP env) {     // genrose function in C++
|           Rcpp::NumericVector x(xs);
|           int n = x.size();
|           double sum = 1.0;
| @@ -23,7 +23,7 @@ namespace Rcpp {
|           return(sum);
|       }
|  
| -     double wild(SEXP xs) {          // wild function in C++
| +     double wild(SEXP xs, SEXP env) {                // wild function in C++
|           Rcpp::NumericVector x(xs);
|           int n = x.size();
|           double sum = 0.0;
| @@ -35,7 +35,7 @@ namespace Rcpp {
|           return(sum);
|       }
|  
| -     double rastrigin(SEXP xs) {     // rastrigin function in C++
| +     double rastrigin(SEXP xs, SEXP env) {   // rastrigin function in C++
|           Rcpp::NumericVector x(xs);
|           int n = x.size();
|           double sum = 20.0;
| @@ -73,22 +73,25 @@ namespace Rcpp {
|           }
|       };
|  
| -     typedef double (*funcPtr)(SEXP);
| +     typedef double (*funcPtr)(SEXP, SEXP);
|       class EvalCompiled : public EvalBase {
|       public:
| -         EvalCompiled( Rcpp::XPtr<funcPtr> xptr ) {
| +         EvalCompiled( Rcpp::XPtr<funcPtr> xptr, SEXP env_ ) {
|               funptr = *(xptr);
| +                env = env_;
|           };
| -         EvalCompiled( SEXP xps ) {
| +         EvalCompiled( SEXP xps, SEXP env_ ) {
|               Rcpp::XPtr<funcPtr> xptr(xps);
|               funptr = *(xptr);
| +                env = env_;
|           };
|           double eval(SEXP par) {
|               neval++;
| -             return funptr(par);
| +             return funptr(par, env);
|           }
|       private:
|           funcPtr funptr;
| +            SEXP env;
|       };
|  
|       RcppExport SEXP putFunPtrInXPtr(SEXP funname) {
| Binary files RcppDE_orig/src/permute.o and RcppDE/src/permute.o differ
| Binary files RcppDE_orig/src/RcppDE.so and RcppDE/src/RcppDE.so differ

-- 
Dirk Eddelbuettel | e...@debian.org | http://dirk.eddelbuettel.com
_______________________________________________
Rcpp-devel mailing list
Rcpp-devel@lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel

Reply via email to