Algorithm-Based - Component-Based - Programming hints - EO documentation

Evolution Engine


Contents



Introduction

The term evolution engine denotes the different parts of an Evolutionary Algorithm that simulate the Darwinism:

The fittest individuals are more likely to reproduce and survive.

Darwinism takes place in two different phases of an EA, though in many popular variants, only one phase is activated.

Selection is the Darwinistic choice of parents that will be allowed to reproduce.
Replacement takes place after reproduction, and is the Darwinistic choice of those individuals that will survive, i.e. become the parents of the next generation.

Both selection and replacement will be discussed in turn, before some helper classes that are used within selection and replacement procedures are presented.


Selection
 
 



Replacement

The replacement phase takes place after the birth of all offspring through variation operators. The idea is to close the generation loop, i.e. to end up with a population of individuals that will be the initial population of next generation. That population will be built upon the old parents and the new-born offspring. In all algorithms that come up with EO, the population size is supposed to be constant from one generation to the next one - though nothing stops you from writing an algorithm with varying population size.

Replacement: The interface

The abstract class for replacement procedures is the functor class eoReplacement, and the interface for its operator() is

void operator()(eoPop<EOT>& _parents, eoPop<EOT>& _offspring)

which you could have guessed from the inheritance tree for class eoReplacement., as you see there that eoReplacement derives from class eoBF<eoPop<EOT>&, eoPop<EOT>&, void>.
This means that it takes 2 populations (called, for obvious anthropomorphic reasons, _parents and _offspring :-) and is free to modify both, but the resulting population should be placed in the first argument (usually called_parents) to close the loop and go to next generation.

Replacement: Instances

Replacement: Adding (weak) elitism

You can add what is called weak elitism to any replacement by encapsulating it into an eoWeakElitismReplacement object. Weak elitism ensures that the overall best fitness in the population will never decrease: if the best fitness in the new population is less than the best fitness of the parent population, then the best parent is added back to the new population, replacing the worse.

Within EO, this is very easy to add:

First, declare your replacement functor (here, generational, but it can be any replacement object):
eoGenerationalReplacement<Indi> genReplace;
Then wrap the weak elitism around it:
eoWeakElitismReplacement<Indi> replace(genReplace);
and use now replace as your replacement procedure within your algorithm.

Note: of course, adding weak elitism to an elitist replacement makes no sense - but will not harm either :-)

Replacement: Test file

The file t-eoReplacement in the test directory implements all above replacmenet procedures withni a very simple and easy-to-monitor Dummy EO class.



Popular evolution engines

This section will be completed soon - in the meantime just trust us that all of these are already implemented in EO (except maybe some of the last category :-) !!!!!!

The most popular evolution engines are listed below, together with the way to use them in EO. If you don't find your particuler algorithm, please send it to us, and we might include it here!



Tournaments

Tournaments are an easy and quick way to select individuals within a population based on simple comparisons. Though usually based on fitness comparisons, they can use any comparison operator.
In EO, there are two variants of tournaments used to select one single individual, namely Deterministic Tournament and Stochastic Tournament, that are used in selection and in replacement procedures, and a global tournament-based selection of a whole bunch of individuals, the EP Tournament. Though the single-selection tournaments can be repeated to select more than one individual, and the batch tournament selection can be used to select a single individual, both uses are probably a waste of CPU time.




Merging populations

In replacement procedures, one frequently needs to merge two populations (computed form old parents and new-born offspring). Classes derived from the abstract class eoMerge are written for that purpose.

eoMerge: interface
The abstract class for merging procedures is the functor class eoMerge, and the interface for its operator() is

void operator()(const eoPop<EOT>& _parents, eoPop<EOT>& _offspring)

which you could have guessed from the inheritance tree for class eoMerge, as you see there that eoMerge derives from
class eoBF<const eoPop<EOT>&, eoPop<EOT>&, void>.
This means that it takes 2 populations and modifies the seond one by adding some individuals from the first one (which is supposed to remain constant).

eoMerge: instances
Available instances of eoMerge objects are eoPlus, that simply adds the parents to the offspring, or eoElitism, that adds only some of the (best) parents to the offspring. A special case of eoElistism is eoNoElitism, an eoMerge that does nothing.



Reducing populations

The other useful component of replacement procedures, eoReduce, kills some individuals from a given population.

eoReduce: interface
The abstract class for reducing procedures is the functor class eoReduce, and the interface for its operator() is

void operator()(eoPop<EOT>& _parents, unsigned int new_size)

which you could have guessed from the inheritance tree for class eoReduce, as you see there that eoReduce derives from
class eoBF<eoPop<EOT>&, unsigned int, void>.
An eoReduce shoud take a population and shrink it to the required size.

eoReduce: instances
Available instances of eoReduce are




Relative or absolute number of individuals

Many classes in selection/replacement procedures will handle a number of individuals that may either be fixed or be a fraction of some argument-population size.
Of course, it is possible to write two different classes that will only differ by the way they compute the number of individuals they have to treat, as it is done for selectors with the two classes eoSelectPerc and eoSelectNumber (it could also have been possible to have some pure abstrat class and implement the computation of the number of individuals to treat in some derived classes).
However, rather than multiply the number of class, EO has defined a class that will handle the problem once and for all, the class eoHowMany. It receives a double, and a boolean indicating whether that double is to be treated as a rate or as an absolute (unisgned) interger.

eoHowMany: interface
The class interface for its operator() is

unsigned int operator()(unsigned int _pop_size)

which you could have guessed from the inheritance tree for class eoHowMany, as you see there that eoHowMany derives from
class eoUF<unsigned int, unsigned int>.

Its constructor takes 2 argumenrts:

eoHowMany(double _rate, bool _interpret_as_rate = true)

so by default the double is indeed interpreted as a rate.

It is used in eoSelectMany (which supersedes eoSelectPerc and eoSelectNumber, but they are left there for tutorial reasons!) as well as in many truncation methods.



Survive and Die


Algorithm-Based - Component-Based - Programming hints -EO documentation

Marc Schoenauer

Last modified: Tue. Dec. 5 2000