Changed the names of the exercise files to exerciseN.p - N lesson nb, p exercise nb

This commit is contained in:
evomarc 2001-01-05 05:48:16 +00:00
commit b1fa5076e2
3 changed files with 11 additions and 8 deletions

View file

@ -0,0 +1,165 @@
#include <stdexcept> // runtime_error
//-----------------------------------------------------------------------------
// FirstBitGA.cpp
//-----------------------------------------------------------------------------
//*
// An instance of a VERY simple Bitstring Genetic Algorithm
//
//-----------------------------------------------------------------------------
// standard includes
#include <iostream> // cout
#include <strstream> // ostrstream, istrstream
// the general include for eo
#include <eo>
//-----------------------------------------------------------------------------
// define your individuals
typedef eoBin<double> Indi; // A bitstring with fitness double
//-----------------------------------------------------------------------------
/** a simple fitness function that computes the number of ones of a bitstring
@param _indi A biststring individual
*/
double binary_value(const Indi & _indi)
{
double sum = 0;
for (unsigned i = 0; i < _indi.size(); i++)
sum += _indi[i];
return sum;
}
//-----------------------------------------------------------------------------
void main_function(int argc, char **argv)
{
const unsigned int SEED = 42; // seed for random number generator
const unsigned int VEC_SIZE = 8; // Number of bits in genotypes
const unsigned int POP_SIZE = 20; // Size of population
const unsigned int MAX_GEN = 500; // Maximum number of generation before STOP
const float CROSS_RATE = 0.8; // Crossover rate
const double P_MUT_PER_BIT = 0.01; // probability of bit-flip mutation
const float MUT_RATE = 1.0; // mutation rate
//////////////////////////
// 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);
/////////////////////////////
// Fitness function
////////////////////////////
// Evaluation: from a plain C++ fn to an EvalFunc Object
eoEvalFuncPtr<Indi> eval( binary_value );
////////////////////////////////
// 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++)
{
bool r = rng.flip(); // new value, random in {0,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
}
// sort pop before printing it!
pop.sort();
// Print (sorted) intial population (raw printout)
cout << "Initial Population" << endl;
cout << pop;
/////////////////////////////////////
// selection and replacement
////////////////////////////////////
// solution solution solution: uncomment one of the following,
// comment out the eoDetTournament lines
// The well-known roulette
// eoProportionalSelect<Indi> select;
// could also use stochastic binary tournament selection
//
// const double RATE = 0.75;
// eoStochTournamentSelect<Indi> select(RATE); // RATE in ]0.5,1]
// The robust tournament selection
const unsigned int T_SIZE = 3; // size for tournament selection
eoDetTournamentSelect<Indi> select(T_SIZE); // T_SIZE in [2,POP_SIZE]
// and of course the random selection
// eoRandomSelect<Indi> select;
// The simple GA evolution engine uses generational replacement
// so no replacement procedure is needed
//////////////////////////////////////
// termination condition
/////////////////////////////////////
// stop after MAX_GEN generations
eoGenContinue<Indi> continuator(MAX_GEN);
//////////////////////////////////////
// The variation operators
//////////////////////////////////////
// standard bit-flip mutation for bitstring
eoBinMutation<Indi> mutation(P_MUT_PER_BIT);
// 1-point mutation for bitstring
eoBinCrossover<Indi> xover;
/////////////////////////////////////////
// the algorithm
////////////////////////////////////////
// standard Generational GA requires as parameters
// selection, evaluation, crossover and mutation, stopping criterion
eoSGA<Indi> gga(select, xover, CROSS_RATE, mutation, MUT_RATE,
eval, continuator);
// Apply algo to pop - that's it!
gga(pop);
// Print (sorted) intial population
pop.sort();
cout << "FINAL Population\n" << pop << endl;
}
// A main that catches the exceptions
int main(int argc, char **argv)
{
#ifdef _MSC_VER
// rng.reseed(42);
int flag = _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
flag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag(flag);
// _CrtSetBreakAlloc(100);
#endif
try
{
main_function(argc, argv);
}
catch(exception& e)
{
cout << "Exception: " << e.what() << '\n';
}
return 1;
}

View file

@ -0,0 +1,198 @@
//-----------------------------------------------------------------------------
// FirstBitEA.cpp
//-----------------------------------------------------------------------------
//*
// Still an instance of a VERY simple Bitstring Genetic Algorithm
// (see FirstBitGA.cpp) but now with Breeder - and Combined Ops
//
//-----------------------------------------------------------------------------
// standard includes
#include <stdexcept> // runtime_error
#include <iostream> // cout
#include <strstream> // ostrstream, istrstream
// the general include for eo
#include <eo>
// REPRESENTATION
//-----------------------------------------------------------------------------
// define your individuals
typedef eoBin<double> Indi; // A bitstring with fitness double
// EVAL
//-----------------------------------------------------------------------------
// a simple fitness function that computes the number of ones of a bitstring
// Now in a separate file, and declared as binary_value(const vector<bool> &)
#include "binary_value.h"
// GENERAL
//-----------------------------------------------------------------------------
void main_function(int argc, char **argv)
{
// PARAMETRES
const unsigned int SEED = 42; // seed for random number generator
const unsigned int T_SIZE = 3; // size for tournament selection
const unsigned int VEC_SIZE = 20; // Number of bits in genotypes
const unsigned int POP_SIZE = 20; // Size of population
const unsigned int MAX_GEN = 500; // Maximum number of generation before STOP
const unsigned int MIN_GEN = 10; // Minimum number of generation before ...
const unsigned int STEADY_GEN = 50; // stop after STEADY_GEN gen. without improvelent
const double P_CROSS = 0.8; // Crossover probability
const double P_MUT = 1.0; // mutation probability
const double P_MUT_PER_BIT = 0.01; // internal probability for bit-flip mutation
// some parameters for chosing among different operators
const double onePointRate = 0.5; // rate for 1-pt Xover
const double twoPointsRate = 0.5; // rate for 2-pt Xover
const double URate = 0.5; // rate for Uniform Xover
const double bitFlipRate = 0.5; // rate for bit-flip mutation
const double oneBitRate = 0.5; // rate for one-bit mutation
// 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
// you need to give the full description of the function
eoEvalFuncPtr<Indi, double, const vector<bool>& > eval( binary_value );
// INIT
////////////////////////////////
// Initilisation of population
////////////////////////////////
// based on boolean_generator class (see utils/rnd_generator.h)
eoInitFixedLength<Indi, boolean_generator>
random(VEC_SIZE, boolean_generator());
// Initialization of the population
eoPop<Indi> pop(POP_SIZE, random);
// and evaluate it in one loop
apply<Indi>(eval, pop); // STL syntax
// OUTPUT
// sort pop before printing it!
pop.sort();
// Print (sorted) intial population (raw printout)
cout << "Initial Population" << endl;
cout << pop;
// ENGINE
/////////////////////////////////////
// selection and replacement
////////////////////////////////////
// SELECT
// The robust tournament selection
eoDetTournamentSelect<Indi> selectOne(T_SIZE); // T_SIZE in [2,POP_SIZE]
// solution solution solution solution solution solution solution
// modify the nb offspring / rate in the constructor. 2 ways:
// second arg treated as integer
eoSelectMany<Indi> select(selectOne,2, eo_is_an_integer);
// second arg treated as a rate (default behavior)
// eoSelectMany<Indi> select(selectOne,0.1);
// REPLACE
// solution solution solution solution solution solution solution
// eoCommaReplacement keeps the best among offspring
// eoPlusReplacement keeps the best among parents + offspring
// eoCommaReplacement<Indi> replace;
eoPlusReplacement<Indi> replace;
// OPERATORS
//////////////////////////////////////
// The variation operators
//////////////////////////////////////
// CROSSOVER
// 1-point crossover for bitstring
eoBinCrossover<Indi> xover1;
// uniform crossover for bitstring
eoBinUxOver<Indi> xoverU;
// 2-pots xover
eoBinNxOver<Indi> xover2(2);
// Combine them with relative rates
eoPropCombinedQuadOp<Indi> xover(xover1, onePointRate);
xover.add(xoverU, URate);
xover.add(xover2, twoPointsRate, true);
// MUTATION
// standard bit-flip mutation for bitstring
eoBinMutation<Indi> mutationBitFlip(P_MUT_PER_BIT);
// mutate exactly 1 bit per individual
eoDetBitFlip<Indi> mutationOneBit;
// Combine them with relative rates
eoPropCombinedMonOp<Indi> mutation(mutationBitFlip, bitFlipRate);
mutation.add(mutationOneBit, oneBitRate, true);
// The operators are encapsulated into an eoTRansform object
eoSGATransform<Indi> transform(xover, P_CROSS, mutation, P_MUT);
// STOP
// CHECKPOINT
//////////////////////////////////////
// termination conditions: use more than one
/////////////////////////////////////
// stop after MAX_GEN generations
eoGenContinue<Indi> genCont(MAX_GEN);
// do MIN_GEN gen., then stop after STEADY_GEN gen. without improvement
eoSteadyFitContinue<Indi> steadyCont(MIN_GEN, STEADY_GEN);
// stop when fitness reaches a target (here VEC_SIZE)
eoFitContinue<Indi> fitCont(VEC_SIZE);
// do stop when one of the above says so
eoCombinedContinue<Indi> continuator(genCont);
continuator.add(steadyCont);
continuator.add(fitCont);
// GENERATION
/////////////////////////////////////////
// the algorithm
////////////////////////////////////////
// Easy EA requires
// selection, transformation, eval, replacement, and stopping criterion
eoEasyEA<Indi> gga(continuator, eval, select, transform, replace);
// Apply algo to pop - that's it!
gga(pop);
// OUTPUT
// Print (sorted) intial population
pop.sort();
cout << "FINAL Population\n" << pop << endl;
// GENERAL
}
// A main that catches the exceptions
int main(int argc, char **argv)
{
#ifdef _MSC_VER
// rng.reseed(42);
int flag = _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
flag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag(flag);
// _CrtSetBreakAlloc(100);
#endif
try
{
main_function(argc, argv);
}
catch(exception& e)
{
cout << "Exception: " << e.what() << '\n';
}
return 1;
}

View file

@ -0,0 +1,361 @@
//-----------------------------------------------------------------------------
// SecondBitGA.cpp
//-----------------------------------------------------------------------------
//*
// Same code than FirstBitEA as far as Evolutionary Computation is concerned
// but now you learn to enter the parameters in a more flexible way
// and to twidle the output to your preferences!
//-----------------------------------------------------------------------------
// standard includes
#include <stdexcept> // runtime_error
#include <iostream> // cout
#include <strstream> // ostrstream, istrstream
#include <fstream>
// the general include for eo
#include <eo>
#include <utils/eoGnuplot1DMonitor.h>
// EVAL
#include "binary_value.h"
// REPRESENTATION
//-----------------------------------------------------------------------------
// define your genotype and fitness types
typedef eoBin<double> Indi;
// the main_function: nothing changed(!), except variable initialization
void main_function(int argc, char **argv)
{
// PARAMETRES
//-----------------------------------------------------------------------------
// instead of having all values of useful parameters as constants, read them:
// either on the command line (--option=value or -o=value)
// or in a parameter file (same syntax, order independent,
// # = usual comment character
// or in the environment (TODO)
// First define a parser from the command-line arguments
eoParser parser(argc, argv);
// For each parameter, define Parameter, read it through the parser,
// and assign the value to the variable
eoValueParam<uint32> seedParam(time(0), "seed", "Random number seed", 'S');
parser.processParam( seedParam );
unsigned seed = seedParam.value();
// description of genotype
eoValueParam<unsigned int> vecSizeParam(8, "vecSize", "Genotype size",'V');
parser.processParam( vecSizeParam, "Representation" );
unsigned vecSize = vecSizeParam.value();
// parameters for evolution engine
eoValueParam<unsigned int> popSizeParam(10, "popSize", "Population size",'P');
parser.processParam( popSizeParam, "Evolution engine" );
unsigned popSize = popSizeParam.value();
eoValueParam<unsigned int> tSizeParam(10, "tSize", "Tournament size",'T');
parser.processParam( tSizeParam, "Evolution Engine" );
unsigned tSize = tSizeParam.value();
// init and stop
eoValueParam<string> loadNameParam("", "Load","A save file to restart from",'L');
parser.processParam( loadNameParam, "Persistence" );
string loadName = loadNameParam.value();
eoValueParam<unsigned int> maxGenParam(100, "maxGen", "Maximum number of generations",'G');
parser.processParam( maxGenParam, "Stopping criterion" );
unsigned maxGen = maxGenParam.value();
eoValueParam<unsigned int> minGenParam(100, "minGen", "Minimum number of generations",'g');
parser.processParam( minGenParam, "Stopping criterion" );
unsigned minGen = minGenParam.value();
eoValueParam<unsigned int> steadyGenParam(100, "steadyGen", "Number of generations with no improvement",'s');
parser.processParam( steadyGenParam, "Stopping criterion" );
unsigned steadyGen = steadyGenParam.value();
// operators probabilities at the algorithm level
eoValueParam<double> pCrossParam(0.6, "pCross", "Probability of Crossover", 'C');
parser.processParam( pCrossParam, "Genetic Operators" );
double pCross = pCrossParam.value();
eoValueParam<double> pMutParam(0.1, "pMut", "Probability of Mutation", 'M');
parser.processParam( pMutParam, "Genetic Operators" );
double pMut = pMutParam.value();
// relative rates for crossovers
eoValueParam<double> onePointRateParam(1, "onePointRate", "Relative rate for one point crossover", '1');
parser.processParam( onePointRateParam, "Genetic Operators" );
double onePointRate = onePointRateParam.value();
eoValueParam<double> twoPointsRateParam(1, "twoPointRate", "Relative rate for two point crossover", '2');
parser.processParam( twoPointsRateParam, "Genetic Operators" );
double twoPointsRate = twoPointsRateParam.value();
eoValueParam<double> uRateParam(2, "uRate", "Relative rate for uniform crossover", 'U');
parser.processParam( uRateParam, "Genetic Operators" );
double URate = uRateParam.value();
// relative rates and private parameters for mutations;
eoValueParam<double> pMutPerBitParam(0.01, "pMutPerBit", "Probability of flipping 1 bit in bit-flip mutation", 'b');
parser.processParam( pMutPerBitParam, "Genetic Operators" );
double pMutPerBit = pMutPerBitParam.value();
eoValueParam<double> bitFlipRateParam(0.01, "bitFlipRate", "Relative rate for bit-flip mutation", 'B');
parser.processParam( bitFlipRateParam, "Genetic Operators" );
double bitFlipRate = bitFlipRateParam.value();
eoValueParam<double> oneBitRateParam(0.01, "oneBitRate", "Relative rate for deterministic bit-flip mutation", 'D');
parser.processParam( oneBitRateParam, "Genetic Operators" );
double oneBitRate = oneBitRateParam.value();
// the name of the "status" file where all actual parameter values will be saved
string str_status = parser.ProgramName() + ".status"; // default value
eoValueParam<string> statusParam(str_status.c_str(), "status","Status file",'S');
parser.processParam( statusParam, "Persistence" );
// do the following AFTER ALL PARAMETERS HAVE BEEN PROCESSED
// i.e. in case you need parameters somewhere else, postpone these
if (parser.userNeedsHelp())
{
parser.printHelp(cout);
exit(1);
}
if (statusParam.value() != "")
{
ofstream os(statusParam.value().c_str());
os << parser; // and you can use that file as parameter file
}
// EVAL
/////////////////////////////
// Fitness function
////////////////////////////
// Evaluation: from a plain C++ fn to an EvalFunc Object ...
eoEvalFuncPtr<Indi, double, const vector<bool>& > plainEval( binary_value );
// ... to an object that counts the nb of actual evaluations
eoEvalFuncCounter<Indi> eval(plainEval);
// INIT
////////////////////////////////
// Initilisation of population
////////////////////////////////
// Either load or initialize
// create an empty pop
eoPop<Indi> pop;
// create a state for reading
eoState inState; // a state for loading - WITHOUT the parser
// register the rng and the pop in the state, so they can be loaded,
// and the present run will be the exact conitnuation of the saved run
// eventually with different parameters
inState.registerObject(rng);
inState.registerObject(pop);
if (loadName != "")
{
inState.load(loadName); // load the pop and the rng
// the fitness is read in the file:
// do only evaluate the pop if the fitness has changed
}
else
{
rng.reseed(seed);
// a Indi random initializer
// based on boolean_generator class (see utils/rnd_generator.h)
eoInitFixedLength<Indi, boolean_generator>
random(vecSize, boolean_generator());
// Init pop from the randomizer: need to use the append function
pop.append(popSize, random);
// and evaluate pop (STL syntax)
apply<Indi>(eval, pop);
} // end of initializatio of the population
// OUTPUT
// sort pop for pretty printout
// pop.sort();
// Print (sorted) intial population (raw printout)
cout << "Initial Population" << endl << pop ;
cout << "and best is " << pop.best_element() << "\n\n";
cout << "and worse is " << pop.worse_element() << "\n\n";
// ENGINE
/////////////////////////////////////
// selection and replacement
////////////////////////////////////
// SELECT
// The robust tournament selection
eoDetTournamentSelect<Indi> selectOne(tSize); // tSize in [2,POPSIZE]
// is now encapsulated in a eoSelectPerc (entage)
eoSelectPerc<Indi> select(selectOne);// by default rate==1
// REPLACE
// And we now have the full slection/replacement - though with
// generational replacement at the moment :-)
eoGenerationalReplacement<Indi> replace;
// want to add (weak) elitism? easy!
// rename the eoGenerationalReplacement replace_main,
// then encapsulate it in the elitist replacement
// eoWeakElitistReplacement<Indi> replace(replace_main);
// OPERATORS
//////////////////////////////////////
// The variation operators
//////////////////////////////////////
// CROSSOVER
// 1-point crossover for bitstring
eoBinCrossover<Indi> xover1;
// uniform crossover for bitstring
eoBinUxOver<Indi> xoverU;
// 2-pots xover
eoBinNxOver<Indi> xover2(2);
// Combine them with relative rates
eoPropCombinedQuadOp<Indi> xover(xover1, onePointRate);
xover.add(xoverU, URate);
xover.add(xover2, twoPointsRate, true);
// MUTATION
// standard bit-flip mutation for bitstring
eoBinMutation<Indi> mutationBitFlip(pMutPerBit);
// mutate exactly 1 bit per individual
eoDetBitFlip<Indi> mutationOneBit;
// Combine them with relative rates
eoPropCombinedMonOp<Indi> mutation(mutationBitFlip, bitFlipRate);
mutation.add(mutationOneBit, oneBitRate, true);
// The operators are encapsulated into an eoTRansform object
eoSGATransform<Indi> transform(xover, pCross, mutation, pMut);
// STOP
//////////////////////////////////////
// termination condition see FirstBitEA.cpp
/////////////////////////////////////
eoGenContinue<Indi> genCont(maxGen);
eoSteadyFitContinue<Indi> steadyCont(minGen, steadyGen);
eoFitContinue<Indi> fitCont(vecSize);
eoCombinedContinue<Indi> continuator(genCont);
continuator.add(steadyCont);
continuator.add(fitCont);
// CHECKPOINT
// but now you want to make many different things every generation
// (e.g. statistics, plots, ...).
// the class eoCheckPoint is dedicated to just that:
// Declare a checkpoint (from a continuator: an eoCheckPoint
// IS AN eoContinue and will be called in the loop of all algorithms)
eoCheckPoint<Indi> checkpoint(continuator);
// Create a counter parameter
eoValueParam<unsigned> generationCounter(0, "Gen.");
// Create an incrementor (sub-class of eoUpdater). Note that the
// parameter's value is passed by reference,
// so every time the incrementer is updated (every generation),
// the data in generationCounter will change.
eoIncrementor<unsigned> increment(generationCounter.value());
// Add it to the checkpoint,
// so the counter is updated (here, incremented) every generation
checkpoint.add(increment);
// now some statistics on the population:
// Best fitness in population
eoBestFitnessStat<Indi> bestStat;
eoAverageStat<Indi> averageStat;
// Second moment stats: average and stdev
eoSecondMomentStats<Indi> SecondStat;
// Add them to the checkpoint to get them called at the appropriate time
checkpoint.add(bestStat);
checkpoint.add(averageStat);
checkpoint.add(SecondStat);
// The Stdout monitor will print parameters to the screen ...
eoStdoutMonitor monitor(false);
// when called by the checkpoint (i.e. at every generation)
checkpoint.add(monitor);
// the monitor will output a series of parameters: add them
monitor.add(generationCounter);
monitor.add(eval); // because now eval is an eoEvalFuncCounter!
monitor.add(bestStat);
monitor.add(SecondStat);
// A file monitor: will print parameters to ... a File, yes, you got it!
eoFileMonitor fileMonitor("stats.xg", " ");
eoGnuplot1DMonitor gnuMonitor("best_average.xg");
// the checkpoint mechanism can handle multiple monitors
checkpoint.add(fileMonitor);
checkpoint.add(gnuMonitor);
// the fileMonitor can monitor parameters, too, but you must tell it!
fileMonitor.add(generationCounter);
fileMonitor.add(bestStat);
fileMonitor.add(SecondStat);
// the fileMonitor can monitor parameters, too, but you must tell it!
gnuMonitor.add(eval);
gnuMonitor.add(bestStat);
gnuMonitor.add(averageStat);
// Last type of item the eoCheckpoint can handle: state savers:
eoState outState;
// Register the algorithm into the state (so it has something to save!!)
outState.registerObject(rng);
outState.registerObject(pop);
// and feed the state to state savers
// save state every 100th generation
eoCountedStateSaver stateSaver1(100, outState, "generation");
// save state every 1 seconds
eoTimedStateSaver stateSaver2(1, outState, "time");
// Don't forget to add the two savers to the checkpoint
checkpoint.add(stateSaver1);
checkpoint.add(stateSaver2);
// and that's it for the (control and) output
// GENERATION
/////////////////////////////////////////
// the algorithm
////////////////////////////////////////
// Easy EA requires
// selection, transformation, eval, replacement, and stopping criterion
eoEasyEA<Indi> gga(checkpoint, eval, select, transform, replace);
// Apply algo to pop - that's it!
gga(pop);
// OUTPUT
// Print (sorted) intial population
pop.sort();
cout << "FINAL Population\n" << pop << endl;
// GENERAL
}
// A main that catches the exceptions
int main(int argc, char **argv)
{
#ifdef _MSC_VER
int flag = _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
flag |= _CRTDBG_LEAK_CHECK_DF;
_CrtSetDbgFlag(flag);
// _CrtSetBreakAlloc(100);
#endif
try
{
main_function(argc, argv);
}
catch(exception& e)
{
cout << "Exception: " << e.what() << '\n';
}
return 1;
}