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.
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
Available instances of eoMergeReduce
replacement include
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 within a very simple and easy-to-monitor Dummy EO class.
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 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.
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.
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
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)
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.