Skip to content

Defining a custom algorithm based on libcmaes primitives

beniz edited this page Dec 19, 2014 · 2 revisions

It is possible to directly expose the inner calls of the library in order to develop new algorithms.

This is typically useful to craft new restart strategies, or specialized optimization loops with custom control.

The code below is available from examples/sample-code-ask-tell.cc and demonstrates how to override the default optimization strategy class.

Since the library is fully object oriented, a user custom space can be easily created by inheriting the default CMAStrategy class, overloading and customizing functions and classes at will:

#include "cmaes.h"
#include <iostream>

using namespace libcmaes;

FitFunc fsphere = [](const double *x, const int N)
{
  double val = 0.0;
  for (int i=0;i<N;i++)
    val += x[i]*x[i];
  return val;
};

class customCMAStrategy : public CMAStrategy<CovarianceUpdate>
{
public:
  customCMAStrategy(FitFunc &func,
                    CMAParameters<> &parameters)
    :CMAStrategy<CovarianceUpdate>(func,parameters)
  {
  }

  ~customCMAStrategy() {}

  dMat ask()
  {
    return CMAStrategy<CovarianceUpdate>::ask();
  }

  void eval(const dMat &candidates,
            const dMat &phenocandidates=dMat(0,0))
 // custom eval.                                                                                             
    for (int r=0;r<candidates.cols();r++)
      {
        _solutions.get_candidate(r)._x = candidates.col(r);
        if (phenocandidates.size()) // if candidates in phenotype space are given                               
          _solutions.get_candidate(r).set_fvalue(_func(phenocandidates.col(r).data(),candidates.rows()));
        else _solutions.get_candidate(r).set_fvalue(_func(candidates.col(r).data(),candidates.rows()));

        //std::cerr << "candidate x: " << _solutions._candidate(r).get_x_dvec().transpose() << std::endl;             
      }
    update_fevals(candidates.cols());
  }

  void tell()
  {
    return CMAStrategy<CovarianceUpdate>::tell();
  }

  bool stop()
  {
    return CMAStrategy<CovarianceUpdate>::stop();
  }

};

int main(int argc, char *argv[])
{
  int dim = 10; // problem dimensions.                                                                          
  std::vector<double> x0(dim,10.0);
  double sigma = 0.1;

  CMAParameters<> cmaparams(x0,sigma);
  //ESOptimizer<CMAStrategy<CovarianceUpdate>,CMAParameters<>> optim(fsphere,cmaparams);    // default call               
  ESOptimizer<customCMAStrategy,CMAParameters<>> optim(fsphere,cmaparams);

  while(!optim.stop())
    {
      dMat candidates = optim.ask();
      optim.eval(candidates);
      optim.tell();
      optim.inc_iter(); // important step: signals next iteration.                                              
    }
  std::cout << optim.get_solutions() << std::endl;
}