Back to Lesson 1 - Tutorial main page - Top-Down page - Bottom-up page - Programming hints - EO documentation

A First Real GA

Click on the figure to see the corresponding code. Tutorial comments are in variable length fonts, after the code.

//-----------------------------------------------------------------------------

#include <stdexcept > // runtime_error

//-----------------------------------------------------------------------------
// FirstRealGA.cpp
//-----------------------------------------------------------------------------
//*
// An instance of a VERY simple Real-coded Genetic Algorithm
//
//-----------------------------------------------------------------------------
// standard includes

#include <iostream>// cout
#include <strstream>// ostrstream, istrstream

// the general include for eo

#include <eo>

// specific incluse, as Real is not (yet) in the standard eo source dir
#include "eoeal.h"
#include "eoRealOp.h"

//-----------------------------------------------------------------------------
// define your individual:

typedef eoReal<double> Indi;

You say here that you will be handling arrays of doubles, whose fitness is a double
Note that this makes Indi derive from STL class vector<double>
//-----------------------------------------------------------------------------
/** a simple fitness function that computes the euclidian norm of a real vector
    @param _indi A real-valued individual
*/

double real_value(const Indi & _indi)
{
  double sum = 0;
  for (unsigned i = 0; i < _indi.size(); i++)
      sum += _indi[i]*_indi[i];
  return (-sum);   // maximizing
}

This simple function computes the sum of the squares of the variables (remember Indi is here a vector of doubles)
//-----------------------------------------------------------------------------

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 object variables in genotypes
const unsigned int POP_SIZE = 20; // Size of population
const unsigned int T_SIZE = 3; // size for tournament selection
const unsigned int MAX_GEN = 500; // Maximum number of generation before STOP
const float CROSS_RATE = 0.8; // Crossover rate
const double EPSILON = 0.01; // range for real uniform mutation
const float MUT_RATE = 0.5; // 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( real_value );

This encapsulate the C++ function real_value into a functor object

////////////////////////////////
// Initilisation of population
////////////////////////////////

// declare the population
eoPop<Indi> pop;

Declares a population object, which is basically an STL vector<Indi>

// fill it!
for (unsigned int igeno=0; igeno<POP_SIZE; igeno++)
  {
    Indi v; // generate a random individual
    for (unsigned ivar=0; ivar<VEC_SIZE; ivar++)
      {
        double r = 2*rng.uniform() - 1; // new value, random in [-1,1)
        v.push_back(r); //
      }
    eval(v); // evaluate it
    pop.push_back(v); // and put it in the population
  }

This initialization of the population is straightforward
rng.uniform() generates a double uniformly in [0,1),
v.push_back simply appends its argument at the end of STL vector v
eval(v)evaluates individal v the functor way, calling eval.operator()(v)

// sort pop before printing it!
pop.sort();

// Print (sorted) intial population (raw printout)
cout << "Initial Population" << endl;
cout << pop;

If you looked at eoPop inheritance diagram, you noticed that it derives from eoPrintable: hence you can stream them using the << operator. Of course, Indis are EO objects , which also are eoPrintable, and the << operator for eoPop uses the << operator for Indi.

/////////////////////////////////////
// selection and replacement
////////////////////////////////////
// The well-known roulette selection
// The robust tournament selection
eoDetTournament<Indi> select(T_SIZE); // SIZE in [2,POP_SIZE]

// eoSGA uses generational replacement by default
// so no replacement procedure has to be given

//////////////////////////////////////
// termination condition
/////////////////////////////////////
// stop after MAX_GEN generations
eoGenContinue<Indi> continuator(MAX_GEN);

This class is called eoGenContinue because the main loop of all eoAlgo says ... while continuator(pop)

//////////////////////////////////////
// The variation operators
//////////////////////////////////////

// offspring(i) uniformly chosen in [parent(i)-epsilon, parent(i)+epsilon]
eoUniformMutation<Indi>  mutation(EPSILON);
// offspring(i) is a linear combination of parent(i)
eoArithmeticCrossover<Indi> xover;

The variation operators are respectively an eoMonOp (unary operator) and an eoQuadOp (binary operator that modifies both its arguments).

/////////////////////////////////////////
// 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);

// Apply algo to pop - that's it!
gga(pop);

This simple algorithm of class eoSGA is a functor object, and running the algorithm amounts to call the operator() on the initial population!

// Print (sorted) intial population (raw printout)
pop.sort();
cout << "FINAL Population\n" << pop << endl;

that's it - just print the final population and you're done!!!

}

// A main that catches the exceptions - do not modify!
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;
}


Back to Lesson 1 - Tutorial main page - Top-Down page - Bottom-up page - Programming hints - EO documentation
Marc Schoenauer

Last modified: Wed Nov 6 17:22:43 CET 2000