Extra Utilities


Included in src/util/SimulatedAnnealing.hh is a general purpose algorithm for globally minimizing a D dimensional continuous function that contains many local minima. Effectively this is a hybrid between the Nelder-Mead downhill simplex method and simulated annealing as described in section 10.9 of Numerical Recipes in 'C' but reimplemented in a less confusing way for C++.


The SimulatedAnnealing class is templated to the dimensionality of function to be minimized. The constructor

SimulatedAnnealing(Minimizable *func)

takes a single argument that is an object implementing the pure virtual Minimizable class.

Minimizable only requires that the object implement the call operator as follows

virtual double operator()(double *args);

where the result is the value of the function evaluated at function(args[0],…,args[D]).

After creating the SimulatedAnnealing object, set the initial simplex using

void SetSimplexPoint(size_t pt, std::vector<double> &point)

where pt specifies the index of the point you are setting [0, D], i.e. D+1 required points, and the simplex is copied from the D length vector point.

Once the initial D+1 simplex points are specified, call the Anneal method to actually minimize

void Anneal(double temp0, size_t nAnneal, size_t nEval, double alpha)

where temp0 is the initial temperature and alpha controls the temperature according to the annealing schedule T = temp0 * (1 - cycle / nAnneal ) ^ alpha. The annealing is run at nAnneal different temperatures ( cycle ) where each cycle tests nEval new points.

Once the algorithm has finished GetBestPoint will return the tested point with the lowest function value in the last Anneal cycle

void GetBestPoint(std::vector<double> &point)

where the best point will be copied into the D length vector point.


As a concrete example, to minimize f(x,y) = x^A+y^B with A=B=2, first implement the Minimizable function

class Func : public Minimizable {
    double A,B;
    Func(double _A, double _B) : A(_A), B(_B) { };
    virtual double operator()(double *params) {
        return pow(params[0],A) + pow(params[1],B);

Then the code to minimize would look something like this

Func func(2.0,2.0); //A = B = 2.0
SimulatedAnnealing<2> anneal(func);

vector<double> point(2), seed(2);

seed[0] = seed[1] = -1.0;
anneal.SetSimplexPoint(0,seed); // Point0 -> (-1,-1)
seed[0] = 1.0;
anneal.SetSimplexPoint(1,seed); // Point1 -> (1,-1)
seed[1] = 1.0;
anneal.SetSimplexPoint(2,seed); // Point2 -> (1,1)

anneal.Anneal(10,150,50,4.0); // Minimize


cout << point[0] << ',' << point[1] << endl;