MPI Multistart: everybody loves comments, except the one who writes them.

This commit is contained in:
Benjamin Bouvier 2012-07-26 16:01:04 +02:00
commit 61c31a4a71
2 changed files with 252 additions and 108 deletions

View file

@ -8,9 +8,24 @@ using namespace eo::mpi;
#include <eo>
#include <es.h>
// Use functions from namespace std
/*
* This file is based on the tutorial lesson 1. We'll consider that you know all the EO
* related parts of the algorithm and we'll focus our attention on parallelization.
*
* This file shows an example of multistart applied to a eoSGA (simple genetic
* algorithm). As individuals need to be serialized, we implement a class inheriting
* from eoReal (which is the base individual), so as to manipulate individuals as they
* were eoReal AND serialize them.
*
* The main function shows how to launch a multistart job, with default functors. If you
* don't know which functors to use, these ones should fit the most of your purposes.
*/
using namespace std;
/*
* eoReal is a vector of double: we just have to serializes the value and the fitness.
*/
class SerializableEOReal: public eoReal<double>, public eoserial::Persistent
{
public:
@ -91,99 +106,48 @@ int main(int argc, char **argv)
const double EPSILON = 0.01; // range for real uniform mutation
const float MUT_RATE = 0.5; // mutation rate
// GENERAL
//////////////////////////
// Random seed
//////////////////////////
//reproducible random seed: if you don't change SEED above,
// you'll aways get the same result, NOT a random run
// rng.reseed(SEED);
// EVAL
/////////////////////////////
// Fitness function
////////////////////////////
// Evaluation: from a plain C++ fn to an EvalFunc Object
eoEvalFuncPtr<Indi> eval( real_value );
// INIT
////////////////////////////////
// Initilisation of population
////////////////////////////////
// declare the population
eoPop<Indi> pop;
// fill it!
/*
for (unsigned int igeno=0; igeno<POP_SIZE; igeno++)
{
Indi v; // void individual, to be filled
for (unsigned ivar=0; ivar<VEC_SIZE; ivar++)
{
double r = 2*rng.uniform() - 1; // new value, random in [-1,1)
v.push_back(r); // append that random value to v
}
eval(v); // evaluate it
pop.push_back(v); // and put it in the population
}
*/
eoUniformGenerator< double > generator;
eoInitFixedLength< Indi > init( VEC_SIZE, generator );
// eoInitAndEval< Indi > init( real_init, eval, continuator );
pop = eoPop<Indi>( POP_SIZE, init );
// ENGINE
/////////////////////////////////////
// selection and replacement
////////////////////////////////////
// SELECT
// The robust tournament selection
eoDetTournamentSelect<Indi> select(T_SIZE); // T_SIZE in [2,POP_SIZE]
// REPLACE
// eoSGA uses generational replacement by default
// so no replacement procedure has to be given
// OPERATORS
//////////////////////////////////////
// The variation operators
//////////////////////////////////////
// CROSSOVER
// offspring(i) is a linear combination of parent(i)
eoDetTournamentSelect<Indi> select(T_SIZE);
eoSegmentCrossover<Indi> xover;
// MUTATION
// offspring(i) uniformly chosen in [parent(i)-epsilon, parent(i)+epsilon]
eoUniformMutation<Indi> mutation(EPSILON);
// STOP
// CHECKPOINT
//////////////////////////////////////
// termination condition
/////////////////////////////////////
// stop after MAX_GEN generations
eoGenContinue<Indi> continuator(MAX_GEN);
/* Does work too with a steady fit continuator. */
// eoSteadyFitContinue< Indi > continuator( 10, 50 );
// GENERATION
/////////////////////////////////////////
// the algorithm
////////////////////////////////////////
// standard Generational GA requires
// selection, evaluation, crossover and mutation, stopping criterion
eoSGA<Indi> gga(select, xover, CROSS_RATE, mutation, MUT_RATE,
eval, continuator);
/* How to assign tasks, which are starts? */
DynamicAssignmentAlgorithm assignmentAlgo;
/* Before a worker starts its algorithm, how does it reinits the population?
* There are a few default usable functors, defined in eoMultiStart.h.
*
* This one (ReuseSamePopEA) doesn't modify the population after a start, so
* the same population is reevaluated on each multistart: the solution tend
* to get better and better.
*/
ReuseSamePopEA< Indi > resetAlgo( continuator, pop, eval );
/**
* How to send seeds to the workers, at the beginning of the parallel job?
* This functors indicates that seeds should be random values.
*/
GetRandomSeeds< Indi > getSeeds( SEED );
// Builds the store
MultiStartStore< Indi > store(
gga,
DEFAULT_MASTER,
resetAlgo,
getSeeds);
// Creates the multistart job and runs it.
// The last argument indicates that we want to launch 5 runs.
MultiStart< Indi > msjob( assignmentAlgo, DEFAULT_MASTER, store, 5 );
msjob.run();
@ -202,5 +166,4 @@ int main(int argc, char **argv)
std::cout << "Global best individual has fitness " << msjob10.best_individuals().best_element().fitness() << std::endl;
}
return 0;
}