Big modifications - now the init and most important the operators

are handled in separate files make_genotype_xxx and make_op_xxx
as it was done in the examples of Lesson4
This commit is contained in:
evomarc 2001-10-04 20:12:19 +00:00
commit f3db65795b
7 changed files with 525 additions and 45 deletions

View file

@ -2,7 +2,7 @@
.cpp: ; c++ -DPACKAGE=\"eo\" -DVERSION=\"0.9.1\" -I. -I../../src -Wall -g -o $@ $*.cpp ../../src/libeo.a ../../src/utils/libeoutils.a
.cpp.o: ; c++ -DPACKAGE=\"eo\" -DVERSION=\"0.9.1\" -DF2C -I. -I../../src -I../Points -I./Sol -I./util -Wall -g -c $*.cpp
.cpp.o: ; c++ -DPACKAGE=\"eo\" -DVERSION=\"0.9.1\" -DF2C -I. -I../../src -I./util -Wall -g -c $*.cpp
# START eventually modify the name of EO dir
@ -11,12 +11,12 @@ DIR_EO = ../../src
LIB_EO = $(DIR_EO)/utils/libeoutils.a $(DIR_EO)/libeo.a
ALL = eoMyStructEA
ALL = MyStructEA
eoMyStructEA : eoMyStructEA.o
c++ -g -o $@ eoMyStructEA.o ../../src/utils/libeoutils.a ../../src/libeo.a -lm
MyStructEA : MyStructEA.o
c++ -g -o $@ MyStructEA.o ../../src/utils/libeoutils.a ../../src/libeo.a -lm
tar : ; tar czvf climat.tgz *.h *.cpp Makefile
tar : ; tar czvf MyStruct.tgz *.h *.cpp Makefile
all : $(ALL)

View file

@ -0,0 +1,184 @@
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
The above line is usefulin Emacs-like editors
*/
/*
Template for creating a new representation in EO
================================================
This is the template main file.
It includes all other files that have been generated by the script create.sh
so it is the only file to compile.
In case you want to build up a separate library for your new Evolving Object,
you'll need some work - follow what's done in the src/ga dir, used in the
main file BitEA in tutorial/Lesson4 dir.
Or you can wait until we do it :-)
*/
// Miscilaneous include and declaration
#include <iostream>
using namespace std;
// eo general include
#include "eo"
// the real bounds (not yet in general eo include)
#include "utils/eoRealVectorBounds.h"
// include here whatever specific files for your representation
// Basically, this should include at least the following
/** definition of representation:
* class eoMyStruct MUST derive from EO<FitT> for some fitness
*/
#include "eoMyStruct.h"
/** definition of initilizqtion:
* class eoMyStructInit MUST derive from eoInit<eoMyStruct>
*/
#include "eoMyStructInit.h"
/** definition of evaluation:
* class eoMyStructEvalFunc MUST derive from eoEvalFunc<eoMyStruct>
* and should test for validity before doing any computation
* see tutorial/Templates/evalFunc.tmpl
*/
#include "eoMyStructEvalFunc.h"
// GENOTYPE eoMyStruct ***MUST*** be templatized over the fitness
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
// START fitness type: double or eoMaximizingFitness if you are maximizing
// eoMinimizingFitness if you are minimizing
typedef eoMyStruct<double> Indi; // ***MUST*** derive from EO
// END fitness type
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
// create an initializer
#include "make_genotype_MyStruct.h"
eoInit<Indi> & make_genotype(eoParameterLoader& _parser, eoState&_state, Indi _eo)
{
return do_make_genotype(_parser, _state, _eo);
}
// and the variation operaotrs
#include "make_op_MyStruct.h"
eoGenOp<Indi>& make_op(eoParameterLoader& _parser, eoState& _state, eoInit<Indi>& _init)
{
return do_make_op(_parser, _state, _init);
}
// Use existing modules to define representation independent routines
// These are parser-based definitions of objects
// how to initialize the population
// it IS representation independent if an eoInit is given
#include <do/make_pop.h>
eoPop<Indi >& make_pop(eoParser& _parser, eoState& _state, eoInit<Indi> & _init)
{
return do_make_pop(_parser, _state, _init);
}
// the stopping criterion
#include <do/make_continue.h>
eoContinue<Indi>& make_continue(eoParser& _parser, eoState& _state, eoEvalFuncCounter<Indi> & _eval)
{
return do_make_continue(_parser, _state, _eval);
}
// outputs (stats, population dumps, ...)
#include <do/make_checkpoint.h>
eoCheckPoint<Indi>& make_checkpoint(eoParameterLoader& _parser, eoState& _state, eoEvalFuncCounter<Indi>& _eval, eoContinue<Indi>& _continue)
{
return do_make_checkpoint(_parser, _state, _eval, _continue);
}
// evolution engine (selection and replacement)
#include <do/make_algo_scalar.h>
eoAlgo<Indi>& make_algo_scalar(eoParameterLoader& _parser, eoState& _state, eoEvalFunc<Indi>& _eval, eoContinue<Indi>& _continue, eoGenOp<Indi>& _op)
{
return do_make_algo_scalar(_parser, _state, _eval, _continue, _op);
}
// simple call to the algo. stays there for consistency reasons
// no template for that one
#include <do/make_run.h>
// the instanciating fitnesses
#include <eoScalarFitness.h>
void run_ea(eoAlgo<Indi>& _ga, eoPop<Indi>& _pop)
{
do_run(_ga, _pop);
}
// checks for help demand, and writes the status file
// and make_help; in libutils
void make_help(eoParser & _parser);
// now use all of the above, + representation dependent things
int main(int argc, char* argv[])
{
try
{
eoParser parser(argc, argv); // for user-parameter reading
eoState state; // keeps all things allocated
// The fitness
//////////////
eoMyStructEvalFunc<Indi> plainEval/* (varType _anyVariable) */;
// turn that object into an evaluation counter
eoEvalFuncCounter<Indi> eval(plainEval);
// the genotype - through a genotype initializer
eoInit<Indi>& init = make_genotype(parser, state, Indi());
// Build the variation operator (any seq/prop construct)
eoGenOp<Indi>& op = make_op(parser, state, init);
//// Now the representation-independent things
//
// YOU SHOULD NOT NEED TO MODIFY ANYTHING BEYOND THIS POINT
// unless you want to add specific statistics to the checkpoint
//////////////////////////////////////////////
// initialize the population
// yes, this is representation indepedent once you have an eoInit
eoPop<Indi>& pop = make_pop(parser, state, init);
// stopping criteria
eoContinue<Indi> & term = make_continue(parser, state, eval);
// output
eoCheckPoint<Indi> & checkpoint = make_checkpoint(parser, state, eval, term);
// algorithm (need the operator!)
eoAlgo<Indi>& ga = make_algo_scalar(parser, state, eval, checkpoint, op);
///// End of construction of the algorithm
/////////////////////////////////////////
// to be called AFTER all parameters have been read!!!
make_help(parser);
//// GO
///////
// evaluate intial population AFTER help and status in case it takes time
apply(eval, pop);
// if you want to print it out
// cout << "Initial Population\n";
// pop.sortedPrintOn(cout);
// cout << endl;
run_ea(ga, pop); // run the ga
cout << "Final Population\n";
pop.sortedPrintOn(cout);
cout << endl;
}
catch(exception& e)
{
cout << e.what() << endl;
}
}

View file

@ -1,7 +1,7 @@
This directory contains sample files that should make it easy to
create an EO algorithm to evolve any type of structure
(EO comes with two examples, bitstrings and vector of real variables,
so you'll need this qs soon as you want to evolve something else).
so you'll need this as soon as you want to evolve something else).
At the moment, only algorithms involving a scalar fitness (double)
are implemented (see test dir for Pareto optimization of multiple-
@ -9,7 +9,7 @@ objective fitness - or be patient :-)
This file will help you to build the same algorithm than the ones
in the Lesson4 of the tutorial, but with YOUR genotype instead of
*bitstrings or vector<double>
bitstrings or vector<double>
It is assumed in the following that you have read the first part of
the tutorial (Lessons 1 to 4).
@ -21,18 +21,19 @@ structure, and that you have enough programming skills to be able to
write C code for its random initilialization, its crossover, its
mutation and the computation of its fitness.
The helper script create.sh will create for you the files you need
from teh examples in tutorial/Templates dir, and all you'll have to do
The helper script * create.sh * will create for you the files you need
from the samples in tutorial/Templates dir, and all you'll have to do
is to include the actual code where indicated in those files (between
keywords START and END).
First, let's choose a name: let's call the new EO class eoAppli.
All newly created classes will be named eoApplicationXXX (in the file
eoApplicationXXX)
All newly created classes will be named eoAppliXXX (in the file
eoAppliXXX)
1- create a directory for your application in the tutorial dir, "parallel" to
the LessonX dirs (though any name can do, of course, we will suppose
its full name, from the / root dir, is APPLICATION in what follows)
1- choose a directory name for your application in the tutorial dir,
"parallel" to the LessonX dirs (though any name can do, of course, we
will suppose its full name, from the / root dir, is APPLICATION in
what follows)
2- cd to the tutorial/Templates dir
@ -41,25 +42,30 @@ its full name, from the / root dir, is APPLICATION in what follows)
4- cd to the APPLICATION dir. You should see there the following
files:
AppliEA.cpp the main file, includes all other, to be compiled
Makefile with default target eoAppliEA
eoAppli.h class eoAppli<FitT>, FitT = template fitness
eoAppliEA.cpp the main file, includes all other, to be compiled
eoAppliEvalFunc.h class for the computation of fotness
eoAppliInit.h class for genotype initlialization
eoAppliMutation.h class for mutation
eoAppliQuadCrossover.h class for (quadratic) crossover
make_genotype_Appli.h helper function that create the initializer
make_op_Appli.h helper function that creates the variatin operators
Note: You can go directly to step 6 and 7: you'll get a lot of
warnings, but will be able to run an EA that does nothing!
5- Edit those files one after the other and add you code where
indicated (look for keywords START and END and modify code in
between).
5- Edit those files to suit your needs. The minimal addition you'll need
to make are
in eoAppli.h define your genotype
in eoAppliInit.h define the initialization of one genotype
in eoAppliMutation.h define the mutation of one genotype
in eoAppliQuadCrossover.h define the crossover of 2 genotypes
Note: If your APPLICATION dir is in the tutorial dir, you don't need
to modify Makefile.
HINT: look for keywords START and END and modify code in between.
6- Compile eoAppliEA.cpp:
6- Compile eoAppliEA.cpp. If your APPLICATION dir is in the tutorial
dir, you don't need to modify Makefile. Just type in
% make
@ -83,24 +89,22 @@ want to become active), and run
HINTS
-----
1- All new classes you will create probably require some parameters in
the constructor, and some (if not all) thoses parameters are likele to
be user parameter: you can either read them in the main file (as is
done in the sample eoAppliEA.cpp) or pass the eoParser to the
1- If some new classes you create require some user parameter, you can
either read them in the file where they are created (e.g.
make_op_Appli.h for variation operators), or pass the eoParser to the
constructor of the class, and read the parameter from the parser.
2- If you stick to privacy for the data in your EO class, you will
probably need to write accessors to those data, as well as some public
methods to modify them.
methods to modify them, as soon as some other methods need them too.
3- The sample eoAppliEA.cpp supposes that you ony have one crossover
and one mutation operator. However, the code for multiple operators
is there: you can have for instance 2 crossover operators, and choose
3- The sample make_op_Appli.h supposes that you ony have one crossover
and one mutation operator. However, the code for multiple operators is
there: you can have for instance 2 crossover operators, and choose
among them according to relative weights (proportional choice) - same
for mutation. Look at the operator section in eoAppliEA.cpp
In particular, the user parameter mutationRate is totally useless for
a single operator, and is there only as a provision for using more
than one.
for mutation. Look at the operator section in eoAppliEA.cpp In
particular, the user parameters cross1Rate and mut1Rate are totally
useless for a single operator.
To add another operator, you have to create another class by mimicking
what has been done for the first operator.
@ -113,13 +117,16 @@ name in the class declaration, in the constructor and in the
className() method.
* in the new eoAppliBetterMutation class, change the code for the
operator() - and eventually the code for the constructor.
* in the eoAppliEA.cpp file, in the mutation section, uncomment the
* in the make_op_Appli.h file, in the mutation section, uncomment the
lines
eoMyStructSecondMutation<Indi> mut2(varType _anyVariable);
double mut2Rate = parser.createParam(1.0, "mut2Rate", "Relative rate for mutation 2", '2', "Variation Operators").value();
propMutation.add(mut2, mut2Rate);
mut = new eoAppliSecondMutation<Indi>(varType _anyVariable);
_state.storeFunctor(mut);
double mut2Rate = _parser.createParam(1.0, "mut2Rate", "Relative rate for mutation 2", '2', "Variation Operators").value();
propMutation.add(*mut, mut2Rate);
and change the name of the class from eoAppliSecondMutation to your
name eoAppliBetterMutation (you can also change the keyword from
mut2Rate to something more meaningful like BetterMutationRate).
You're done!
In case of problem: Marc.Schoenauer@inria.fr

View file

@ -3,11 +3,17 @@ if ($#argv < 2) then
echo Usage $argv[0] ApplicationName TargetDir
exit
endif
sed s/eoMyStruct/eo$1/g eoMyStruct.tmpl > $2/eo$1.h
sed s/eoMyStruct/eo$1/g init.tmpl > $2/eo$1Init.h
sed s/eoMyStruct/eo$1/g evalFunc.tmpl > $2/eo$1EvalFunc.h
sed s/eoMyStruct/eo$1/g mutation.tmpl > $2/eo$1Mutation.h
sed s/eoMyStruct/eo$1/g quadCrossover.tmpl > $2/eo$1QuadCrossover.h
sed s/eoMyStruct/eo$1/g eoMyStructEA.cpp > $2/eo$1EA.cpp
sed s/eoMyStruct/eo$1/g Makefile.tmpl > $2/Makefile
if (! -e $2) then
mkdir $2
endif
sed s/MyStruct/$1/g eoMyStruct.tmpl > $2/eo$1.h
sed s/MyStruct/$1/g init.tmpl > $2/eo$1Init.h
sed s/MyStruct/$1/g evalFunc.tmpl > $2/eo$1EvalFunc.h
sed s/MyStruct/$1/g mutation.tmpl > $2/eo$1Mutation.h
sed s/MyStruct/$1/g quadCrossover.tmpl > $2/eo$1QuadCrossover.h
sed s/MyStruct/$1/g MyStructEA.cpp > $2/$1EA.cpp
sed s/MyStruct/$1/g make_genotype_MyStruct.h > $2/make_genotype_$1.h
sed s/MyStruct/$1/g make_op_MyStruct.h > $2/make_op_$1.h
sed s/MyStruct/$1/g Makefile.tmpl > $2/Makefile

View file

@ -4,7 +4,7 @@ The above line is usefulin Emacs-like editors
*/
/*
Template for continuator in EO, i.e. stopping conditions for EO algorithms
Template for evaluator in EO, a functor that computes the fitness of an EO
==========================================================================
*/

View file

@ -0,0 +1,73 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// make_genotype.h
// (c) Maarten Keijzer, Marc Schoenauer and GeNeura Team, 2001
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
Marc.Schoenauer@polytechnique.fr
mkeijzer@dhi.dk
*/
//-----------------------------------------------------------------------------
#ifndef _make_genotype_h
#define _make_genotype_h
#include <eoMyStruct.h>
#include <eoMyStructInit.h>
// also need the parser and param includes
#include <utils/eoParser.h>
#include <utils/eoState.h>
/*
* This fuction does the create an eoInit<eoMyStruct>
*
* It could be here tempatized only on the fitness, as it can be used
* to evolve structures with any fitness.
* However, for consistency reasons, it was finally chosen, as in
* the rest of EO, to templatize by the full EOT, as this eventually
* allows to choose the type of genotype at run time (see in es dir)
*
* It returns an eoInit<EOT> that can later be used to initialize
* the population (see make_pop.h).
*
* It uses a parser (to get user parameters) and a state (to store the memory)
* the last argument is to disambiguate the call upon different instanciations.
*
* WARNING: that last argument will generally be the result of calling
* the default ctor of EOT, resulting in most cases in an EOT
* that is ***not properly initialized***
*/
template <class EOT>
eoInit<EOT> & do_make_genotype(eoParameterLoader& _parser, eoState& _state, EOT)
{
// read any useful parameter here from the parser
// the param itself will belong to the parser (as far as memory is concerned)
// paramType & param = _parser.createParam(deafultValue, "Keyword", "Comment to appear in help and status", 'c',"Section of status file").value();
// Then built the initializer - a pointer, stored in the eoState
eoInit<EOT>* init = new eoMyStructInit<EOT> /* ( param ) */ ;
// store in state
_state.storeFunctor(init);
// and return a reference
return *init;
}
#endif

View file

@ -0,0 +1,210 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// make_op_MyStruct.h
// (c) Marc Schoenauer, Maarten Keijzer and GeNeura Team, 2001
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
Marc.Schoenauer@polytechnique.fr
mkeijzer@dhi.dk
*/
//-----------------------------------------------------------------------------
#ifndef _make_op_MyStruct_h
#define _make_op_MyStruct_h
// the operators
#include <eoOp.h>
#include <eoGenOp.h>
#include <eoCloneOps.h>
#include <eoOpContainer.h>
// combinations of simple eoOps (eoMonOp and eoQuadOp)
#include <eoProportionalCombinedOp.h>
/** definition of mutation:
* class eoMyStructMonop MUST derive from eoMonOp<eoMyStruct>
*/
#include "eoMyStructMutation.h"
/** definition of crossover (either as eoBinOp (2->1) or eoQuadOp (2->2):
* class eoMyStructBinCrossover MUST derive from eoBinOp<eoMyStruct>
* OR
* class eoMyStructQuadCrossover MUST derive from eoQuadOp<eoMyStruct>
*/
// #include "eoMyStructBinOp.h"
// OR
#include "eoMyStructQuadCrossover.h"
// also need the parser and state includes
#include <utils/eoParser.h>
#include <utils/eoState.h>
/////////////////// variation operators ///////////////
// canonical (crossover + mutation) only at the moment //
/*
* This function builds the operators that will be applied to the eoMyStruct
*
* It uses a parser (to get user parameters), a state (to store the memory)
* the last parameter is an eoInit: if some operator needs some info
* about the genotypes, the init has it all (e.g. bounds, ...)
* Simply do
* EOT myEO;
* _init(myEO);
* and myEO is then an ACTUAL object
*
* As usual, the template is the complete EOT even though only the fitness
* is actually templatized here: the following only applies to eoMyStruct
*/
template <class EOT>
eoGenOp<EOT> & do_make_op(eoParameterLoader& _parser, eoState& _state, eoInit<EOT>& _init)
{
// this is a temporary version, while Maarten codes the full tree-structured
// general operator input
// BTW we must leave that simple version available somehow, as it is the one
// that 90% people use!
/////////////////////////////
// Variation operators
////////////////////////////
// read crossover and mutations, combine each in a proportional Op
// and create the eoGenOp that calls crossover at rate pCross
// then mutation with rate pMut
// the crossovers
/////////////////
// here we can have eoQuadOp (2->2) only - no time for the eoBinOp case
// you can have more than one - combined in a proportional way
// first, define the crossover objects and read their rates from the parser
// A first crossover
eoQuadOp<Indi> *cross = new eoMyStructQuadCrossover<Indi> /* (varType _anyVariable) */;
// store in the state
_state.storeFunctor(cross);
// read its relative rate in the combination
double cross1Rate = _parser.createParam(1.0, "cross1Rate", "Relative rate for crossover 1", '1', "Variation Operators").value();
// and create the combined operator with this one
eoPropCombinedQuadOp<Indi> *propXover =
new eoPropCombinedQuadOp<Indi>(*cross, cross1Rate);
// and of course stor it in the state
_state.storeFunctor(propXover);
// Optional: A second(and third, and ...) crossover
// of course you must create the corresponding classes
// and all ***MUST*** derive from eoQuadOp<Indi>
/* Uncomment if necessary - and replicate as many time as you need
cross = new eoMyStructSecondCrossover<Indi>(varType _anyVariable);
_state.storeFunctor(cross);
double cross2Rate = _parser.createParam(1.0, "cross2Rate", "Relative rate for crossover 2", '2', "Variation Operators").value();
propXover.add(*cross, cross2Rate);
*/
// if you want some gentle output, the last one shoudl be like
// propXover.add(*cross, crossXXXRate, true);
// the mutation: same story
////////////////
// you can have more than one - combined in a proportional way
// for each mutation,
// - define the mutator object
// - read its rate from the parser
// - add it to the proportional combination
// a first mutation
eoMonOp<Indi> *mut = new eoMyStructMutation<Indi>/* (varType _anyVariable) */;
_state.storeFunctor(mut);
// its relative rate in the combination
double mut1Rate = _parser.createParam(1.0, "mut1Rate", "Relative rate for mutation 1", '1', "Variation Operators").value();
// and the creation of the combined operator with this one
eoPropCombinedMonOp<Indi> *propMutation = new eoPropCombinedMonOp<Indi>(*mut, mut1Rate);
_state.storeFunctor(propMutation);
// Optional: A second(and third, and ...) mutation with their rates
// of course you must create the corresponding classes
// and all ***MUST*** derive from eoMonOp<Indi>
/* Uncomment if necessary - and replicate as many time as you need
mut = new eoMyStructSecondMutation<Indi>(varType _anyVariable);
_state.storeFunctor(mut);
double mut2Rate = _parser.createParam(1.0, "mut2Rate", "Relative rate for mutation 2", '2', "Variation Operators").value();
propMutation.add(*mut, mut2Rate);
*/
// if you want some gentle output, the last one shoudl be like
// propMutation.add(*mut, mutXXXRate, true);
// end of crossover and mutation definitions
////////////////////////////////////////////
// END Modify definitions of objects by eventually add parameters
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
// from now on, you do not need to modify anything
// though you CAN add things to the checkpointing (see tutorial)
// now build the eoGenOp:
// to simulate SGA (crossover with proba pCross + mutation with proba pMut
// we must construct
// a sequential combination of
// with proba 1, a proportional combination of
// a QuadCopy and our crossover
// with proba pMut, our mutation
// but of course you're free to use any smart combination you could think of
// especially, if you have to use eoBinOp rather than eoQuad Op youùll have
// to modify that part
// First read the individual level parameters
eoValueParam<double>& pCrossParam = _parser.createParam(0.6, "pCross", "Probability of Crossover", 'C', "Variation Operators" );
// minimum check
if ( (pCrossParam.value() < 0) || (pCrossParam.value() > 1) )
throw runtime_error("Invalid pCross");
eoValueParam<double>& pMutParam = _parser.createParam(0.1, "pMut", "Probability of Mutation", 'M', "Variation Operators" );
// minimum check
if ( (pMutParam.value() < 0) || (pMutParam.value() > 1) )
throw runtime_error("Invalid pMut");
// the crossover - with probability pCross
eoProportionalOp<Indi> * propOp = new eoProportionalOp<Indi> ;
_state.storeFunctor(propOp);
eoQuadOp<Indi> *ptQuad = new eoQuadCloneOp<Indi>;
_state.storeFunctor(ptQuad);
propOp->add(*propXover, pCrossParam.value()); // crossover, with proba pcross
propOp->add(*ptQuad, 1-pCrossParam.value()); // nothing, with proba 1-pcross
// now the sequential
eoSequentialOp<Indi> *op = new eoSequentialOp<Indi>;
_state.storeFunctor(op);
op->add(*propOp, 1.0); // always do combined crossover
op->add(*propMutation, pMutParam.value()); // then mutation, with proba pmut
// that's it - return a reference
return *op;
}
#endif