diff --git a/eo/tutorial/html/eoOperators.html b/eo/tutorial/html/eoOperators.html index bcd070cb..b7c61d1b 100644 --- a/eo/tutorial/html/eoOperators.html +++ b/eo/tutorial/html/eoOperators.html @@ -2,7 +2,7 @@
- +The basic idea of EO variation operators is that they operate on genotypes +only. Hence there should be generally no reference to anything related +to the fitness within a variation operator. However, whenever the genotype +of an individual has been modified, it will be necessary to recompute its +fitness before any selection process. This is why all +variation operator return a bool that indicates whether or not +the genotype argument has been modified or not. +
EO classes for variation operators:
void operator()(EOT & , const EOT &) +
bool operator()(EOT & , const EOT &)
for eoBinOp (note the const)
- which you could have guessed from the inheritance diagrams up to the
@@ -139,28 +147,42 @@ an eoQuad object.
Using crossover operators:
However, you will hardly have to do so, as operators are used within
-other classes, and are applied systematically to whole sets of individuals
-(e.g. that have already been selected, in standard generational evolutionary
-algorithms).
- However, you will hardly have to actually apply operators to individuals,
+as operators are used within other classes, and are applied systematically
+to whole sets of individuals (e.g. that have already been selected, in
+standard generation-based evolutionary algorithms).
+ Writing a crossover
operator:
-
void operator()(EOT & , EOT &
+
bool operator()(EOT & , EOT &
)
for eoQuadOp
Directly applying crossover operators is straightforward from the interface
above:
-
eoBinOpDerivedClass<Indi> myBinOp(parameters);
-// use constructor to pass
-
eoQuadOpDerivedClass<Indi> myQuadOp(parameters);
-// any useful argument
-
Indi eo1= ..., eo2= ...; //
-the candidates to crossover
-
myBinOp(eo1, eo2);
-// will modify eo1 only
-
myQuadOp(eo1, eo2);
-// will modify eo1 and eo2
-
Hence the way to use such operators will more likely ressemble, if
-you are using for instance an SGA, this (definition,
-usage).
-See also the different ways that are described below, encapsulating the
-operators into combined operators objects.
+
eoBinOpDerivedClass<Indi> myBinOp(parameters);
+
+// use constructor to pass
+
eoQuadOpDerivedClass<Indi> myQuadOp(parameters);
+
+// any useful argument
+
Indi eo1= ..., eo2= ...;
+
+// the candidates to crossover
+
if (myBinOp(eo1, eo2))
+
{ ...
+
+// eo1 has been modified, not eo2
+
}
+
else ...
+
+// none has been modified
+
if (myQuadOp(eo1, eo2))
+
{ ...
+
+// both eo1 and eo2 have been modified
+
}
+
else ...
+
+// none has been modified
+
Hence the way to use such operators will more likely ressemble this
+if you are using for instance an SGA. See also the different ways that
+are described below, encapsulating the operators into combined operators
+objects.
There are only two things to modify in the template
+
There are three things to modify in the template
class definitions provided (apart from the name of the class you are
creating!)
@@ -173,8 +195,8 @@ The operator() method, which performs the
actual crossover.
bool operator()(EOT & )
which you could have guessed from the inheritance diagrams up to the eoUF abstract class.
Using mutation operators:
Directly applying mutation operators is straightforward from the interface
above:
-
eoMonOpDerivedClass<Indi> myMutation(parameters);
-//pass parameters in constructor
-
Indi eo1 = ...;
-// eo1 is candidate to mutation
-
myMutation(eo1);
-// will modify eo1
-
However, you will hardly have to do so, as operators are used within
-other classes, and are applied systematically to whole sets of individuals
-(e.g. that have already been selected, in standard generational evolutionary
-algorithms).
-
Hence the way to use such operators will more likely ressemble, if
-you are using for instance an SGA, this (definition,
-usage).
-See also the different ways that are described below, encapsulating the
-operators into combined operators objects.
+
eoMonOpDerivedClass<Indi> myMutation(parameters);
+//pass parameters in constructor
+
Indi eo = ...;
+// eo is candidate to mutation
+
if (myMutation(eo))
+
{ ...
+
+// eo has been modified
+
}
+
else
+
+// eo has not been modified
+
However, you will hardly have to actually apply operators to individuals,
+as operators are used within other classes, and are applied systematically
+to whole sets of individuals (e.g. that have already been selected, in
+standard generational evolutionary algorithms).
+
Hence the way to use such operators will more likely ressemble this
+if you are using for instance an SGA. See also the different ways that
+are described below, encapsulating the operators into combined operators
+objects.
Writing a mutation
operator:
There are only two things to modify in the template
@@ -228,11 +255,11 @@ The operator() method, which performs the
actual crossover.
The best thing to do is to go to the Lesson2
of the tutorial, where everything is explained. You will find out how you
can use
-
several mutations (respectiveley crossovers) as a single operator:
-every time the operator is called, one of the available operators is chosen
-by some roulette wheel selection using realtive weights.
+
several mutations (respectiveley quadratic crossovers) as a single
+operator: every time the operator is called, one of the available operators
+is chosen by some roulette wheel selection using realtive weights.
Interface:
- void apply(eoPopulator<EOT>&
+_plop)
+ As you can see,the interface for eoGenOp
is based on that of another class, called eoPopulator.
An
eoPopulator
is a population, but also behaves like
an iterator over a population (hence
-the name, Population-Iterator).
- The basic
-interface of an eoPopulator
-(see also the documentation,
-of course) is the following: Individuals are accessed through the operator*;
-Basic iterator operations are available, like (pre)incrementation through
-operator++,
-position management through seekp
-(returns the current position) and tellp
-(go to a given position); Individuals can also be inserted
-and erased at current position using
-the corresponding methods; last but not least, as the individuals are returned
-by reference, it is mandatory to ensure that they will not be moved around
-later: the memory management routine reserve is called whenever there
-is a chance to add some individuals in the population.
+the name, Population-Iterator).
+However, please note that you should probably never use an eoGenOp alone,
+but rather through objects of type eoOpContainer.
This results in the following general interface for an eoGenOp:
It receives as argument an eoPopulator,
gets the individuals it needs using the operator*,
and must handle the positinning of the using the operator++
method.
- void operator()(eoPopulator&
+ bool apply()(eoPopulator&
_pop)
// do whatever the operator is supposed to
do
+ void apply()(eoPopulator&
_pop)
// invalidate the parents that
+have been modified
+ Of course the size of the resulting population will grow - and you should
+have a replacement procedure that takes care of that.
+
- void operator()(eoPopulator&
+ void apply()(eoPopulator&
_pop)
where select is any selector you like. Note the const: you are not allowed
-to modify an element of the original population (but you could of course
-have copied it!). Now to find out where that selector comes from, you'll
-have to wait until next section. If you can't wait, go directly there.
+ where select is any selector you like. Note the
+const: you are not allowed to modify an element of the original
+population (but you could of course have copied it!). As usual, the select
+selector was pased to the operator at construct time.
// then kill the ones that are now
+useless
+ Writing a general
operator:
- The basic
+interface of an eoPopulator
+(see also the documentation,
+of course) is the following:
+ Example: An eoSelectivePopulator
+is the main ingredient of the eoGeneralBreeder
+operator()
+method - a class that creates a population of offspring from the parents
+applying an eoGenOp (usually an eoOpContainer) to all selected parents
+in turn.
The interface for eoGenOp
+
All the work a general operator is done within the apply()
+method. WHy not in the usual operator() method? Because some memory management
+are needed, that are performed in the base class itself - which then calls
+the virtual apply() method.
+The interface for a eoGenOp thus is
+not deducible from its inheritance diagram, and actually is
+
{
-
EOT & eo1 = *_pop; // get
-(select if necessary) the guy
-
++_pop;
+
EOT& parent1 = *_pop;
+//
+select the first parent
+
++_plop;
-// advance
-
EOT & eo2 = *_pop; // get
-(select if necessary) the guy
-
++_pop;
+// advance once for each selected parents
+
...
+
EOT& parentN = *_pop;
+//
+select the last parent
+
-// advance
-
...
-
EOT & eoN = *_pop; // get
-(select if necessary) the guy
-
++_pop;
-
-// advance
+// don't advance after the last one: _plop always
+
+// points to the last that has already been treated
}
@@ -318,29 +340,40 @@ were parents
void operator()(eoPopulator&
+
+
+
+
{
-
EOT & eo1 = *_pop; // get
-(select if necessary) the guy
-
++_pop;
-
-// advance
-
// Now create second offspring - eo1
-is modified too!
-
EOT eo2 = create_individual(eo1);
-
// inserts eo2 in _pop after eo1
-
_pop.insert(eo2);
-
...
-
Of course the size of the resulting population will grow - and you
-should have a replacement procedure that takes care of that.
+
// get the necessary number
+of parents (see above)
+
...
+
// Now create any supplementary offspring
+
EOT ofs1 = create_individual(...);
+
...
+
EOT ofsK = create_individual(...);
+
// inserts offspring in _pop after
+parentN
+
_pop.insert(ofs1);
+
...
+
parent1.invalidate();
+
...
+
parentN.invalidate();
+
} // over
+
There are two possibilities:
+
+
+
{
-
EOT & eo1 = *_pop; // get
-(select if necessary) the guy
-
++_pop;
-
-// advance
-
const EOT & eo2 = select(_pop.source());
-
// get the necessary number
+of parents (see above)
+
...
+
// get extra parents - use
+private selector
+
const EOT& parentN+1 = select(_pop.source());
+
...
+
const EOT& parentM = select(_pop.source());
+
void operator()(eoPopulator&
+
void apply()(eoPopulator&
_pop)
{
-
EOT & eo1 = *_pop; // get
-(select if necessary) the guy
-
++_pop;
-
-// advance
-
EOT & eo2 = *_pop; // get
-(select if necessary) the guy
-
++_pop;
-
-// advance
-
// do whatever needs to be done, modifying
-eo1 but not eo2
-
_pop.delete(); //
-removes (untouched) eo2 from the list
// get the necessary number
+of parents (see above)
+
...
+
// do whatever needs to be done to
+any parent
+
_plop.erase();
+// as many times as necessary
+
...
+
// invalidate fitnesses of remaining
+modified parents
+
parent1.invalidate();
+
...
+
parentK.invalidate();
+
}
Warning: if you use operators that
have different number of parents than offspring, you are deviating from
@@ -398,36 +437,84 @@ for all forthcoming EO algorithms.
Directly applying general operators to given individuals is impossible
in EO, due to its interface. You need the help
of an individual dispenser of class eoPopulator.
-But anyway general operators were thought to be used mainly in combination
-of one another, as described below.
+But anyway general operators were thought to be used putely in eoOpContainer,
+as described below.
There are many things to modify in the template
+
There are many things to modify in the template
class definitions provided.
-
Warning: as usual, don't forget
-to invalidate the fitness of the individual
-- if it has actually been modified. Otherwise, the lazy
+Warning: in general operators,
+you must not forget to invalidate the
+fitness of any individual that has actually been modified. this implicitely
+implies that general operators can only be applied to EO object (i.e. objects
+with a fitness), and not to any type of structure.
+
+the fitness again and will keep the old obsolete value.
It you don't invalidate the individual, the lazy
fitness evaluation procedure in EO will not know it should compute
-the fitness again and will keep the old value.
The
populators:
-
The public interface class eoPopulator
-has been described above. However, a protected method, termed select,
+
As has been said above, an
+eoPopulator
+is a population, but also behaves like
+an iterator over a population (hence
+the name, Population-Iterator).
+
+
+Moreover, a protected method, termed select,
is used inside the object to get new parents for the following operator,
and its implementation distinguishes two types of eoPopulator:
@@ -447,19 +534,29 @@ object (passed at construct time). Hence it can handle any number of parents
at will. The idea of such populator is to handle the whole breeding
process, i.e. selection and variation operators.
-An immediate consequence is that if you are not sure of the numebr of
+An immediate consequence is that if you are not sure of the number of
parents you will need in some operators (e.g. because of some stochastic
proportional selection ebtween operators that don't need the same number
of parents, then you must use an eoSelectivePopulator
-to apply the variation operators to the population.
+to apply the variation operators to the population, and thus get exactly
+the number of offspring you want.
+
General
-Combinations:
-
There are two main ways to use and combine general operators in EO:
-the proportional combination, similar to what has been described for simple
-operators above, and the sequential
-combination, which amounts to apply all operators in turn to a bunch of
-individuals, each operator being applied with a specific probability.
+Operator Containers:
Proportional combinations
When called upon a population (through an eoPopulator
object), an eoProportionalOpContainer
@@ -519,6 +616,25 @@ Next pending parent
someOperatorType<Indi> myOperator;
eoYYYOpContainer<Indi> myOpContainer;
myOpContainer.add(myOperator, rate); //
-rate: double whose meaning depends on XXX
-
where YYY can be one of Proportional and Sequential.
-
Warning: the way rate
-will be used is highly dependent on the type of eoOpContainer
-your are creating there:
-
where YYY can be one of Proportional and Sequential. Note that before +being added to the container, all simple operators are wrapped into the +corresponding eoGenOp (see e.g. how an eoMonOp +is wrapped into +an eoMonGenOp- or how any +operator is handled by calling the appropriate wrapper). In particular, +the wrapper ensures that individuals who have +been modified are invalidated. +
Containers,
Selectors and Populators
The way the eoOpContainer are applied
on a population using an eoPopulator
@@ -633,20 +737,20 @@ general operators:
preferences, i.e. choose a mate for a first parent according
to some characteritics of that first parent).
This is made possible in EO because the general operators have a handle
-on the initial population through the method source() of the argument eoPopulator
-they work on. Their operator()
+on the initial population through the method source()
+of the argument eoPopulator they work on. Their apply()
method shoudl look like
-
void operator()(eoPopulator&
+ void apply()(eoPopulator&
_pop)
{
EOT & eo1 = *_pop; // get
(select if necessary) the first guy
-
++_pop;
+
++_pop;
-// advance
+
EOT & eo2 = findBlonde(_pop.source());
-
-// select mate
+//
+select mate
// do whatever the operator is supposed to
do
}
@@ -671,7 +775,7 @@ documentation
Marc Schoenauer
Last
-modified: Fri Dec. 8 2000
+modified: Sat. Feb. 17 2001