GOing to the generic operators: some additions (eoGeneric*)

and some modifications in eoFixedLength and eoVariableLength.
This commit is contained in:
evomarc 2001-01-11 10:48:31 +00:00
commit 4b2bb7f564
9 changed files with 788 additions and 15 deletions

View file

@ -46,7 +46,17 @@ class eoFixedLength : public EO<FitT>, public std::vector<GeneType>
eoFixedLength(unsigned size = 0, GeneType value = GeneType()) : EO<FitT>(), std::vector<GeneType>(size, value)
{}
/// to avoid conflicts between EO::operator< and vector<double>::operator<
// we can't have a Ctor from a vector, it would create ambiguity
// with the copy Ctor
void value(std::vector<GeneType> _v)
{
if (_v.size() != size())
throw runtime_error("Wrong size in vector assignation in eoFixedLength");
copy(_v.begin(), _v.end(), begin());
invalidate();
}
/// to avoid conflicts between EO::operator< and vector<GeneType>::operator<
bool operator<(const eoFixedLength<FitT, GeneType>& _eo) const
{
return EO<FitT>::operator<(_eo);

75
eo/src/eoGenericBinOp.h Normal file
View file

@ -0,0 +1,75 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoGenericBinOp.h
// (c) GeNeura Team, 2000 - EEAAX 1999 - Maarten Keijzer 2000
/*
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
mak@dhi.dk
*/
//-----------------------------------------------------------------------------
#ifndef _eoGenericBinOp_h
#define _eoGenericBinOp_h
#include <eoOp.h>
/** Contains base classes for generic binary operators for eoFixedLength
and eoVariableLength (They also derive from the eoOp) as well as
the corresponding converters to actual Ops.
*/
/** eoGenericBinOp is the generic binary operator:
it takes two arguments, modifies the first one, and returns a boolean
indicating if the argument has actually been modified
*/
template <class EOT>
class eoGenericBinOp: public eoOp<EOT>, public eoBF<EOT &, const EOT &, bool>
{
public:
/// Ctor
eoGenericBinOp()
: eoOp<EOT>( eoOp<EOT>::binary ) {};
virtual string className() const {return "eoGenericBinOp";};
};
/** Converter from eoGenericBinOp to eoBinOp
the only thinig to do is to transform the boolean into invalidation
*/
template <class EOT>
class eoGeneric2TrueBinOp: public eoBinOp<EOT>
{
public:
/// Ctor
eoGeneric2TrueBinOp(eoGenericBinOp<EOT> & _binOp)
: binOp( _binOp ) {};
virtual string className() const {return "eoGeneric2TrueBinOp";}
virtual void operator()(EOT & _eo1, const EOT & _eo2)
{
if (binOp(_eo1, _eo2))
_eo1.invalidate();
}
private:
eoGenericBinOp<EOT> & binOp;
};
#endif

75
eo/src/eoGenericMonOp.h Normal file
View file

@ -0,0 +1,75 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoGenericMonOp.h
// (c) GeNeura Team, 2000 - EEAAX 1999 - Maarten Keijzer 2000
/*
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
mak@dhi.dk
*/
//-----------------------------------------------------------------------------
#ifndef _eoGenericMonOp_h
#define _eoGenericMonOp_h
#include <eoOp.h>
/** Contains base classes for generic operators for eoFixedLength
and eoVariableLength (They also derive from the eoOp) as well as
the corresponding converters to actual Ops.
*/
/** eoGenericMonOp is the generic unary operator:
it takes one argument, and returns a boolean indicating if the argument
has been modified
*/
template <class EOT>
class eoGenericMonOp: public eoOp<EOT>, public eoUF<EOT&, bool>
{
public:
/// Ctor
eoGenericMonOp()
: eoOp<EOT>( eoOp<EOT>::unary ) {};
virtual string className() const {return "eoGenericMonOp";};
};
/** COnverter from eoGenericMonOp to eoMonOp
the only thinig to do is to transform the boolean into invalidation
*/
template <class EOT>
class eoGeneric2TrueMonOp: public eoMonOp<EOT>
{
public:
/// Ctor
eoGeneric2TrueMonOp(eoGenericMonOp<EOT> & _monOp)
: monOp( _monOp ) {};
virtual string className() const {return "eoGeneric2trueMonOp";}
virtual void operator()(EOT & _eo)
{
if (monOp(_eo))
_eo.invalidate();
}
private:
eoGenericMonOp<EOT> & monOp;
};
#endif

83
eo/src/eoGenericQuadOp.h Normal file
View file

@ -0,0 +1,83 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoGenericQuadOp.h
// (c) GeNeura Team, 2000 - EEAAX 1999 - Maarten Keijzer 2000
/*
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
mak@dhi.dk
*/
//-----------------------------------------------------------------------------
#ifndef _eoGenericQuadOp_h
#define _eoGenericQuadOp_h
#include <eoOp.h>
/** Contains base classes for generic quadratic operators for eoFixedLength
and eoVariableLength (They also derive from the eoOp) as well as
the corresponding converters to actual Ops.
*/
/** eoGenericQuadOp is the generic quadratic operator:
it takes two arguments, modifies the first one, and returns a boolean
indicating if the arguments have actually been modified
WARNING: even if only 1 argument is modified, it should return true,
and both fitnesses will be invalidated. It is assumed that
quadratic operators do some exchange of genetic material, so
if one is modified, the other is, too!
*/
template <class EOT>
class eoGenericQuadOp: public eoOp<EOT>, public eoBF<EOT &, EOT &, bool>
{
public:
/// Ctor
eoGenericQuadOp()
: eoOp<EOT>( eoOp<EOT>::binary ) {};
virtual string className() const {return "eoGenericQuadOp";};
};
/** Converter from eoGenericQuadOp to eoQuadOp
the only thinig to do is to transform the boolean into invalidation
*/
template <class EOT>
class eoGeneric2TrueQuadOp: public eoQuadOp<EOT>
{
public:
/// Ctor
eoGeneric2TrueQuadOp(eoGenericQuadOp<EOT> & _quadOp)
: quadOp( _quadOp ) {};
virtual string className() const {return "eoGeneric2TrueQuadOp";}
virtual void operator()(EOT & _eo1, EOT & _eo2)
{
if (quadOp(_eo1, _eo2))
{
_eo1.invalidate();
_eo2.invalidate();
}
}
private:
eoGenericQuadOp<EOT> & quadOp;
};
#endif

View file

@ -105,6 +105,7 @@ public:
/** Quadratic genetic operator: subclasses eoOp, and defines basically the
operator() with two operands, both can be modified.
*/
#define eoQuadraticOp eoQuadOp
template<class EOType>
class eoQuadraticOp: public eoOp<EOType>, public eoBF<EOType&, EOType&, void> {
@ -115,6 +116,29 @@ public:
virtual string className() const {return "eoQuadOp";};
};
// Turning an eoBinOp into an eoQuadOp is generic:
template <class EOT>
class eoQuad2BinOp: public eoBinOp<EOT>
{
public:
// Ctor, from an eoQuadOp
eoQuad2BinOp(eoQuadOp<EOT> & _quadOp) : quadOp(_quadOp) {}
// Operator() simply calls embedded quadOp operator() with dummy second arg
void operator()(EOT & _eo1, const EOT & _eo2)
{
EOT eoTmp = _eo2; // a copy that can be modified
// if the embedded eoQuadOp is not symmetrical,
// the result might be biased - hence the flip ...
if (eo::rng.flip(0.5))
quadOp(_eo1, eoTmp); // both are modified - that's all
else
quadOp(eoTmp, _eo1); // both are modified - that's all
}
private:
eoQuadOp<EOT> & quadOp;
};
// some forward declarations

View file

@ -79,15 +79,24 @@ class eoPop: public vector<EOT>, public eoObject, public eoPersistent
}
};
/** SAME Initialization task than init. ctor, but is NOT a constructor
/** appends random guys at end of pop.
Can be used to initialize it pop is empty
@param _popSize total population size
@param _chromInit Initialization routine, produces EO's, needs to be an eoInit
*/
void append( unsigned _popSize, eoInit<EOT>& _chromInit )
void append( unsigned _newPopSize, eoInit<EOT>& _chromInit )
{
resize(size()+_popSize); // adjust the size
for ( unsigned i = 0; i < _popSize; i++ )
unsigned oldSize = size();
if (_newPopSize < oldSize)
{
throw runtime_error("New size smaller than old size in pop.append");
return;
}
if (_newPopSize == oldSize)
return;
resize(_newPopSize); // adjust the size
for ( unsigned i = oldSize; i < _popSize; i++ )
{
_chromInit(operator[](i));
}

View file

@ -27,21 +27,34 @@
#ifndef _eoVariableLength_h
#define _eoVariableLength_h
#include <list>
#include <vector>
/**
Base class for variable length chromosomes. Derives from EO and list,
Base class for variable length chromosomes. Derives from EO and vector,
redirects the smaller than operator to EO (fitness based comparison),
and implements the virtual functions printOn() and readFrom()
*/
template <class FitT, class GeneType>
class eoVariableLength : public EO<FitT>, public std::list<GeneType>
class eoVariableLength : public EO<FitT>, public std::vector<GeneType>
{
public :
typedef GeneType AtomType;
typedef std::list<GeneType> ContainerType;
typedef std::vector<GeneType> ContainerType;
// default ctor
eoVariableLength(unsigned size = 0, GeneType value = GeneType()) : EO<FitT>(), std::vector<GeneType>(size, value)
{}
// we can't have a Ctor from a vector, it would create ambiguity
// with the copy Ctor
void value(std::vector<GeneType> _v)
{
resize(_v.size());
copy(_v.begin(), _v.end(), begin());
invalidate();
}
/// printing...
void printOn(ostream& os) const
@ -51,7 +64,7 @@ class eoVariableLength : public EO<FitT>, public std::list<GeneType>
os << size() << ' ';
std::copy(begin(), end(), ostream_iterator<double>(os));
std::copy(begin(), end(), ostream_iterator<AtomType>(os, " "));
}
/// reading...
@ -62,14 +75,14 @@ class eoVariableLength : public EO<FitT>, public std::list<GeneType>
unsigned sz;
is >> sz;
resize(0);
resize(sz);
unsigned i;
unsigned gene;
for (i = 0; i < sz; ++i)
{
is >> gene;
push_back(gene);
AtomType atom;
is >> atom;
operator[](i) = atom;
}
}
@ -81,7 +94,7 @@ class eoVariableLength : public EO<FitT>, public std::list<GeneType>
};
/// to avoid conflicts between EO::operator< and vector<double>::operator<
/// to avoid conflicts between EO::operator< and vector<GeneType>::operator<
template <class FitT, class GeneType>
bool operator<(const eoVariableLength<FitT, GeneType>& _eo1, const eoVariableLength<FitT, GeneType>& _eo2)
{

View file

@ -0,0 +1,294 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoVariableLengthCrossover.h
// (c) GeNeura Team, 2000 - EEAAX 1999 - Maarten Keijzer 2000
/*
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
mak@dhi.dk
*/
//-----------------------------------------------------------------------------
#ifndef _eoVariableLengthCrossover_h
#define _eoVariableLengthCrossover_h
#include <eoFunctor.h>
#include <eoVariableLength.h>
#include <eoGenericBinOp.h>
#include <eoGenericQuadOp.h>
/**
Base classes for generic crossovers on variable length chromosomes.
Basically, they exchange genes - we need some matching information to apply
atom crossover
*/
//* A helper class for choosing which genes to exchange
template <class Atom>
class eoAtomExchange : public eoBF<unsigned, Atom &, bool>
{
public:
// a function to initlialize - to be called before every crossover
virtual void randomize(unsigned int, unsigned int){}
};
//* Uniform crossover - well, not really for FixedLength
template <class Atom>
class eoUniformAtomExchange: public eoAtomExchange<Atom>
{
public:
eoUniformAtomExchange(double _rate=0.5):rate(_rate){}
// randomize: fill the mask: the exchange will be simulated first
// to see if sizes are OK, so it must be repeatable
void randomize(unsigned _size1, unsigned _size2)
{
mask.resize(_size1 + _size2);
for (unsigned i=0; i<_size1+_size2; i++)
mask[i]=eo::rng.flip(rate);
}
// the operator() simply returns the mask booleans in turn
bool operator()(unsigned _i, Atom & )
{
return mask[_i];
}
private:
double rate;
vector<bool> mask;
};
/** Exchange Crossover using an AtomExchange
*/
template <class EOT>
class eoVlAtomExchangeQuadOp : public eoGenericQuadOp<EOT>
{
public :
typedef typename EOT::AtomType AtomType;
// default ctor: requires bounds on number of genes + a rate
eoVlAtomExchangeQuadOp(unsigned _Min, unsigned _Max,
eoAtomExchange<AtomType>& _atomExchange):
Min(_Min), Max(_Max), atomExchange(_atomExchange) {}
bool operator()(EOT & _eo1, EOT & _eo2)
{
EOT tmp1, tmp2; // empty individuals
unsigned index=0;
// main loop: until sizes are OK, do only simulated exchange
unsigned i, i1, i2;
do {
// "initialize the AtomExchange
atomExchange.randomize(_eo1.size(), _eo2.size());
// simulate crossover
i1=i2=0;
for (i=0; i<_eo1.size(); i++)
{
if (atomExchange(i, _eo1[i]))
i1++;
else
i2++;
}
for (i=0; i<_eo2.size(); i++)
{
if (atomExchange(i, _eo2[i]))
i2++;
else
i1++;
}
index++;
} while ( ( (i1<Min) || (i2<Min) ||
(i1>Max) || (i2>Max) )
&& (index<10000) );
if (index >= 10000)
{
cout << "Warning: impossible to generate individual of the right size in 10000 trials\n";
return false;
}
// here we know we have the right sizes: do the actual exchange
for (i=0; i<_eo1.size(); i++)
{
if (atomExchange(i, _eo1[i]))
tmp1.push_back(_eo1[i]);
else
tmp2.push_back(_eo1[i]);
}
for (i=0; i<_eo2.size(); i++)
{
if (atomExchange(i, _eo2[i]))
tmp2.push_back(_eo2[i]);
else
tmp1.push_back(_eo2[i]);
}
// and put everything back in place
_eo1.swap(tmp1);
_eo2.swap(tmp2);
return true; // should we test that? Yes, but no time now
}
private:
unsigned Min, Max;
eoAtomExchange<AtomType> & atomExchange;
};
/** Direct Uniform Exchange of genes (obsolete, already :-)
A very primitive version, that does no verification at all!!!
NEEDS to be improved - but no time now :-(((
Especially, if both guys have maximal size, it will take a lot of time
to generate 2 offspring that both are not oversized!!!
Also, we should first check for identical atoms, and copy them to the
offspring, and only after that exchange the other ones (Radcliffe's RRR).
*/
template <class EOT>
class eoVlUniformQuadOp : public eoGenericQuadOp<EOT>
{
public :
typedef typename EOT::AtomType AtomType;
// default ctor: requires bounds on number of genes + a rate
eoVlUniformQuadOp(unsigned _Min, unsigned _Max, double _rate=0.5) :
Min(_Min), Max(_Max), rate(_rate) {}
bool operator()(EOT & _eo1, EOT & _eo2)
{
unsigned i;
EOT tmp1, tmp2;
unsigned index=0;
do {
for (i=0; i<_eo1.size(); i++)
{
if (eo::rng.flip(rate))
tmp1.push_back(_eo1[i]);
else
tmp2.push_back(_eo1[i]);
// here we should look for _eo1[i] inside _eo2 and erase it if found!
}
for (i=0; i<_eo2.size(); i++)
{
if (eo::rng.flip(rate))
tmp1.push_back(_eo2[i]);
else
tmp2.push_back(_eo2[i]);
}
index++;
} while ( ( (tmp1.size()<Min) || (tmp2.size()<Min) ||
(tmp1.size()>Max) || (tmp2.size()>Max) )
&& (index<10000) );
if (index >= 10000)
{
cout << "Warning: impossible to generate individual of the right size in 10000 trials\n";
return false;
}
_eo1.swap(tmp1);
_eo2.swap(tmp2);
return true; // should we test that?
}
private:
unsigned Min, Max;
double rate;
};
/** Direct Uniform Exchange of genes for Variable Length, BINARY version
A very primitive version, that does no verification at all!!!
NEEDS to be improved - but no time now :-(((
Especially, if both guys have maximal size, it will take some time
to generate even 1 offspring that is not oversized!!!
Also, we should first check for identical atoms, and copy them to the
offspring, and only after that exchange the other ones (Radcliffe's RRR).
*/
template <class EOT>
class eoVlUniformBinOp : public eoGenericBinOp<EOT>
{
public :
typedef typename EOT::AtomType AtomType;
// default ctor: requires bounds on number of genes + a rate
eoVlUniformBinOp(unsigned _Min, unsigned _Max, double _rate=0.5) :
Min(_Min), Max(_Max), rate(_rate) {}
bool operator()(EOT & _eo1, const EOT & _eo2)
{
unsigned i;
EOT tmp1;
bool tmpIsOne=true, tmpIsTwo=true;
unsigned index=0;
do {
for (i=0; i<_eo1.size(); i++)
{
if (eo::rng.flip(rate))
{
tmp1.push_back(_eo1[i]);
tmpIsTwo = false;
}
else
tmpIsOne=false;
// we should look for _eo1[i] inside _eo2 and erase it there if found!
}
for (i=0; i<_eo2.size(); i++)
{
if (! eo::rng.flip(rate))
{
tmp1.push_back(_eo2[i]);
tmpIsOne = false;
}
else
tmpIsTwo = false;
}
index++;
} while ( ( (tmp1.size()<Min) || (tmp1.size()>Max) )
&& (index<10000) );
// this while condition is not optimal, as it may take some time
if (index >= 10000)
{
cout << "Warning: impossible to generate individual of the right size in 10000 trials\n";
return false;
}
_eo1.swap(tmp1);
if (tmpIsTwo)
{
// _eo1.fitness(_eo2.fitness()); NO FITNESS EXISTS HERE!
return false;
}
if (tmpIsOne) // already has the right fitness
{ // WRONG: NO FITNESS EXISTS HERE!
return false;
}
return true; // there were some modifications...
}
private:
unsigned Min, Max;
double rate;
};
#endif

View file

@ -0,0 +1,190 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoVariableLengthMutation.h
// (c) GeNeura Team, 2000 - EEAAX 1999 - Maarten Keijzer 2000
/*
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
mak@dhi.dk
*/
//-----------------------------------------------------------------------------
#ifndef _eoVariableLengthMutation_h
#define _eoVariableLengthMutation_h
#include <eoFunctor.h>
#include <eoVariableLength.h>
#include <eoGenericMonOp.h>
/**
Base classes for generic mutations on variable length chromosomes.
THey all require a generic mutation for their simple genes
*/
/** THis ones applies its atomic mutation to all the genes
*/
template <class EOT>
class eoVlAllMutation : public eoGenericMonOp<EOT>
{
public :
typedef typename EOT::AtomType AtomType;
// default ctor: requires an Atom mutation
eoVlAllMutation(eoGenericMonOp<AtomType> & _atomMutation) :
atomMutation(_atomMutation) {}
bool operator()(EOT & _eo)
{
bool modified=false;
for (unsigned i=0; i<_eo.size(); i++)
{
if (atomMutation(_eo[i]))
modified = true;
}
return modified;
}
private:
eoGenericMonOp<AtomType> & atomMutation;
};
/** This ones applies its atomic mutation to a fixed
number of genes (1 by default)
*/
template <class EOT>
class eoVlKMutation : public eoGenericMonOp<EOT>
{
public :
typedef typename EOT::AtomType AtomType;
// default ctor: requires an Atom mutation
eoVlKMutation(eoGenericMonOp<AtomType> & _atomMutation, unsigned _nb=1) :
nb(_nb), atomMutation(_atomMutation) {}
bool operator()(EOT & _eo)
{
bool modified=false;
for (unsigned k=0; k<nb; k++)
{
unsigned i = rng.random(_eo.size()); // we don't test for duplicates...
if (atomMutation(_eo[i]))
modified = true;
}
return modified;
}
private:
unsigned nb;
eoGenericMonOp<AtomType> & atomMutation;
};
/** Addition of a gene
Is inserted at a random position - so can be applied to both
order-dependent and order-independent
*/
template <class EOT>
class eoVlAddMutation : public eoGenericMonOp<EOT>
{
public :
typedef typename EOT::AtomType AtomType;
/** default ctor
* @param nMax max number of atoms
* @param _atomInit an Atom initializer
*/
eoVlAddMutation(unsigned _nMax, eoInit<AtomType> & _atomInit) :
nMax(_nMax), atomInit(_atomInit) {}
bool operator()(EOT & _eo)
{
if (_eo.size() >= nMax)
return false; // unmodifed
AtomType atom;
atomInit(atom);
unsigned pos = rng.random(_eo.size()+1);
_eo.insert(_eo.begin()+pos, atom);
return true;
}
private:
unsigned nMax;
eoInit<AtomType> & atomInit;
};
//* A helper class for choosing which site to delete
template <class EOT>
class eoGeneDelChooser : public eoUF<EOT &, unsigned int>
{};
//* Unifirm choice of gene to delete
template <class EOT>
class eoUniformGeneChooser: public eoGeneDelChooser<EOT>
{
public:
eoUniformGeneChooser(){}
unsigned operator()(EOT & _eo)
{
return eo::rng.random(_eo.size());
}
};
/** Deletion of a gene
By default at a random position, but a "chooser" can be specified
can of course be applied to both order-dependent and order-independent
*/
template <class EOT>
class eoVlDelMutation : public eoGenericMonOp<EOT>
{
public :
typedef typename EOT::AtomType AtomType;
/** ctor with an external gene chooser
* @param nMin min number of atoms t oleave in the individual
* @param _geneChooser an eoGeneCHooser to choose which one to delete
*/
eoVlDelMutation(unsigned _nMin, eoGeneDelChooser<EOT> & _chooser) :
nMin(_nMin), uChooser(), chooser(_chooser) {}
/** ctor with unifirm gebe chooser
* @param nMin min number of atoms t oleave in the individual
*/
eoVlDelMutation(unsigned _nMin) :
nMin(_nMin), uChooser(), chooser(uChooser) {}
bool operator()(EOT & _eo)
{
if (_eo.size() <= nMin)
return false; // unmodifed
unsigned pos = chooser(_eo);
_eo.erase(_eo.begin()+pos);
return true;
}
private:
unsigned nMin;
eoUniformGeneChooser<EOT> uChooser;
eoGeneDelChooser<EOT> & chooser;
};
#endif