From 65191e221259530d45b22fe8939b841a520da146 Mon Sep 17 00:00:00 2001 From: Caner Candan Date: Wed, 22 Sep 2010 14:38:15 +0200 Subject: [PATCH] + eda algo: same algo than eda-sa without sa, + plotting scripts and problem functions moved to application/common --- CMakeLists.txt | 1 + application/CMakeLists.txt | 6 + application/common/CMakeLists.txt | 14 + application/{eda_sa => common}/Rosenbrock.h | 0 application/{eda_sa => common}/Sphere.h | 0 application/{eda_sa => common}/ggobi.py | 0 application/{eda_sa => common}/gplot.py | 0 application/eda/CMakeLists.txt | 27 ++ application/eda/eda.param | 7 + application/eda/main.cpp | 267 ++++++++++++++++++++ application/eda_sa/CMakeLists.txt | 4 +- application/eda_sa/main.cpp | 4 +- src/do | 1 + src/doEDA.h | 252 ++++++++++++++++++ src/doEDASA.h | 24 +- test/CMakeLists.txt | 2 +- 16 files changed, 595 insertions(+), 14 deletions(-) create mode 100644 application/common/CMakeLists.txt rename application/{eda_sa => common}/Rosenbrock.h (100%) rename application/{eda_sa => common}/Sphere.h (100%) rename application/{eda_sa => common}/ggobi.py (100%) rename application/{eda_sa => common}/gplot.py (100%) create mode 100644 application/eda/CMakeLists.txt create mode 100644 application/eda/eda.param create mode 100644 application/eda/main.cpp create mode 100644 src/doEDA.h diff --git a/CMakeLists.txt b/CMakeLists.txt index da9615509..31da2b9c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,6 +83,7 @@ ADD_SUBDIRECTORY(doc) ###################################################################################### + ###################################################################################### ### 7) Create executable, link libraries and prepare target ###################################################################################### diff --git a/application/CMakeLists.txt b/application/CMakeLists.txt index 591fb3035..dabb9ea0f 100644 --- a/application/CMakeLists.txt +++ b/application/CMakeLists.txt @@ -2,6 +2,12 @@ ### 1) Where do we go now ?!? ###################################################################################### +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/common + ) + +ADD_SUBDIRECTORY(common) ADD_SUBDIRECTORY(eda_sa) +ADD_SUBDIRECTORY(eda) ###################################################################################### diff --git a/application/common/CMakeLists.txt b/application/common/CMakeLists.txt new file mode 100644 index 000000000..41a16ecfc --- /dev/null +++ b/application/common/CMakeLists.txt @@ -0,0 +1,14 @@ +PROJECT(common) + +SET(RESOURCES + gplot.py + ggobi.py + ) + +FOREACH(file ${RESOURCES}) + EXECUTE_PROCESS( + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_SOURCE_DIR}/${file} + ${DO_BINARY_DIR}/${file} + ) +ENDFOREACH(file) diff --git a/application/eda_sa/Rosenbrock.h b/application/common/Rosenbrock.h similarity index 100% rename from application/eda_sa/Rosenbrock.h rename to application/common/Rosenbrock.h diff --git a/application/eda_sa/Sphere.h b/application/common/Sphere.h similarity index 100% rename from application/eda_sa/Sphere.h rename to application/common/Sphere.h diff --git a/application/eda_sa/ggobi.py b/application/common/ggobi.py similarity index 100% rename from application/eda_sa/ggobi.py rename to application/common/ggobi.py diff --git a/application/eda_sa/gplot.py b/application/common/gplot.py similarity index 100% rename from application/eda_sa/gplot.py rename to application/common/gplot.py diff --git a/application/eda/CMakeLists.txt b/application/eda/CMakeLists.txt new file mode 100644 index 000000000..41d61ce04 --- /dev/null +++ b/application/eda/CMakeLists.txt @@ -0,0 +1,27 @@ +PROJECT(eda) + +FIND_PACKAGE(Boost 1.33.0) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) +LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) + +SET(RESOURCES + ${PROJECT_NAME}.param + ) + +FOREACH(file ${RESOURCES}) + EXECUTE_PROCESS( + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_CURRENT_SOURCE_DIR}/${file} + ${DO_BINARY_DIR}/${file} + ) +ENDFOREACH(file) + +FILE(GLOB SOURCES *.cpp) + +SET(EXECUTABLE_OUTPUT_PATH ${DO_BINARY_DIR}) + +ADD_EXECUTABLE(${PROJECT_NAME} ${SOURCES}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} do doutils ${EO_LIBRARIES} ${MO_LIBRARIES} ${Boost_LIBRARIES}) diff --git a/application/eda/eda.param b/application/eda/eda.param new file mode 100644 index 000000000..9aceb2306 --- /dev/null +++ b/application/eda/eda.param @@ -0,0 +1,7 @@ +--rho=0 # -p : +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include "Rosenbrock.h" +#include "Sphere.h" + + +typedef eoReal EOT; +typedef doNormalMulti< EOT > Distrib; + + +int main(int ac, char** av) +{ + eoParserLogger parser(ac, av); + + // Letters used by the following declarations: + // a d i p t + + std::string section("Algorithm parameters"); + + // FIXME: default value to check + //double initial_temperature = parser.createParam((double)10e5, "temperature", "Initial temperature", 'i', section).value(); // i + + 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); + + doEstimator< Distrib >* estimator = new doEstimatorNormalMulti< EOT >(); + state.storeFunctor(estimator); + + eoSelectOne< EOT >* selectone = new eoDetTournamentSelect< EOT >( 2 ); + state.storeFunctor(selectone); + + doModifierMass< Distrib >* modifier = new doNormalMultiCenter< EOT >(); + state.storeFunctor(modifier); + + eoEvalFunc< EOT >* plainEval = new Rosenbrock< EOT >(); + state.storeFunctor(plainEval); + + 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); + + 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 ); + state.storeFunctor(init); + + //----------------------------------------------------------------------------- + + + //----------------------------------------------------------------------------- + // (1) Population init and sampler + //----------------------------------------------------------------------------- + + // 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 doUniform). + + eoPop< EOT >& 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 doSampler. + //----------------------------------------------------------------------------- + + doBounder< EOT >* bounder = new doBounderRng< EOT >(EOT(pop[0].size(), -5), + EOT(pop[0].size(), 5), + *gen); + state.storeFunctor(bounder); + + //----------------------------------------------------------------------------- + + + //----------------------------------------------------------------------------- + // Prepare sampler class with a specific distribution + //----------------------------------------------------------------------------- + + doSampler< Distrib >* sampler = new doSamplerNormalMulti< EOT >( *bounder ); + state.storeFunctor(sampler); + + //----------------------------------------------------------------------------- + + + //----------------------------------------------------------------------------- + // Metropolis sample parameters + //----------------------------------------------------------------------------- + + //unsigned int popSize = parser.getORcreateParam((unsigned int)20, "popSize", "Population Size", 'P', "Evolution Engine").value(); + + //moContinuator< moDummyNeighbor >* sa_continue = new moIterContinuator< moDummyNeighbor >( popSize ); + //state.storeFunctor(sa_continue); + + //----------------------------------------------------------------------------- + + + //----------------------------------------------------------------------------- + // SA parameters + //----------------------------------------------------------------------------- + + //double threshold_temperature = parser.createParam((double)0.1, "threshold", "Minimal temperature at which stop", 't', section).value(); // t + //double alpha = parser.createParam((double)0.1, "alpha", "Temperature decrease rate", 'a', section).value(); // a + + //moCoolingSchedule* cooling_schedule = new moSimpleCoolingSchedule(initial_temperature, alpha, 0, threshold_temperature); + //state.storeFunctor(cooling_schedule); + + //----------------------------------------------------------------------------- + + + //----------------------------------------------------------------------------- + // stopping criteria + // ... and creates the parameter letters: C E g G s T + //----------------------------------------------------------------------------- + + eoContinue< EOT >& eo_continue = do_make_continue(parser, state, eval); + + //----------------------------------------------------------------------------- + + + //----------------------------------------------------------------------------- + // population output + //----------------------------------------------------------------------------- + + eoCheckPoint< EOT >& pop_continue = do_make_checkpoint(parser, state, eval, eo_continue); + + doPopStat< EOT >* popStat = new doPopStat; + state.storeFunctor(popStat); + pop_continue.add(*popStat); + + doFileSnapshot* fileSnapshot = new doFileSnapshot("EDA_ResPop"); + state.storeFunctor(fileSnapshot); + fileSnapshot->add(*popStat); + pop_continue.add(*fileSnapshot); + + //----------------------------------------------------------------------------- + + + //----------------------------------------------------------------------------- + // distribution output + //----------------------------------------------------------------------------- + + doDummyContinue< Distrib >* dummy_continue = new doDummyContinue< Distrib >(); + state.storeFunctor(dummy_continue); + + doCheckPoint< Distrib >* distribution_continue = new doCheckPoint< Distrib >( *dummy_continue ); + state.storeFunctor(distribution_continue); + + doDistribStat< Distrib >* distrib_stat = new doStatNormalMulti< 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 ); + + //----------------------------------------------------------------------------- + + + //----------------------------------------------------------------------------- + // eoEPRemplacement causes the using of the current and previous + // sample for sampling. + //----------------------------------------------------------------------------- + + eoReplacement< EOT >* replacor = new eoEPReplacement< EOT >(pop.size()); + + // Below, use eoGenerationalReplacement to sample only on the current sample + + //eoReplacement< EOT >* replacor = new eoGenerationalReplacement< EOT >(); // FIXME: to define the size + + state.storeFunctor(replacor); + + //----------------------------------------------------------------------------- + + + //----------------------------------------------------------------------------- + // EDA algorithm configuration + //----------------------------------------------------------------------------- + + doAlgo< Distrib >* algo = new doEDA< Distrib > + (*selector, *estimator, *selectone, *modifier, *sampler, + pop_continue, *distribution_continue, + eval, + //*sa_continue, *cooling_schedule, initial_temperature, + *replacor); + + //----------------------------------------------------------------------------- + + + // state.storeFunctor(algo); + + if (parser.userNeedsHelp()) + { + parser.printHelp(std::cout); + exit(1); + } + + // Help + Verbose routines + + make_verbose(parser); + make_help(parser); + + + //----------------------------------------------------------------------------- + // Beginning of the algorithm call + //----------------------------------------------------------------------------- + + try + { + do_run(*algo, pop); + } + catch (eoEvalFuncCounterBounderException& e) + { + eo::log << eo::warnings << "warning: " << e.what() << std::endl; + } + catch (std::exception& e) + { + eo::log << eo::errors << "error: " << e.what() << std::endl; + exit(EXIT_FAILURE); + } + + //----------------------------------------------------------------------------- + + return 0; +} diff --git a/application/eda_sa/CMakeLists.txt b/application/eda_sa/CMakeLists.txt index 63901a33a..f92e105f2 100644 --- a/application/eda_sa/CMakeLists.txt +++ b/application/eda_sa/CMakeLists.txt @@ -8,9 +8,7 @@ INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) SET(RESOURCES - eda_sa.param - gplot.py - ggobi.py + ${PROJECT_NAME}.param ) FOREACH(file ${RESOURCES}) diff --git a/application/eda_sa/main.cpp b/application/eda_sa/main.cpp index 00cbea6f2..6e4729de3 100644 --- a/application/eda_sa/main.cpp +++ b/application/eda_sa/main.cpp @@ -163,7 +163,7 @@ int main(int ac, char** av) state.storeFunctor(popStat); pop_continue.add(*popStat); - doFileSnapshot* fileSnapshot = new doFileSnapshot("ResPop"); + doFileSnapshot* fileSnapshot = new doFileSnapshot("EDASA_ResPop"); state.storeFunctor(fileSnapshot); fileSnapshot->add(*popStat); pop_continue.add(*fileSnapshot); @@ -191,7 +191,7 @@ int main(int ac, char** av) // stdout_monitor->add(*distrib_stat); // distribution_continue->add( *stdout_monitor ); - eoFileMonitor* file_monitor = new eoFileMonitor("distribution_bounds.txt"); + eoFileMonitor* file_monitor = new eoFileMonitor("eda_sa_distribution_bounds.txt"); state.storeFunctor(file_monitor); file_monitor->add(*distrib_stat); distribution_continue->add( *file_monitor ); diff --git a/src/do b/src/do index 1f91d3923..ff2b3e674 100644 --- a/src/do +++ b/src/do @@ -10,6 +10,7 @@ #include "doAlgo.h" #include "doEDASA.h" +#include "doEDA.h" #include "doDistrib.h" #include "doUniform.h" diff --git a/src/doEDA.h b/src/doEDA.h new file mode 100644 index 000000000..6873e5da4 --- /dev/null +++ b/src/doEDA.h @@ -0,0 +1,252 @@ +// (c) Thales group, 2010 +/* + Authors: + Johann Dreo + Caner Candan +*/ + +#ifndef _doEDA_h +#define _doEDA_h + +#include +#include + +#include + +#include "doAlgo.h" +#include "doEstimator.h" +#include "doModifierMass.h" +#include "doSampler.h" +#include "doContinue.h" + +template < typename D > +class doEDA : public doAlgo< D > +{ +public: + //! Alias for the type EOT + typedef typename D::EOType EOT; + + //! Alias for the atom type + typedef typename EOT::AtomType AtomType; + + //! Alias for the fitness + typedef typename EOT::Fitness Fitness; + +public: + + //! doEDA constructor + /*! + All the boxes used by a EDASA need to be given. + + \param selector Population Selector + \param estimator Distribution Estimator + \param selectone SelectOne + \param modifier Distribution Modifier + \param sampler Distribution Sampler + \param pop_continue Population Continuator + \param distribution_continue Distribution Continuator + \param evaluation Evaluation function. + \param sa_continue Stopping criterion. + \param cooling_schedule Cooling schedule, describes how the temperature is modified. + \param initial_temperature The initial temperature. + \param replacor Population replacor + */ + doEDA (eoSelect< EOT > & selector, + doEstimator< D > & estimator, + eoSelectOne< EOT > & selectone, + doModifierMass< D > & modifier, + doSampler< D > & sampler, + eoContinue< EOT > & pop_continue, + doContinue< D > & distribution_continue, + eoEvalFunc < EOT > & evaluation, + //moContinuator< moDummyNeighbor > & sa_continue, + //moCoolingSchedule & cooling_schedule, + //double initial_temperature, + eoReplacement< EOT > & replacor + ) + : _selector(selector), + _estimator(estimator), + _selectone(selectone), + _modifier(modifier), + _sampler(sampler), + _pop_continue(pop_continue), + _distribution_continue(distribution_continue), + _evaluation(evaluation), + //_sa_continue(sa_continue), + //_cooling_schedule(cooling_schedule), + //_initial_temperature(initial_temperature), + _replacor(replacor) + + {} + + //! function that launches the EDASA algorithm. + /*! + As a moTS or a moHC, the EDASA can be used for HYBRIDATION in an evolutionary algorithm. + + \param pop A population to improve. + \return TRUE. + */ + void operator ()(eoPop< EOT > & pop) + { + assert(pop.size() > 0); + + //double temperature = _initial_temperature; + + eoPop< EOT > current_pop; + + eoPop< EOT > selected_pop; + + + //------------------------------------------------------------- + // Estimating a first time the distribution parameter thanks + // to population. + //------------------------------------------------------------- + + D distrib = _estimator(pop); + + double size = distrib.size(); + assert(size > 0); + + //------------------------------------------------------------- + + + do + { + //------------------------------------------------------------- + // (3) Selection of the best points in the population + //------------------------------------------------------------- + + selected_pop.clear(); + + _selector(pop, selected_pop); + + assert( selected_pop.size() > 0 ); + + //------------------------------------------------------------- + + + //------------------------------------------------------------- + // (4) Estimation of the distribution parameters + //------------------------------------------------------------- + + distrib = _estimator(selected_pop); + + //------------------------------------------------------------- + + + // TODO: utiliser selected_pop ou pop ??? + + assert(selected_pop.size() > 0); + + + //------------------------------------------------------------- + // Init of a variable contening a point with the bestest fitnesses + //------------------------------------------------------------- + + EOT current_solution = _selectone(selected_pop); + + //------------------------------------------------------------- + + + //------------------------------------------------------------- + // Fit the current solution with the distribution parameters (bounds) + //------------------------------------------------------------- + + // FIXME: si besoin de modifier la dispersion de la distribution + // _modifier_dispersion(distribution, selected_pop); + _modifier(distrib, current_solution); + + //------------------------------------------------------------- + + + //------------------------------------------------------------- + // Evaluating a first time the current solution + //------------------------------------------------------------- + + _evaluation( current_solution ); + + //------------------------------------------------------------- + + + //------------------------------------------------------------- + // Building of the sampler in current_pop + //------------------------------------------------------------- + + //_sa_continue.init( current_solution ); + + current_pop.clear(); + + for ( unsigned int i = 0; i < pop.size(); ++i ) + //do + { + EOT candidate_solution = _sampler(distrib); + _evaluation( candidate_solution ); + + // TODO: verifier le critere d'acceptation + if ( candidate_solution.fitness() < current_solution.fitness() + // || rng.uniform() < exp( ::fabs(candidate_solution.fitness() - current_solution.fitness()) / temperature ) + ) + { + current_pop.push_back(candidate_solution); + current_solution = candidate_solution; + } + } + //while ( _sa_continue( current_solution) ); + + //------------------------------------------------------------- + + + _replacor(pop, current_pop); // copy current_pop in pop + + pop.sort(); + + //if ( ! _cooling_schedule( temperature ) ){ eo::log << eo::debug << "_cooling_schedule" << std::endl; break; } + + if ( ! _distribution_continue( distrib ) ){ eo::log << eo::debug << "_distribution_continue" << std::endl; break; } + + if ( ! _pop_continue( pop ) ){ eo::log << eo::debug << "_pop_continue" << std::endl; break; } + + } + while ( 1 ); + } + +private: + + //! A EOT selector + eoSelect < EOT > & _selector; + + //! A EOT estimator. It is going to estimate distribution parameters. + doEstimator< D > & _estimator; + + //! SelectOne + eoSelectOne< EOT > & _selectone; + + //! A D modifier + doModifierMass< D > & _modifier; + + //! A D sampler + doSampler< D > & _sampler; + + //! A EOT population continuator + eoContinue < EOT > & _pop_continue; + + //! A D continuator + doContinue < D > & _distribution_continue; + + //! A full evaluation function. + eoEvalFunc < EOT > & _evaluation; + + //! Stopping criterion before temperature update + //moContinuator< moDummyNeighbor > & _sa_continue; + + //! The cooling schedule + //moCoolingSchedule & _cooling_schedule; + + //! Initial temperature + //double _initial_temperature; + + //! A EOT replacor + eoReplacement < EOT > & _replacor; +}; + +#endif // !_doEDA_h diff --git a/src/doEDASA.h b/src/doEDASA.h index c8e9ad9a9..c6fb4927d 100644 --- a/src/doEDASA.h +++ b/src/doEDASA.h @@ -159,6 +159,15 @@ public: //------------------------------------------------------------- + //------------------------------------------------------------- + // Evaluating a first time the current solution + //------------------------------------------------------------- + + _evaluation( current_solution ); + + //------------------------------------------------------------- + + //------------------------------------------------------------- // Building of the sampler in current_pop //------------------------------------------------------------- @@ -170,21 +179,20 @@ public: do { EOT candidate_solution = _sampler(distrib); - - EOT& e1 = candidate_solution; - _evaluation( e1 ); - EOT& e2 = current_solution; - _evaluation( e2 ); + _evaluation( candidate_solution ); // TODO: verifier le critere d'acceptation - if ( e1.fitness() < e2.fitness() || - rng.uniform() < exp( ::fabs(e1.fitness() - e2.fitness()) / temperature ) ) + if ( candidate_solution.fitness() < current_solution.fitness() || + rng.uniform() < exp( ::fabs(candidate_solution.fitness() - current_solution.fitness()) / temperature ) ) { current_pop.push_back(candidate_solution); current_solution = candidate_solution; } } - while ( _sa_continue( current_solution) ); + while ( _sa_continue( current_solution ) ); + + //------------------------------------------------------------- + _replacor(pop, current_pop); // copy current_pop in pop diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 80651e533..dbb444816 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -30,7 +30,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/application/eda_sa) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/application/common) SET(SOURCES t-doEstimatorNormalMulti