manual merge from cmaes

This commit is contained in:
Pierre Savéant 2012-07-18 14:53:08 +02:00
commit 1d41c79c1a
20 changed files with 916 additions and 156 deletions

View file

@ -41,8 +41,8 @@ Authors:
#include "Sphere.h"
typedef eoReal<eoMinimizingFitness> EOT;
typedef edoNormalMulti< EOT > Distrib;
typedef eoReal<eoMinimizingFitness> RealVec;
typedef edoNormalAdaptive< RealVec > Distrib;
int main(int ac, char** av)
@ -57,26 +57,34 @@ int main(int ac, char** av)
eoState state;
// Instantiate all needed parameters for EDA algorithm
double selection_rate = parser.createParam((double)0.5, "selection_rate", "Selection Rate", 'R', section).value(); // R
eoSelect< EOT >* selector = new eoDetSelect< EOT >( selection_rate );
state.storeFunctor(selector);
edoEstimator< Distrib >* estimator = new edoEstimatorNormalMulti< EOT >();
state.storeFunctor(estimator);
eoEvalFunc< EOT >* plainEval = new Rosenbrock< EOT >();
state.storeFunctor(plainEval);
//double selection_rate = parser.createParam((double)0.5, "selection_rate", "Selection Rate", 'R', section).value(); // R
unsigned long max_eval = parser.getORcreateParam((unsigned long)0, "maxEval", "Maximum number of evaluations (0 = none)", 'E', "Stopping criterion").value(); // E
eoEvalFuncCounterBounder< EOT > eval(*plainEval, max_eval);
unsigned int dim = parser.createParam((unsigned int)10, "dimension-size", "Dimension size", 'd', section).value(); // d
double mu = dim / 2;
edoNormalAdaptive<RealVec> distribution(dim);
eoSelect< RealVec >* selector = new eoRankMuSelect< RealVec >( mu );
state.storeFunctor(selector);
edoEstimator< Distrib >* estimator = new edoEstimatorNormalAdaptive<RealVec>( distribution );
state.storeFunctor(estimator);
eoEvalFunc< RealVec >* plainEval = new Rosenbrock< RealVec >();
state.storeFunctor(plainEval);
eoEvalFuncCounterBounder< RealVec > eval(*plainEval, max_eval);
eoRndGenerator< double >* gen = new eoUniformGenerator< double >(-5, 5);
state.storeFunctor(gen);
unsigned int dimension_size = parser.createParam((unsigned int)10, "dimension-size", "Dimension size", 'd', section).value(); // d
eoInitFixedLength< EOT >* init = new eoInitFixedLength< EOT >( dimension_size, *gen );
eoInitFixedLength< RealVec >* init = new eoInitFixedLength< RealVec >( dim, *gen );
state.storeFunctor(init);
@ -84,28 +92,28 @@ int main(int ac, char** av)
// Generation of population from do_make_pop (creates parameters, manages persistance and so on...)
// ... and creates the parameters: L P r S
// this first sampler creates a uniform distribution independently from our distribution (it does not use edoUniform).
eoPop< EOT >& pop = do_make_pop(parser, state, *init);
eoPop< RealVec >& pop = do_make_pop(parser, state, *init);
// (2) First evaluation before starting the research algorithm
apply(eval, pop);
// Prepare bounder class to set bounds of sampling.
// This is used by edoSampler.
edoBounder< EOT >* bounder =
new edoBounderRng< EOT >( EOT(pop[0].size(), -5), EOT(pop[0].size(), 5), *gen); // FIXME do not use hard-coded bounds
edoBounder< RealVec >* bounder =
new edoBounderRng< RealVec >( RealVec(dim, -5), RealVec(dim, 5), *gen); // FIXME do not use hard-coded bounds
state.storeFunctor(bounder);
// Prepare sampler class with a specific distribution
edoSampler< Distrib >* sampler = new edoSamplerNormalMulti< EOT >( *bounder );
edoSampler< Distrib >* sampler = new edoSamplerNormalAdaptive< RealVec >( *bounder );
state.storeFunctor(sampler);
// stopping criteria
// ... and creates the parameter letters: C E g G s T
eoContinue< EOT >& eo_continue = do_make_continue(parser, state, eval);
eoContinue< RealVec >& eo_continue = do_make_continue(parser, state, eval);
// population output
eoCheckPoint< EOT >& pop_continue = do_make_checkpoint(parser, state, eval, eo_continue);
eoCheckPoint< RealVec >& pop_continue = do_make_checkpoint(parser, state, eval, eo_continue);
// distribution output
edoDummyContinue< Distrib >* dummy_continue = new edoDummyContinue< Distrib >();
state.storeFunctor(dummy_continue);
@ -115,9 +123,9 @@ int main(int ac, char** av)
// eoEPRemplacement causes the using of the current and previous
// sample for sampling.
eoReplacement< EOT >* replacor = new eoEPReplacement< EOT >(pop.size());
eoReplacement< RealVec >* replacor = new eoEPReplacement< RealVec >(pop.size());
state.storeFunctor(replacor);
// Some stuff to display helper when we are using -h option
if (parser.userNeedsHelp())
{
@ -129,40 +137,11 @@ int main(int ac, char** av)
make_verbose(parser);
make_help(parser);
// population output (after helper)
//
// FIXME: theses objects are instanciated there in order to avoid a folder
// removing as edoFileSnapshot does within ctor.
edoPopStat< EOT >* popStat = new edoPopStat<EOT>;
state.storeFunctor(popStat);
pop_continue.add(*popStat);
edoFileSnapshot* fileSnapshot = new edoFileSnapshot("EDA_ResPop");
state.storeFunctor(fileSnapshot);
fileSnapshot->add(*popStat);
pop_continue.add(*fileSnapshot);
// distribution output (after helper)
edoDistribStat< Distrib >* distrib_stat = new edoStatNormalMulti< EOT >();
state.storeFunctor(distrib_stat);
distribution_continue->add( *distrib_stat );
// eoMonitor* stdout_monitor = new eoStdoutMonitor();
// state.storeFunctor(stdout_monitor);
// stdout_monitor->add(*distrib_stat);
// distribution_continue->add( *stdout_monitor );
eoFileMonitor* file_monitor = new eoFileMonitor("eda_distribution_bounds.txt");
state.storeFunctor(file_monitor);
file_monitor->add(*distrib_stat);
distribution_continue->add( *file_monitor );
eoPopLoopEval<EOT> popEval( eval );
eoPopLoopEval<RealVec> popEval( eval );
// EDA algorithm configuration
edoAlgo< Distrib >* algo = new edoEDA< Distrib >
(popEval, *selector, *estimator, *sampler, *replacor,
edoAlgo< Distrib >* algo = new edoAlgoAdaptive< Distrib >
(distribution, popEval, *selector, *estimator, *sampler, *replacor,
pop_continue, *distribution_continue );

View file

@ -161,7 +161,7 @@ int main(int ac, char** av)
eoPopLoopEval<EOT> popEval( eval );
// EDA algorithm configuration
edoAlgo< Distrib >* algo = new edoEDA< Distrib >
edoAlgo< Distrib >* algo = new edoAlgoStateless< Distrib >
(popEval, *selector, *estimator, *sampler, *replacor,
pop_continue, *distribution_continue );

View file

@ -30,17 +30,21 @@ Authors:
#include "edoAlgo.h"
//#include "edoEDASA.h"
#include "edoEDA.h"
#include "edoAlgoAdaptive.h"
#include "edoAlgoStateless.h"
#include "edoDistrib.h"
#include "edoUniform.h"
#include "edoNormalMono.h"
#include "edoNormalMulti.h"
#include "edoNormalAdaptive.h"
#include "edoEstimator.h"
#include "edoEstimatorUniform.h"
#include "edoEstimatorNormalMono.h"
#include "edoEstimatorNormalMulti.h"
#include "edoEstimatorAdaptive.h"
#include "edoEstimatorNormalAdaptive.h"
#include "edoModifier.h"
#include "edoModifierDispersion.h"
@ -53,6 +57,7 @@ Authors:
#include "edoSamplerUniform.h"
#include "edoSamplerNormalMono.h"
#include "edoSamplerNormalMulti.h"
#include "edoSamplerNormalAdaptive.h"
#include "edoVectorBounds.h"

View file

@ -40,7 +40,7 @@ template < typename D >
class edoAlgo : public eoAlgo< typename D::EOType >
{
//! Alias for the type
typedef typename D::EOType EOT;
typedef typename D::EOType EOType;
// virtual R operator()(A1) = 0; (defined in eoUF)

View file

@ -22,14 +22,13 @@ Copyright (C) 2010 Thales group
/*
Authors:
Johann Dréo <johann.dreo@thalesgroup.com>
Caner Candan <caner.candan@thalesgroup.com>
Pierre Savéant <pierre.saveant@thalesgroup.com>
*/
#ifndef _edoEDA_h
#define _edoEDA_h
#ifndef _edoAlgoAdaptive_h
#define _edoAlgoAdaptive_h
#include <eo>
//#include <mo>
#include <utils/eoRNG.h>
@ -41,25 +40,27 @@ Authors:
//! edoEDA< D >
template < typename D >
class edoEDA : public edoAlgo< D >
/** A generic stochastic search template for algorithms that need a distribution parameter.
*/
template < typename EOD >
class edoAlgoAdaptive : public edoAlgo< EOD >
{
public:
//! Alias for the type EOT
typedef typename D::EOType EOT;
typedef typename EOD::EOType EOType;
//! Alias for the atom type
typedef typename EOT::AtomType AtomType;
typedef typename EOType::AtomType AtomType;
//! Alias for the fitness
typedef typename EOT::Fitness Fitness;
typedef typename EOType::Fitness Fitness;
public:
//! edoEDA constructor
/*!
Takes algo operators, all are mandatory
\param distrib A distribution to use, if you want to update this parameter (e.gMA-ES) instead of replacing it (e.g. an EDA)
\param evaluation Evaluate a population
\param selector Selection of the best candidate solutions in the population
\param estimator Estimation of the distribution parameters
@ -68,15 +69,17 @@ public:
\param pop_continuator Stopping criterion based on the population features
\param distribution_continuator Stopping criterion based on the distribution features
*/
edoEDA (
eoPopEvalFunc < EOT > & evaluator,
eoSelect< EOT > & selector,
edoEstimator< D > & estimator,
edoSampler< D > & sampler,
eoReplacement< EOT > & replacor,
eoContinue< EOT > & pop_continuator,
edoContinue< D > & distribution_continuator
edoAlgoAdaptive(
EOD & distrib,
eoPopEvalFunc < EOType > & evaluator,
eoSelect< EOType > & selector,
edoEstimator< EOD > & estimator,
edoSampler< EOD > & sampler,
eoReplacement< EOType > & replacor,
eoContinue< EOType > & pop_continuator,
edoContinue< EOD > & distribution_continuator
) :
_distrib(distrib),
_evaluator(evaluator),
_selector(selector),
_estimator(estimator),
@ -87,10 +90,12 @@ public:
_distribution_continuator(distribution_continuator)
{}
//! edoEDA constructor without an edoContinue
//! constructor without an edoContinue
/*!
Takes algo operators, all are mandatory
\param distrib A distribution to use, if you want to update this parameter (e.gMA-ES) instead of replacing it (e.g. an EDA)
\param evaluation Evaluate a population
\param selector Selection of the best candidate solutions in the population
\param estimator Estimation of the distribution parameters
@ -98,14 +103,16 @@ public:
\param replacor Replace old solutions by new ones
\param pop_continuator Stopping criterion based on the population features
*/
edoEDA (
eoPopEvalFunc < EOT > & evaluator,
eoSelect< EOT > & selector,
edoEstimator< D > & estimator,
edoSampler< D > & sampler,
eoReplacement< EOT > & replacor,
eoContinue< EOT > & pop_continuator
edoAlgoAdaptive (
EOD & distrib,
eoPopEvalFunc < EOType > & evaluator,
eoSelect< EOType > & selector,
edoEstimator< EOD > & estimator,
edoSampler< EOD > & sampler,
eoReplacement< EOType > & replacor,
eoContinue< EOType > & pop_continuator
) :
_distrib( distrib ),
_evaluator(evaluator),
_selector(selector),
_estimator(estimator),
@ -116,43 +123,40 @@ public:
_distribution_continuator( _dummy_continue )
{}
/** A basic EDA algorithm that iterates over:
* selection, estimation, sampling, bounding, evaluation, replacement
/** Call the algorithm
*
* \param pop the population of candidate solutions
* \return void
*/
void operator ()(eoPop< EOT > & pop)
void operator ()(eoPop< EOType > & pop)
{
assert(pop.size() > 0);
eoPop< EOT > current_pop;
eoPop< EOT > selected_pop;
eoPop< EOType > current_pop;
eoPop< EOType > selected_pop;
// FIXME one must instanciate a first distrib here because there is no empty constructor, see if it is possible to instanciate Distributions without parameters
D distrib = _estimator(pop);
// update the extern distribution passed to the estimator (cf. CMA-ES)
// OR replace the dummy distribution for estimators that do not need extern distributions (cf. EDA)
_distrib = _estimator(pop);
// Evaluating a first time the candidate solutions
// The first pop is not supposed to be evaluated (@see eoPopLoopEval).
_evaluator( current_pop, pop );
// _evaluator( current_pop, pop );
do {
// (1) Selection of the best points in the population
//selected_pop.clear(); // FIXME is it necessary to clear?
_selector(pop, selected_pop);
assert( selected_pop.size() > 0 );
// TODO: utiliser selected_pop ou pop ???
// (2) Estimation of the distribution parameters
distrib = _estimator(selected_pop);
_distrib = _estimator(selected_pop);
// (3) sampling
// The sampler produces feasible solutions (@see edoSampler that
// encapsulate an edoBounder)
current_pop.clear();
for( unsigned int i = 0; i < pop.size(); ++i ) {
current_pop.push_back( _sampler(distrib) );
current_pop.push_back( _sampler(_distrib) );
}
// (4) Evaluate new solutions
@ -161,35 +165,40 @@ public:
// (5) Replace old solutions by new ones
_replacor(pop, current_pop); // e.g. copy current_pop in pop
} while( _distribution_continuator( distrib ) && _pop_continuator( pop ) );
} while( _distribution_continuator( _distrib ) && _pop_continuator( pop ) );
} // operator()
private:
protected:
//! The distribution that you want to update
EOD & _distrib;
//! A full evaluation function.
eoPopEvalFunc < EOT > & _evaluator;
eoPopEvalFunc<EOType> & _evaluator;
//! A EOT selector
eoSelect < EOT > & _selector;
//! A EOType selector
eoSelect<EOType> & _selector;
//! A EOT estimator. It is going to estimate distribution parameters.
edoEstimator< D > & _estimator;
//! A EOType estimator. It is going to estimate distribution parameters.
edoEstimator<EOD> & _estimator;
//! A D sampler
edoSampler< D > & _sampler;
edoSampler<EOD> & _sampler;
//! A EOT replacor
eoReplacement < EOT > & _replacor;
//! A EOType replacor
eoReplacement<EOType> & _replacor;
//! A EOT population continuator
eoContinue < EOT > & _pop_continuator;
//! A EOType population continuator
eoContinue<EOType> & _pop_continuator;
//! A D continuator that always return true
edoDummyContinue<D> _dummy_continue;
edoDummyContinue<EOD> _dummy_continue;
//! A D continuator
edoContinue < D > & _distribution_continuator;
edoContinue<EOD> & _distribution_continuator;
};
#endif // !_edoEDA_h
#endif // !_edoAlgoAdaptive_h

109
edo/src/edoAlgoStateless.h Normal file
View file

@ -0,0 +1,109 @@
/*
The Evolving Distribution Objects framework (EDO) is a template-based,
ANSI-C++ evolutionary computation library which helps you to write your
own estimation of distribution algorithms.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 2010 Thales group
*/
/*
Authors:
Johann Dréo <johann.dreo@thalesgroup.com>
Pierre Savéant <pierre.saveant@thalesgroup.com>
*/
#ifndef _edoAlgoStateless_h
#define _edoAlgoStateless_h
#include "edoAlgoAdaptive.h"
/** A generic stochastic search template for algorithms that need a distribution parameter but replace it rather than update it
*
* This use a default dummy distribution, for algorithms willing to replace it instead of updating
* Thus we can instanciate _distrib on this and replace it at the first iteration with an estimator.
* This is why an edoDistrib must have an empty constructor.
*/
template < typename EOD >
class edoAlgoStateless : public edoAlgoAdaptive< EOD >
{
public:
//! Alias for the type EOT
typedef typename EOD::EOType EOType;
//! Alias for the atom type
typedef typename EOType::AtomType AtomType;
//! Alias for the fitness
typedef typename EOType::Fitness Fitness;
public:
/** Full constructor
\param evaluation Evaluate a population
\param selector Selection of the best candidate solutions in the population
\param estimator Estimation of the distribution parameters
\param sampler Generate feasible solutions using the distribution
\param replacor Replace old solutions by new ones
\param pop_continuator Stopping criterion based on the population features
\param distribution_continuator Stopping criterion based on the distribution features
You are not supposed to override the tmp_distrib default initalization, or else use edoAlgoAdaptive
*/
edoAlgoStateless(
eoPopEvalFunc < EOType > & evaluator,
eoSelect< EOType > & selector,
edoEstimator< EOD > & estimator,
edoSampler< EOD > & sampler,
eoReplacement< EOType > & replacor,
eoContinue< EOType > & pop_continuator,
edoContinue< EOD > & distribution_continuator,
EOD* tmp_distrib = (new EOD())
) :
edoAlgoAdaptive<EOD>( *tmp_distrib, evaluator, selector, estimator, sampler, replacor, pop_continuator, distribution_continuator)
{}
/** Constructor without an edoContinue
\param evaluation Evaluate a population
\param selector Selection of the best candidate solutions in the population
\param estimator Estimation of the distribution parameters
\param sampler Generate feasible solutions using the distribution
\param replacor Replace old solutions by new ones
\param pop_continuator Stopping criterion based on the population features
You are not supposed to override the tmp_distrib default initalization, or else use edoAlgoAdaptive
*/
edoAlgoStateless (
eoPopEvalFunc < EOType > & evaluator,
eoSelect< EOType > & selector,
edoEstimator< EOD > & estimator,
edoSampler< EOD > & sampler,
eoReplacement< EOType > & replacor,
eoContinue< EOType > & pop_continuator,
EOD* tmp_distrib = (new EOD())
) :
edoAlgoAdaptive<EOD>( *tmp_distrib, evaluator, selector, estimator, sampler, replacor, pop_continuator)
{}
~edoAlgoStateless()
{
// delete the temporary distrib allocated in constructors
delete &(this->_distrib);
}
};
#endif // !_edoAlgoStateless_h

View file

@ -46,13 +46,13 @@ class edoEDASA : public edoAlgo< D >
{
public:
//! Alias for the type EOT
typedef typename D::EOType EOT;
typedef typename D::EOType EOType;
//! Alias for the atom type
typedef typename EOT::AtomType AtomType;
typedef typename EOType::AtomType AtomType;
//! Alias for the fitness
typedef typename EOT::Fitness Fitness;
typedef typename EOType::Fitness Fitness;
public:
@ -73,18 +73,18 @@ public:
\param initial_temperature The initial temperature.
\param replacor Population replacor
*/
edoEDASA (eoSelect< EOT > & selector,
edoEDASA (eoSelect< EOType > & selector,
edoEstimator< D > & estimator,
eoSelectOne< EOT > & selectone,
eoSelectOne< EOType > & selectone,
edoModifierMass< D > & modifier,
edoSampler< D > & sampler,
eoContinue< EOT > & pop_continue,
eoContinue< EOType > & pop_continue,
edoContinue< D > & distribution_continue,
eoEvalFunc < EOT > & evaluation,
moContinuator< moDummyNeighbor<EOT> > & sa_continue,
moCoolingSchedule<EOT> & cooling_schedule,
eoEvalFunc < EOType > & evaluation,
moContinuator< moDummyNeighbor<EOType> > & sa_continue,
moCoolingSchedule<EOType> & cooling_schedule,
double initial_temperature,
eoReplacement< EOT > & replacor
eoReplacement< EOType > & replacor
)
: _selector(selector),
_estimator(estimator),
@ -108,15 +108,15 @@ public:
\param pop A population to improve.
\return TRUE.
*/
void operator ()(eoPop< EOT > & pop)
void operator ()(eoPop< EOType > & pop)
{
assert(pop.size() > 0);
double temperature = _initial_temperature;
eoPop< EOT > current_pop;
eoPop< EOType > current_pop;
eoPop< EOT > selected_pop;
eoPop< EOType > selected_pop;
//-------------------------------------------------------------
@ -165,7 +165,7 @@ public:
// Init of a variable contening a point with the bestest fitnesses
//-------------------------------------------------------------
EOT current_solution = _selectone(selected_pop);
EOType current_solution = _selectone(selected_pop);
//-------------------------------------------------------------
@ -200,7 +200,7 @@ public:
do
{
EOT candidate_solution = _sampler(distrib);
EOType candidate_solution = _sampler(distrib);
_evaluation( candidate_solution );
// TODO: verifier le critere d'acceptation
@ -232,14 +232,14 @@ public:
private:
//! A EOT selector
eoSelect < EOT > & _selector;
//! A EOType selector
eoSelect < EOType > & _selector;
//! A EOT estimator. It is going to estimate distribution parameters.
//! A EOType estimator. It is going to estimate distribution parameters.
edoEstimator< D > & _estimator;
//! SelectOne
eoSelectOne< EOT > & _selectone;
eoSelectOne< EOType > & _selectone;
//! A D modifier
edoModifierMass< D > & _modifier;
@ -247,26 +247,26 @@ private:
//! A D sampler
edoSampler< D > & _sampler;
//! A EOT population continuator
eoContinue < EOT > & _pop_continue;
//! A EOType population continuator
eoContinue < EOType > & _pop_continue;
//! A D continuator
edoContinue < D > & _distribution_continue;
//! A full evaluation function.
eoEvalFunc < EOT > & _evaluation;
eoEvalFunc < EOType > & _evaluation;
//! Stopping criterion before temperature update
moContinuator< moDummyNeighbor<EOT> > & _sa_continue;
moContinuator< moDummyNeighbor<EOType> > & _sa_continue;
//! The cooling schedule
moCoolingSchedule<EOT> & _cooling_schedule;
moCoolingSchedule<EOType> & _cooling_schedule;
//! Initial temperature
double _initial_temperature;
//! A EOT replacor
eoReplacement < EOT > & _replacor;
//! A EOType replacor
eoReplacement < EOType > & _replacor;
};
#endif // !_edoEDASA_h

View file

@ -0,0 +1,55 @@
/*
The Evolving Distribution Objects framework (EDO) is a template-based,
ANSI-C++ evolutionary computation library which helps you to write your
own estimation of distribution algorithms.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 2010 Thales group
*/
/*
Authors:
Johann Dréo <johann.dreo@thalesgroup.com>
Pierre Savéant <pierre.saveant@thalesgroup.com>
*/
#ifndef _edoEstimatorAdaptive_h
#define _edoEstimatorAdaptive_h
#include <eoPop.h>
#include <eoFunctor.h>
#include "edoEstimator.h"
/** An interface that explicits the needs for a permanent distribution
* that will be updated by operators.
*/
template < typename EOD >
class edoEstimatorAdaptive : public edoEstimator<EOD>
{
public:
typedef typename EOD::EOType EOType;
edoEstimatorAdaptive<EOD>( EOD& distrib ) : _distrib(distrib) {}
// virtual D operator() ( eoPop< EOT >& )=0 (provided by eoUF< A1, R >)
EOD & distribution() const { return _distrib; }
protected:
EOD & _distrib;
};
#endif // !_edoEstimatorAdaptive_h

View file

@ -0,0 +1,249 @@
/*
The Evolving Distribution Objects framework (EDO) is a template-based,
ANSI-C++ evolutionary computation library which helps you to write your
own estimation of distribution algorithms.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 2010 Thales group
*/
/*
Authors:
Johann Dréo <johann.dreo@thalesgroup.com>
Pierre Savéant <pierre.saveant@thalesgroup.com>
*/
#ifndef _edoEstimatorNormalAdaptive_h
#define _edoEstimatorNormalAdaptive_h
#ifdef WITH_EIGEN
#include <algorithm>
#include<Eigen/Dense>
#include "edoNormalAdaptive.h"
#include "edoEstimatorAdaptive.h"
//! edoEstimatorNormalMulti< EOT >
template< typename EOT, typename EOD = edoNormalAdaptive<EOT> >
class edoEstimatorNormalAdaptive : public edoEstimatorAdaptive< EOD >
{
public:
typedef typename EOT::AtomType AtomType;
typedef typename EOD::Vector Vector; // column vectors @see edoNormalAdaptive
typedef typename EOD::Matrix Matrix;
edoEstimatorNormalAdaptive( EOD& distrib ) :
edoEstimatorAdaptive<EOD>( distrib ),
_calls(0),
_eigeneval(0)
{}
private:
Eigen::VectorXd edoCMAESweights( unsigned int pop_size )
{
// compute recombination weights
Eigen::VectorXd weights( pop_size );
double sum_w = 0;
for( unsigned int i = 0; i < pop_size; ++i ) {
double w_i = log( pop_size + 0.5 ) - log( i + 1 );
weights(i) = w_i;
sum_w += w_i;
}
// normalization of weights
weights /= sum_w;
assert( weights.size() == pop_size);
return weights;
}
public:
void resetCalls()
{
_calls = 0;
}
// update the distribution reference this->distribution()
edoNormalAdaptive<EOT> operator()( eoPop<EOT>& pop )
{
/**********************************************************************
* INITIALIZATION
*********************************************************************/
unsigned int N = pop[0].size(); // FIXME expliciter la dimension du pb ?
unsigned int lambda = pop.size();
// number of calls to the operator == number of generations
_calls++;
// number of "evaluations" until now
unsigned int counteval = _calls * lambda;
// Here, if we are in canonical CMA-ES,
// pop is supposed to be the mu ranked better solutions,
// as the rank mu selection is supposed to have occured.
Matrix arx( N, lambda );
// copy the pop (most probably a vector of vectors) in a Eigen3 matrix
for( unsigned int d = 0; d < N; ++d ) {
for( unsigned int i = 0; i < lambda; ++i ) {
arx(d,i) = pop[i][d]; // NOTE: pop = arx.transpose()
} // dimensions
} // individuals
// muXone array for weighted recombination
Eigen::VectorXd weights = edoCMAESweights( lambda );
assert( weights.size() == lambda );
// FIXME exposer les constantes dans l'interface
// variance-effectiveness of sum w_i x_i
double mueff = pow(weights.sum(), 2) / (weights.array().square()).sum();
// time constant for cumulation for C
double cc = (4+mueff/N) / (N+4 + 2*mueff/N);
// t-const for cumulation for sigma control
double cs = (mueff+2) / (N+mueff+5);
// learning rate for rank-one update of C
double c1 = 2 / (pow(N+1.3,2)+mueff);
// and for rank-mu update
double cmu = 2 * (mueff-2+1/mueff) / ( pow(N+2,2)+mueff);
// damping for sigma
double damps = 1 + 2*std::max(0.0, sqrt((mueff-1)/(N+1))-1) + cs;
// shortcut to the referenced distribution
EOD& d = this->distribution();
// C^-1/2
Matrix invsqrtC =
d.coord_sys() * d.scaling().asDiagonal().inverse()
* d.coord_sys().transpose();
assert( invsqrtC.innerSize() == d.coord_sys().innerSize() );
assert( invsqrtC.outerSize() == d.coord_sys().outerSize() );
// expectation of ||N(0,I)|| == norm(randn(N,1))
double chiN = sqrt(N)*(1-1/(4*N)+1/(21*pow(N,2)));
/**********************************************************************
* WEIGHTED MEAN
*********************************************************************/
// compute weighted mean into xmean
Vector xold = d.mean();
assert( xold.size() == N );
// xmean ( N, 1 ) = arx( N, lambda ) * weights( lambda, 1 )
Vector xmean = arx * weights;
assert( xmean.size() == N );
d.mean( xmean );
/**********************************************************************
* CUMULATION: UPDATE EVOLUTION PATHS
*********************************************************************/
// cumulation for sigma
d.path_sigma(
(1.0-cs)*d.path_sigma() + sqrt(cs*(2.0-cs)*mueff)*invsqrtC*(xmean-xold)/d.sigma()
);
// sign of h
double hsig;
if( d.path_sigma().norm()/sqrt(1.0-pow((1.0-cs),(2.0*counteval/lambda)))/chiN
< 1.4 + 2.0/(N+1.0)
) {
hsig = 1.0;
} else {
hsig = 0.0;
}
// cumulation for the covariance matrix
d.path_covar(
(1.0-cc)*d.path_covar() + hsig*sqrt(cc*(2.0-cc)*mueff)*(xmean-xold) / d.sigma()
);
Matrix xmu( N, lambda);
xmu = xold.rowwise().replicate(lambda);
assert( xmu.innerSize() == N );
assert( xmu.outerSize() == lambda );
Matrix artmp = (1.0/d.sigma()) * (arx - xmu);
// Matrix artmp = (1.0/d.sigma()) * arx - xold.colwise().replicate(lambda);
assert( artmp.innerSize() == N && artmp.outerSize() == lambda );
/**********************************************************************
* COVARIANCE MATRIX ADAPTATION
*********************************************************************/
d.covar(
(1-c1-cmu) * d.covar() // regard old matrix
+ c1 * (d.path_covar()*d.path_covar().transpose() // plus rank one update
+ (1-hsig) * cc*(2-cc) * d.covar()) // minor correction if hsig==0
+ cmu * artmp * weights.asDiagonal() * artmp.transpose() // plus rank mu update
);
// Adapt step size sigma
d.sigma( d.sigma() * exp((cs/damps)*(d.path_sigma().norm()/chiN - 1)) );
/**********************************************************************
* DECOMPOSITION OF THE COVARIANCE MATRIX
*********************************************************************/
// Decomposition of C into B*diag(D.^2)*B' (diagonalization)
if( counteval - _eigeneval > lambda/(c1+cmu)/N/10 ) { // to achieve O(N^2)
_eigeneval = counteval;
// enforce symmetry of the covariance matrix
Matrix C = d.covar();
// FIXME edoEstimatorNormalAdaptive.h:213:44: erreur: expected primary-expression before ) token
// copy the upper part in the lower one
//C.triangularView<Eigen::Lower>() = C.adjoint();
// Matrix CS = C.triangularView<Eigen::Upper>() + C.triangularView<Eigen::StrictlyUpper>().transpose();
d.covar( C );
Eigen::SelfAdjointEigenSolver<Matrix> eigensolver( d.covar() ); // FIXME use JacobiSVD?
d.coord_sys( eigensolver.eigenvectors() );
Matrix D = eigensolver.eigenvalues().asDiagonal();
assert( D.innerSize() == N && D.outerSize() == N );
// from variance to standard deviations
D.cwiseSqrt();
d.scaling( D.diagonal() );
}
return d;
} // operator()
protected:
unsigned int _calls;
unsigned int _eigeneval;
// EOD & distribution() inherited from edoEstimatorAdaptive
};
#endif // WITH_EIGEN
#endif // !_edoEstimatorNormalAdaptive_h

121
edo/src/edoNormalAdaptive.h Normal file
View file

@ -0,0 +1,121 @@
/*
The Evolving Distribution Objects framework (EDO) is a template-based,
ANSI-C++ evolutionary computation library which helps you to write your
own estimation of distribution algorithms.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 2010 Thales group
*/
/*
Authors:
Johann Dreo <johann.dreo@thalesgroup.com>
Pierre Savéant <pierre.saveant@thalesgroup.com>
*/
#ifndef _edoNormalAdaptive_h
#define _edoNormalAdaptive_h
#include "edoDistrib.h"
#ifdef WITH_EIGEN
#include <Eigen/Dense>
template < typename EOT >
class edoNormalAdaptive : public edoDistrib< EOT >
{
public:
//typedef EOT EOType;
typedef typename EOT::AtomType AtomType;
typedef Eigen::Matrix< AtomType, Eigen::Dynamic, 1> Vector; // column vectors ( n lines, 1 column)
typedef Eigen::Matrix< AtomType, Eigen::Dynamic, Eigen::Dynamic> Matrix;
edoNormalAdaptive( unsigned int dim = 1 ) :
_dim(dim),
_mean( Vector::Zero(dim) ),
_C( Matrix::Identity(dim,dim) ),
_B( Matrix::Identity(dim,dim) ),
_D( Vector::Constant( dim, 1) ),
_sigma(1.0),
_p_c( Vector::Zero(dim) ),
_p_s( Vector::Zero(dim) )
{
assert( _dim > 0);
}
edoNormalAdaptive( unsigned int dim,
Vector mean,
Matrix C,
Matrix B,
Vector D,
double sigma,
Vector p_c,
Vector p_s
) :
_mean( mean ),
_C( C ),
_B( B ),
_D( D ),
_sigma(sigma),
_p_c( p_c ),
_p_s( p_s )
{
assert( dim > 0);
assert( _mean.innerSize() == dim );
assert( _C.innerSize() == dim && _C.outerSize() == dim );
assert( _B.innerSize() == dim && _B.outerSize() == dim );
assert( _D.innerSize() == dim );
assert( _sigma != 0.0 );
assert( _p_c.innerSize() == dim );
assert( _p_s.innerSize() == dim );
}
unsigned int size()
{
return _mean.innerSize();
}
Vector mean() const {return _mean;}
Matrix covar() const {return _C;}
Matrix coord_sys() const {return _B;}
Vector scaling() const {return _D;}
double sigma() const {return _sigma;}
Vector path_covar() const {return _p_c;}
Vector path_sigma() const {return _p_s;}
void mean( Vector m ) { _mean = m; assert( m.size() == _dim ); }
void covar( Matrix c ) { _C = c; assert( c.innerSize() == _dim && c.outerSize() == _dim ); }
void coord_sys( Matrix b ) { _B = b; assert( b.innerSize() == _dim && b.outerSize() == _dim ); }
void scaling( Vector d ) { _D = d; assert( d.size() == _dim ); }
void sigma( double s ) { _sigma = s; assert( s != 0.0 );}
void path_covar( Vector p ) { _p_c = p; assert( p.size() == _dim ); }
void path_sigma( Vector p ) { _p_s = p; assert( p.size() == _dim ); }
private:
unsigned int _dim;
Vector _mean; //
Matrix _C; // covariance matrix
Matrix _B; // eigen vectors / coordinates system
Vector _D; // eigen values / scaling
double _sigma; //
Vector _p_c; // evolution path for C
Vector _p_s; // evolution path for sigma
};
#endif // WITH_EIGEN
#endif // !_edoNormalAdaptive_h

View file

@ -45,6 +45,15 @@ class edoNormalMulti : public edoDistrib< EOT >
public:
typedef typename EOT::AtomType AtomType;
edoNormalMulti( unsigned int dim = 1 ) :
_mean( const ublas::vector<AtomType>(0,dim) ),
_varcovar( const ublas::identity_matrix<AtomType>(dim) )
{
assert(_mean.size() > 0);
assert(_mean.size() == _varcovar.size1());
assert(_mean.size() == _varcovar.size2());
}
edoNormalMulti
(
const ublas::vector< AtomType >& mean,
@ -86,6 +95,15 @@ public:
typedef Eigen::Matrix< AtomType, Eigen::Dynamic, 1> Vector;
typedef Eigen::Matrix< AtomType, Eigen::Dynamic, Eigen::Dynamic> Matrix;
edoNormalMulti( unsigned int dim = 1 ) :
_mean( Vector::Zero(dim) ),
_varcovar( Matrix::Identity(dim,dim) )
{
assert(_mean.size() > 0);
assert(_mean.innerSize() == _varcovar.innerSize());
assert(_mean.innerSize() == _varcovar.outerSize());
}
edoNormalMulti(
const Vector & mean,
const Matrix & varcovar

View file

@ -0,0 +1,91 @@
/*
The Evolving Distribution Objects framework (EDO) is a template-based,
ANSI-C++ evolutionary computation library which helps you to write your
own estimation of distribution algorithms.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 2010 Thales group
*/
/*
Authors:
Johann Dréo <johann.dreo@thalesgroup.com>
Pierre Savéant <pierre.saveant@thalesgroup.com>
*/
#ifndef _edoSamplerNormalAdaptive_h
#define _edoSamplerNormalAdaptive_h
#include <cmath>
#include <limits>
#include <edoSampler.h>
/** Sample points in a multi-normal law defined by a mean vector and a covariance matrix.
*
* Given M the mean vector and V the covariance matrix, of order n:
* - draw a vector T in N(0,I) (i.e. each value is drawn in a normal law with mean=0 an stddev=1)
* - compute the Cholesky decomposition L of V (i.e. such as V=LL*)
* - return X = M + LT
*/
#ifdef WITH_EIGEN
template< class EOT, typename EOD = edoNormalAdaptive< EOT > >
class edoSamplerNormalAdaptive : public edoSampler< EOD >
{
public:
typedef typename EOT::AtomType AtomType;
typedef typename EOD::Vector Vector;
typedef typename EOD::Matrix Matrix;
edoSamplerNormalAdaptive( edoRepairer<EOT> & repairer )
: edoSampler< EOD >( repairer)
{}
EOT sample( EOD& distrib )
{
unsigned int N = distrib.size();
assert( N > 0);
// T = vector of size elements drawn in N(0,1)
Vector T( N );
for ( unsigned int i = 0; i < N; ++i ) {
T( i ) = rng.normal();
}
assert(T.innerSize() == N );
assert(T.outerSize() == 1);
// mean(N,1) + sigma * B(N,N) * ( D(N,1) .* T(N,1) )
Vector sol = distrib.mean()
+ distrib.sigma()
* distrib.coord_sys() * (distrib.scaling().cwiseProduct(T) ); // C * T = B * (D .* T)
assert( sol.size() == N );
/*Vector sol = distrib.mean() + distrib.sigma()
* distrib.coord_sys().dot( distrib.scaling().dot( T ) );*/
// copy in the EOT structure (more probably a vector)
EOT solution( N );
for( unsigned int i = 0; i < N; i++ ) {
solution[i]= sol(i);
}
return solution;
}
};
#endif // WITH_EIGEN
#endif // !_edoSamplerNormalAdaptive_h

View file

@ -47,7 +47,7 @@ Authors:
#include <boost/numeric/ublas/lu.hpp>
#include <boost/numeric/ublas/symmetric.hpp>
template< class EOT, typename EOD = edoNormalMulti< EOT > >
template< typename EOT, typename EOD = edoNormalMulti< EOT > >
class edoSamplerNormalMulti : public edoSampler< EOD >
{
public:
@ -91,7 +91,7 @@ protected:
#else
#ifdef WITH_EIGEN
template< class EOT, typename EOD = edoNormalMulti< EOT > >
template< typename EOT, typename EOD = edoNormalMulti< EOT > >
class edoSamplerNormalMulti : public edoSampler< EOD >
{
public:

View file

@ -31,7 +31,7 @@ Authors:
#include<sstream>
#include "edoStat.h"
#include "edoNormalMulti.h"
#include "../edoNormalMulti.h"
#ifdef WITH_BOOST