Well, what do you know, major commit.

Changed the signature of eoMon, eoBin and eoQuadOp to return a bool,
without invalidating fitness. Added a set of invalidators to take over
that job (see for instance eoSGA and eoSGATransform how this can transparantly used)

Derived eoState from eoFunctorStore (for convenience, from a design perspective this may sound wrong)

Added a wrap_op function that does the wrapping for you (see eoOpContainer how this made this functor
exceedingly less hairy). Checked all the tests removed the eoGeneric*Op family (not needed anymore)
and of course changed all the operators to reflect the change (and found a few that didn't
invalidate the fitness, thus really pointing out the advantage of the current approach)
This commit is contained in:
maartenkeijzer 2001-02-14 10:35:26 +00:00
commit 3a9b5a0e7e
30 changed files with 651 additions and 564 deletions

View file

@ -10,11 +10,10 @@ DEPS = $(top_builddir)/src/libeo.a $(top_builddir)/src/utils/libeoutils.a
INCLUDES = -I$(top_builddir)/src
LDADDS = $(top_builddir)/src/libeo.a $(top_builddir)/src/utils/libeoutils.a
CXXFLAGS = -g
###############################################################################
bin_PROGRAMS = gprop
###############################################################################
gprop_SOURCES = gprop.cc

View file

@ -109,11 +109,11 @@ mlp::set trn_set, val_set, tst_set;
class eoChromMutation: public eoMonOp<Chrom>
{
public:
void operator()(Chrom& chrom)
bool operator()(Chrom& chrom)
{
mse::net tmp(chrom);
tmp.train(trn_set, 10, 0, 0.001);
chrom.invalidate();
return true;
}
};
@ -124,7 +124,7 @@ public:
class eoChromXover: public eoQuadOp<Chrom>
{
public:
void operator()(Chrom& chrom1, Chrom& chrom2)
bool operator()(Chrom& chrom1, Chrom& chrom2)
{
chrom1.normalize();
chrom2.desaturate();
@ -132,8 +132,8 @@ public:
mse::net tmp1(chrom1), tmp2(chrom2);
tmp1.train(trn_set, 100, 0, 0.001);
tmp2.train(trn_set, 100, 0, 0.001);
chrom1.invalidate();
chrom2.invalidate();
return true;
}
};

View file

@ -116,7 +116,7 @@ void init_eoChromEvaluator(const unsigned& c, const unsigned& l, string s)
uniform_generator<int> color(0, num_colors);
generate(solution.begin(), solution.end(), color);
}
solution.fitness(eoChromEvaluator(solution));
}
@ -143,14 +143,14 @@ public:
class eoChromMutation: public eoMonOp<Chrom>
{
// many operators in one :(
void operator()(Chrom& chrom)
bool operator()(Chrom& chrom)
{
uniform_generator<unsigned> what(0, 2);
uniform_generator<unsigned> position(0, chrom.size());
switch(what())
{
case 0:
case 0:
{
// mutation
uniform_generator<int> color(0, num_colors);
@ -171,7 +171,7 @@ class eoChromMutation: public eoMonOp<Chrom>
}
}
chrom.invalidate();
return true;
}
};
@ -182,12 +182,11 @@ class eoChromMutation: public eoMonOp<Chrom>
class eoChromXover: public eoQuadOp<Chrom>
{
public:
void operator()(Chrom& chrom1, Chrom& chrom2)
bool operator()(Chrom& chrom1, Chrom& chrom2)
{
uniform_generator<unsigned> position(0, chrom1.size());
swap_ranges(chrom1.begin(), chrom1.begin() + position(), chrom2.begin());
chrom1.invalidate();
chrom2.invalidate();
return true;
}
};
@ -195,6 +194,6 @@ public:
#endif // mastermind_h
// Local Variables:
// mode:C++
// Local Variables:
// mode:C++
// End:

View file

@ -8,7 +8,7 @@ SUBDIRS = es ga gp utils other
CPPFLAGS = -O2
lib_LIBRARIES = libeo.a
libeo_a_SOURCES = eoPrintable.cpp eoPersistent.cpp eoFunctorStore.cpp
libeo_a_SOURCES = eoPrintable.cpp eoPersistent.cpp eoFunctorStore.cpp
libeoincdir = $(includedir)/eo
libeoinc_HEADERS = eo EO.h apply.h eoAlgo.h eoBreed.h eoCombinedContinue.h eoContinue.h eoCounter.h eoDetSelect.h eoDetTournamentSelect.h eoEasyEA.h eoEvalFunc.h eoEvalFuncPtr.h eoFactory.h eoFitContinue.h eoFitnessScalingSelect.h eoFixedLength.h eoFunctor.h eoFunctorStore.h eoGenContinue.h eoGenericBinOp.h eoGenericMonOp.h eoGenericQuadOp.h eoInit.h eoMerge.h eoMergeReduce.h eoObject.h eoOp.h eoOpSelMason.h eoPersistent.h eoPop.h eoPrintable.h eoProportionalCombinedOp.h eoProportionalSelect.h eoRandomSelect.h eoRankingSelect.h eoReduce.h eoReduceMerge.h eoReplacement.h eoSGA.h eoSGATransform.h eoScalarFitness.h eoSelect.h eoSelectFactory.h eoSelectMany.h eoSelectNumber.h eoSelectOne.h eoSelectPerc.h eoSteadyFitContinue.h eoStochTournamentSelect.h eoSurviveAndDie.h eoTransform.h eoVariableLength.h eoVariableLengthCrossover.h eoVariableLengthMutation.h es.h ga.h
libeoinc_HEADERS = eo EO.h apply.h eoAlgo.h eoBreed.h eoCombinedContinue.h eoContinue.h eoCounter.h eoDetSelect.h eoDetTournamentSelect.h eoEasyEA.h eoEvalFunc.h eoEvalFuncPtr.h eoFactory.h eoFitContinue.h eoFitnessScalingSelect.h eoFixedLength.h eoFunctor.h eoFunctorStore.h eoGenContinue.h eoInvalidateOps.h eoInit.h eoMerge.h eoMergeReduce.h eoObject.h eoOp.h eoOpSelMason.h eoPersistent.h eoPop.h eoPrintable.h eoProportionalCombinedOp.h eoProportionalSelect.h eoRandomSelect.h eoRankingSelect.h eoReduce.h eoReduceMerge.h eoReplacement.h eoSGA.h eoSGATransform.h eoScalarFitness.h eoSelect.h eoSelectFactory.h eoSelectMany.h eoSelectNumber.h eoSelectOne.h eoSelectPerc.h eoSteadyFitContinue.h eoStochTournamentSelect.h eoSurviveAndDie.h eoTransform.h eoVariableLength.h eoVariableLengthCrossover.h eoVariableLengthMutation.h es.h ga.h

View file

@ -196,7 +196,7 @@ template <class Procedure>
eoProcedureCounter<Procedure>& make_counter(eoFunctorBase::procedure_tag, Procedure& _proc, eoFunctorStore& store, std::string _name = "proc_counter")
{
eoProcedureCounter<Procedure>* result = new eoProcedureCounter<Procedure>(_proc, _name);
store.add(result);
store.storeFunctor(result);
return *result;
}
@ -204,7 +204,7 @@ template <class UnaryFunctor>
eoUnaryFunctorCounter<UnaryFunctor>& make_counter(eoFunctorBase::unary_function_tag, UnaryFunctor& _proc, eoFunctorStore& store, std::string _name = "uf_counter")
{
eoUnaryFunctorCounter<UnaryFunctor>* result = new eoUnaryFunctorCounter<UnaryFunctor>(_proc, _name);
store.add(result);
store.storeFunctor(result);
return *result;
}
@ -212,7 +212,7 @@ template <class BinaryFunctor>
eoBinaryFunctorCounter<BinaryFunctor>& make_counter(eoFunctorBase::binary_function_tag, BinaryFunctor& _proc, eoFunctorStore& store, std::string _name = "uf_counter")
{
eoBinaryFunctorCounter<BinaryFunctor>* result = new eoBinaryFunctorCounter<BinaryFunctor>(_proc, _name);
store.add(result);
store.storeFunctor(result);
return *result;
}

View file

@ -34,9 +34,9 @@ class eoFunctorBase;
/**
eoFunctorStore is a class that stores functors that are allocated on the
heap. This class can be used in factories to store allocated memory for
dynamically created functors.
dynamically created functors.
*/
class eoFunctorStore
class eoFunctorStore
{
public :
@ -45,13 +45,19 @@ class eoFunctorStore
~eoFunctorStore();
/// Add an eoFunctorBase to the store
void add(eoFunctorBase* r) { vec.push_back(r); }
template <class Functor>
Functor& storeFunctor(Functor* r)
{
// If the compiler complains about the following line, check if you really are giving it a pointer to an eoFunctorBase derived object
vec.push_back(r);
return *r;
}
private :
/// no copying allowed
eoFunctorStore(const eoFunctorStore&);
/// no copying allowed
eoFunctorStore operator=(const eoFunctorStore&);
std::vector<eoFunctorBase*> vec;

View file

@ -1,9 +1,9 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoGenOp.h
// eoGenOp.h
// (c) Maarten Keijzer and Marc Schoenauer, 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
@ -18,7 +18,7 @@
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: mkeijzer@dhi.dk
Contact: mak@dhi.dk
Marc.Schoenauer@polytechnique.fr
*/
//-----------------------------------------------------------------------------
@ -28,7 +28,7 @@
#include <eoOp.h>
#include <eoPopulator.h>
#include <eoFunctorStore.h>
/** @name General variation operators
@ -41,15 +41,22 @@ thanks to the friend class eoPopulator
/** The base class for General Operators
Subclass this operator is you want to define an operator that falls
outside of the eoMonOp, eoBinOp, eoQuadOp classification. The argument
the operator will receive is an eoPopulator, which is a wrapper around
the original population, is an instantiation of the next population and
has often a selection function embedded in it to select new individuals.
Note that the actual work is performed in the apply function.
*/
template <class EOT>
class eoGenOp : public eoOp<EOT>, public eoUF<eoPopulator<EOT> &, void>
{
public :
/// Ctor that honors its superclass
eoGenOp(): eoOp<EOT>( eoOp<EOT>::general ) {}
eoGenOp(): eoOp<EOT>( eoOp<EOT>::general ) {}
virtual unsigned max_production(void) = 0;
virtual unsigned max_production(void) = 0;
virtual string className() = 0;
void operator()(eoPopulator<EOT>& _pop)
{
@ -57,6 +64,7 @@ class eoGenOp : public eoOp<EOT>, public eoUF<eoPopulator<EOT> &, void>
apply(_pop);
}
protected :
/** the function that will do the work
*/
@ -75,7 +83,8 @@ class eoMonGenOp : public eoGenOp<EOT>
void apply(eoPopulator<EOT>& _it)
{
op(*_it); // look how simple
if (op(*_it))
(*_it).invalidate(); // look how simple
}
string className() {return op.className();}
@ -101,8 +110,9 @@ class eoBinGenOp : public eoGenOp<EOT>
{
EOT& a = *_pop;
EOT& b = *++_pop;
op(a, b);
_pop.erase();
if (op(a, b))
a.invalidate();
_pop.erase(); // erase the b from the next population
}
string className() {return op.className();}
@ -115,17 +125,18 @@ template <class EOT>
class eoSelBinGenOp : public eoGenOp<EOT>
{
public:
eoSelBinGenOp(eoBinOp<EOT>& _op, eoSelectOne<EOT>& _sel) :
eoSelBinGenOp(eoBinOp<EOT>& _op, eoSelectOne<EOT>& _sel) :
op(_op), sel(_sel) {}
unsigned max_production(void) { return 1; }
void apply(eoPopulator<EOT>& _pop)
{ // _pop.source() gets the original population, an eoVecOp can make use of this as well
op(*_pop, sel(_pop.source()));
if (op(*_pop, sel(_pop.source())))
(*_pop).invalidate();
}
string className() {return op.className();}
private :
eoBinOp<EOT>& op;
eoSelectOne<EOT>& sel;
@ -147,7 +158,11 @@ class eoQuadGenOp : public eoGenOp<EOT>
EOT& a = *_pop;
EOT& b = *++_pop;
op(a, b);
if(op(a, b))
{
a.invalidate();
b.invalidate();
}
}
string className() {return op.className();}
@ -155,6 +170,41 @@ class eoQuadGenOp : public eoGenOp<EOT>
eoQuadOp<EOT>& op;
};
/**
Factory function for automagically creating references to an
eoGenOp object. Useful when you are too lazy to figure out
which wrapper belongs to which operator. The memory allocated
in the wrapper will be stored in a eoFunctorStore (eoState derives from this).
Therefore the memory will only be freed when the eoFunctorStore is deleted.
Make very sure that you are not using these wrappers after this happens.
You can use this function 'wrap_op' in the following way. Suppose you've
created an eoQuadOp<EOT> called my_quad, and you want to feed it to an eoTransform
derived class that expects an eoGenOp<EOT>. If you have an eoState lying around
(which is generally a good idea) you can say:
eoDerivedTransform<EOT> trans(eoGenOp<EOT>::wrap_op(my_quad, state), ...);
And as long as your state is not destroyed (by going out of scope for example,
your 'trans' functor will be usefull.
As a final note, you can also enter an eoGenOp as the argument. It will
not allocate memory then. This to make it even easier to use the wrap_op function.
For an example of how this is used, check the eoOpContainer class.
@see eoOpContainer
*/
template <class EOT>
eoGenOp<EOT>& wrap_op(eoOp<EOT>& _op, eoFunctorStore& _store)
{
switch(_op.getType())
{
case eoOp<EOT>::unary : return _store.storeFunctor(new eoMonGenOp<EOT>(static_cast<eoMonOp<EOT>&>(_op)));
case eoOp<EOT>::binary : return _store.storeFunctor(new eoBinGenOp<EOT>(static_cast<eoBinOp<EOT>&>(_op)));
case eoOp<EOT>::quadratic : return _store.storeFunctor(new eoQuadGenOp<EOT>(static_cast<eoQuadOp<EOT>&>(_op)));
case eoOp<EOT>::general : return static_cast<eoGenOp<EOT>&>(_op);
}
}
#endif

View file

@ -104,10 +104,11 @@ class eoInitAdaptor : public eoMonOp<EOT>
{
public :
eoInitAdaptor(eoInit<EOT>& _init) : init(_init) {}
void operator()(EOT& _eot)
bool operator()(EOT& _eot)
{
init(_eot);
return true;
}
private :

118
eo/src/eoInvalidateOps.h Normal file
View file

@ -0,0 +1,118 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoInvalidateOps.h
// (c) Maarten Keijzer 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
mak@dhi.dk
*/
//-----------------------------------------------------------------------------
#ifndef _eoInvalidateOps_h
#define _eoInvalidateOps_h
#include <eoOp.h>
/**
One of the invalidator operators. Use this one as a 'hat' on an operator
that is defined to work on a generic datatype. This functor will then check
the return type of the operator and invalidate the fitness of the individual.
This functor is used in algorithms that work with straight eoMonOp, eoBinOp
or eoQuadOp operators, for instance eoSGA. Note that eoGenOp derived operators
generally do invalidate the fitness of the objects they have changed.
*/
template <class EOT>
class eoInvalidateMonOp : public eoMonOp<EOT>
{
public:
eoInvalidateMonOp(eoMonOp<EOT>& _op) : op(_op) {}
bool operator()(EOT& _eo)
{
if (op(_eo))
_eo.invalidate();
return false; // we did change the thing, but it is already invalidated
}
private:
eoMonOp<EOT>& op;
};
/**
One of the invalidator operators. Use this one as a 'hat' on an operator
that is defined to work on a generic datatype. This functor will then check
the return type of the operator and invalidate the fitness of the individual.
This functor is used in algorithms that work with straight eoMonOp, eoBinOp
or eoQuadOp operators, for instance eoSGA. Note that eoGenOp derived operators
generally do invalidate the fitness of the objects they have changed.
*/
template <class EOT>
class eoInvalidateBinOp : public eoBinOp<EOT>
{
public:
eoInvalidateBinOp(eoBinOp<EOT>& _op) : op(_op) {}
bool operator()(EOT& _eo, const EOT& _eo2)
{
if (op(_eo, _eo2))
_eo.invalidate();
return false; // we did change the thing, but it is already invalidated
}
private:
eoBinOp<EOT>& op;
};
/**
One of the invalidator operators. Use this one as a 'hat' on an operator
that is defined to work on a generic datatype. This functor will then check
the return type of the operator and invalidate the fitness of the individual.
This functor is used in algorithms that work with straight eoMonOp, eoBinOp
or eoQuadOp operators, for instance eoSGA. Note that eoGenOp derived operators
generally do invalidate the fitness of the objects they have changed.
*/
template <class EOT>
class eoInvalidateQuadOp : public eoQuadOp<EOT>
{
public:
eoInvalidateQuadOp(eoQuadOp<EOT>& _op) : op(_op) {}
bool operator()(EOT& _eo1, EOT& _eo2)
{
if (op(_eo1, _eo2))
{
_eo1.invalidate();
_eo2.invalidate();
}
return false; // we did change the thing, but it is already invalidated
}
private:
eoQuadOp<EOT>& op;
};
#endif

View file

@ -29,23 +29,23 @@
#include <eoFunctor.h>
#include <utils/eoRNG.h>
/**
\defgroup operators
\defgroup Operators
Genetic Operators are used for various purposes
*/
/** @name Genetic operators
What is a genetic algorithm without genetic operators?
There is a genetic operator hierarchy, with eoOp as father and
eoMonOp (monary or unary operator), eoBinOp and eoQuadOp (binary operators)
What is a genetic algorithm without genetic operators?
There is a genetic operator hierarchy, with eoOp as father and
eoMonOp (monary or unary operator), eoBinOp and eoQuadOp (binary operators)
and eoGenOp (any number of inputs and outputs, see eoGenOp.h)
as subclasses.
Nobody should subclass eoOp, you should subclass eoGenOp, eoBinOp, eoQuadOp
or eoMonOp, those are the ones actually used here.
as subclasses.
Nobody should subclass eoOp, you should subclass eoGenOp, eoBinOp, eoQuadOp
or eoMonOp, those are the ones actually used here.
#eoOp#s are only printable objects, so if you want to build them
from a file, it has to be done in another class, namely factories.
Each hierarchy of #eoOp#s should have its own factory, which know
#eoOp#s are only printable objects, so if you want to build them
from a file, it has to be done in another class, namely factories.
Each hierarchy of #eoOp#s should have its own factory, which know
how to build them from a description in a file.
@author GeNeura Team, Marten Keijzer and Marc Schoenauer
@ -55,10 +55,13 @@ how to build them from a description in a file.
/** Abstract data types for EO operators.
* Genetic operators act on chromosomes, changing them. The type to
* instantiate them should be an eoObject, but in any case, they are
* type-specific; each kind of evolvable object can have its own operators
*/
Genetic operators act on chromosomes, changing them.
The type to use them on is problem specific. If your genotype
is a vector<bool>, there are operators that work specifically
on vector<bool>, but you might also find that generic operators
working on vector<T> are what you need.
*/
template<class EOType>
class eoOp
@ -88,9 +91,13 @@ private:
OpType opType;
};
/** eoMonOp is the monary operator: genetic operator that takes only one EO */
/**
eoMonOp is the monary operator: genetic operator that takes only one EO.
When defining your own, make sure that you return a boolean value
indicating that you have changed the content.
*/
template <class EOType>
class eoMonOp: public eoOp<EOType>, public eoUF<EOType&, void>
class eoMonOp: public eoOp<EOType>, public eoUF<EOType&, bool>
{
public:
/// Ctor
@ -100,11 +107,13 @@ public:
};
/** Binary genetic operator: subclasses eoOp, and defines basically the
/** Binary genetic operator: subclasses eoOp, and defines basically the
* operator() with two operands, only the first one can be modified
When defining your own, make sure that you return a boolean value
indicating that you have changed the content.
*/
template<class EOType>
class eoBinOp: public eoOp<EOType>, public eoBF<EOType&, const EOType&, void>
class eoBinOp: public eoOp<EOType>, public eoBF<EOType&, const EOType&, bool>
{
public:
/// Ctor
@ -113,11 +122,13 @@ public:
virtual string className() const {return "eoBinOp";};
};
/** Quad genetic operator: subclasses eoOp, and defines basically the
/** Quad genetic operator: subclasses eoOp, and defines basically the
operator() with two operands, both can be modified.
When defining your own, make sure that you return a boolean value
indicating that you have changed the content.
*/
template<class EOType>
class eoQuadOp: public eoOp<EOType>, public eoBF<EOType&, EOType&, void> {
class eoQuadOp: public eoOp<EOType>, public eoBF<EOType&, EOType&, bool> {
public:
/// Ctor
eoQuadOp()
@ -138,15 +149,15 @@ public:
/** Operator() simply calls embedded quadOp operator() with dummy second arg
*/
void operator()(EOT & _eo1, const EOT & _eo2)
bool operator()(EOT & _eo1, const EOT & _eo2)
{
EOT eoTmp = _eo2; // a copy that can be modified
// if the embedded eoQuadOp is not symmetrical,
// 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
return quadOp(_eo1, eoTmp); // both are modified - that's all
else
quadOp(eoTmp, _eo1); // both are modified - that's all
return quadOp(eoTmp, _eo1); // both are modified - that's all
}
private:

View file

@ -1,9 +1,9 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoOpContainer.h
// eoOpContainer.h
// (c) Maarten Keijzer and Marc Schoenauer, 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
@ -29,13 +29,13 @@
#include <eoGenOp.h>
/** eoOpContainer is a base class for the sequential and proportional selectors
* It takes care of wrapping the other operators,
* It takes care of wrapping the other operators,
* and deleting stuff that it has allocated
*
* Warning: all operators are added together with a rate (double)
* However, the meaning of this rate will be different in
* the differnet instances of eoOpContainer:
* an ***absolute*** probability in the sequential version, and
* However, the meaning of this rate will be different in
* the differnet instances of eoOpContainer:
* an ***absolute*** probability in the sequential version, and
* a ***relative*** weight in the proportional version
*/
template <class EOT>
@ -43,15 +43,11 @@ class eoOpContainer : public eoGenOp<EOT>
{
public :
/** Ctor: nothing much to do */
eoOpContainer() : max_to_produce(0) {}
eoOpContainer() : max_to_produce(2) {}
/** Dtor: delete all the GenOps created when wrapping simple ops
*/
virtual ~eoOpContainer(void)
{
for (unsigned i = 0; i < owned_genops.size(); ++i)
delete owned_genops[i];
}
virtual ~eoOpContainer(void) {}
/** for memory management (doesn't have to be very precise */
virtual unsigned max_production(void)
@ -59,57 +55,16 @@ class eoOpContainer : public eoGenOp<EOT>
return max_to_produce;
}
/** wraps then add a simple eoMonOp */
void add(eoMonOp<EOT>& _op, double _rate)
/**
Add an operator to the container, also give it a rate
(sidenote, it's much less hairy since I added the wrap_op is used)
*/
void add(eoOp<EOT>& _op, double _rate)
{
owned_genops.push_back(new eoMonGenOp<EOT>(_op));
ops.push_back(owned_genops.back());
ops.push_back(&wrap_op<EOT>(_op, store));
rates.push_back(_rate);
max_to_produce = max(max_to_produce,unsigned(1));
}
/** wraps then add a simple eoBinOp
* First case, no selector
*/
void add(eoBinOp<EOT>& _op, double _rate)
{
owned_genops.push_back(new eoBinGenOp<EOT>(_op));
ops.push_back(owned_genops.back());
rates.push_back(_rate);
max_to_produce = max(max_to_produce,unsigned(1));
}
/** wraps then add a simple eoBinOp
* Second case: a sepecific selector
*/
void add(eoBinOp<EOT>& _op, eoSelectOne<EOT> & _sel, double _rate)
{
owned_genops.push_back(new eoSelBinGenOp<EOT>(_op, _sel));
ops.push_back(owned_genops.back());
rates.push_back(_rate);
max_to_produce = max(max_to_produce,unsigned(1));
}
/** wraps then add a simple eoQuadOp */
void add(eoQuadOp<EOT>& _op, double _rate)
{
owned_genops.push_back(new eoQuadGenOp<EOT>(_op));
ops.push_back(owned_genops.back());
rates.push_back(_rate);
max_to_produce = max(max_to_produce,unsigned(2));
}
/** can add any GenOp */
void add(eoGenOp<EOT>& _op, double _rate)
{
ops.push_back(&_op);
rates.push_back(_rate);
max_to_produce = max(max_to_produce,_op.max_production());
max_to_produce = max(max_to_produce,ops.back()->max_production());
}
virtual string className() = 0;
@ -120,7 +75,7 @@ class eoOpContainer : public eoGenOp<EOT>
vector<eoGenOp<EOT>*> ops;
private :
vector<eoGenOp<EOT>*> owned_genops;
eoFunctorStore store;
unsigned max_to_produce;
};

View file

@ -28,19 +28,16 @@
#include <eoPrintable.h>
#include <eoFunctor.h>
#include <eoOp.h>
#include <eoGenericMonOp.h>
#include <eoGenericBinOp.h>
#include <eoGenericQuadOp.h>
#include <utils/eoRNG.h>
/**
\defgroup PropCombined operators
Combination of same-type Genetic Operators - Proportional choice
Combination of same-type Genetic Operators - Proportional choice
*/
/** @name PropCombined Genetic operators
This files contains the classes eoPropCombinedXXXOp (XXX in {Mon, Bin, Quad})
that allow to use more than a single operator of a specific class
This files contains the classes eoPropCombinedXXXOp (XXX in {Mon, Bin, Quad})
that allow to use more than a single operator of a specific class
into an algorithm, chosing by a roulette wheel based on user-defined rates
@author Marc Schoenauer
@ -52,7 +49,7 @@ into an algorithm, chosing by a roulette wheel based on user-defined rates
//// combined MonOp
//////////////////////////////////////////////////////
/** eoMonOp is the monary operator: genetic operator that takes only one EO
/** eoMonOp is the monary operator: genetic operator that takes only one EO
* now accepts generic operators
*/
@ -63,35 +60,16 @@ class eoPropCombinedMonOp: public eoMonOp<EOT>
public:
/// Ctor from a "true" operator
eoPropCombinedMonOp(eoMonOp<EOT> & _first, const double _rate)
{
ops.push_back(&_first);
rates.push_back(_rate);
}
/// Ctor from a generic operator
eoPropCombinedMonOp(eoGenericMonOp<EOT> & _first, const double _rate)
{
eoGeneric2TrueMonOp<EOT> *trueFirst =
new eoGeneric2TrueMonOp<EOT>(_first);
ops.push_back(trueFirst);
{
ops.push_back(&_first);
rates.push_back(_rate);
}
virtual string className() const { return "eoPropCombinedMonOp"; }
virtual void add(eoMonOp<EOT> & _op, const double _rate, bool _verbose=false)
{
ops.push_back(&_op);
rates.push_back(_rate);
// compute the relative rates in percent - to warn the user!
if (_verbose)
printOn(cout);
}
virtual void add(eoGenericMonOp<EOT> & _op, const double _rate, bool _verbose=false)
{
eoGeneric2TrueMonOp<EOT> *trueOp = new eoGeneric2TrueMonOp<EOT>(_op);
ops.push_back(trueOp);
{
ops.push_back(&_op);
rates.push_back(_rate);
// compute the relative rates in percent - to warn the user!
if (_verbose)
@ -110,10 +88,10 @@ public:
_os << ops[i]->className() << " with rate " << 100*rates[i]/total << " %\n";
}
virtual void operator()(EOT & _indi)
virtual bool operator()(EOT & _indi)
{
unsigned what = rng.roulette_wheel(rates); // choose one op
(*ops[what])(_indi); // apply it
return (*ops[what])(_indi); // apply it
}
protected:
std::vector<eoMonOp<EOT>*> ops;
@ -124,7 +102,7 @@ std::vector<double> rates;
//// combined BinOp
//////////////////////////////////////////////////////
/** COmbined Binary genetic operator:
/** COmbined Binary genetic operator:
* operator() has two operands, only the first one can be modified
*/
template <class EOT>
@ -133,16 +111,16 @@ class eoPropCombinedBinOp: public eoBinOp<EOT>
public:
/// Ctor
eoPropCombinedBinOp(eoBinOp<EOT> & _first, const double _rate)
{
ops.push_back(&_first);
{
ops.push_back(&_first);
rates.push_back(_rate);
}
virtual string className() const { return "eoPropCombinedBinOp"; }
virtual void add(eoBinOp<EOT> & _op, const double _rate, bool _verbose=false)
{
ops.push_back(&_op);
{
ops.push_back(&_op);
rates.push_back(_rate);
// compute the relative rates in percent - to warn the user!
if (_verbose)
@ -160,7 +138,7 @@ virtual void add(eoBinOp<EOT> & _op, const double _rate, bool _verbose=false)
virtual void operator()(EOT & _indi1, const EOT & _indi2)
{
unsigned what = rng.roulette_wheel(rates); // choose one op index
(*ops[what])(_indi1, _indi2); // apply it
return (*ops[what])(_indi1, _indi2); // apply it
}
private:
std::vector<eoBinOp<EOT>*> ops;
@ -172,13 +150,13 @@ std::vector<double> rates;
//// combined QuadOp
//////////////////////////////////////////////////////
/** Quad genetic operator: subclasses eoOp, and defines basically the
/** Quad genetic operator: subclasses eoOp, and defines basically the
operator() with two operands, both can be modified.
*/
/** Combined quad genetic operator:
/** Combined quad genetic operator:
* operator() has two operands, both can be modified
* generic operators are now allowed: there are imbedded into
* generic operators are now allowed: there are imbedded into
* the corresponding "true" operator
*/
template <class EOT>
@ -187,17 +165,8 @@ class eoPropCombinedQuadOp: public eoQuadOp<EOT>
public:
/// Ctor from a true operator
eoPropCombinedQuadOp(eoQuadOp<EOT> & _first, const double _rate)
{
ops.push_back(&_first);
rates.push_back(_rate);
}
/// Ctor from a generic operator
eoPropCombinedQuadOp(eoGenericQuadOp<EOT> & _first, const double _rate)
{
eoGeneric2TrueQuadOp<EOT> *trueFirst =
new eoGeneric2TrueQuadOp<EOT>(_first);
ops.push_back(trueFirst);
{
ops.push_back(&_first);
rates.push_back(_rate);
}
@ -205,19 +174,8 @@ virtual string className() const { return "eoPropCombinedQuadOp"; }
// addition of a true operator
virtual void add(eoQuadOp<EOT> & _op, const double _rate, bool _verbose=false)
{
ops.push_back(&_op);
rates.push_back(_rate);
// compute the relative rates in percent - to warn the user!
if (_verbose)
printOn(cout);
}
// addition of a generic operator
virtual void add(eoGenericQuadOp<EOT> & _op, const double _rate, bool _verbose=false)
{
eoGeneric2TrueQuadOp<EOT> *trueOp = new eoGeneric2TrueQuadOp<EOT>(_op);
ops.push_back(trueOp);
{
ops.push_back(&_op);
rates.push_back(_rate);
// compute the relative rates in percent - to warn the user!
if (_verbose)
@ -236,10 +194,10 @@ virtual void add(eoGenericQuadOp<EOT> & _op, const double _rate, bool _verbose=f
_os << ops[i]->className() << " with rate " << 100*rates[i]/total << " %\n";
}
virtual void operator()(EOT & _indi1, EOT & _indi2)
virtual bool operator()(EOT & _indi1, EOT & _indi2)
{
unsigned what = rng.roulette_wheel(rates); // choose one op index
(*ops[what])(_indi1, _indi2); // apply it
return (*ops[what])(_indi1, _indi2); // apply it
}
private:
std::vector<eoQuadOp<EOT>*> ops;
@ -247,6 +205,6 @@ std::vector<double> rates;
};
// for General Ops, it's another story - see eoGOpSelector
#endif
// for General Ops, it's another story -
#endif

View file

@ -27,7 +27,7 @@
#ifndef _eoSGA_h
#define _eoSGA_h
#include <eoOp.h>
#include <eoInvalidateOps.h>
#include <eoContinue.h>
#include <eoPop.h>
#include <eoSelectOne.h>
@ -36,13 +36,13 @@
#include <eoAlgo.h>
#include <apply.h>
/** The Simple Genetic Algorithm, following Holland and Goldberg
* Needs a selector (class eoSelectOne) a crossover (eoQuad,
* i.e. a 2->2 operator) and a mutation with their respective rates,
* of course an evaluation function (eoEvalFunc) and a continuator
/** The Simple Genetic Algorithm, following Holland and Goldberg
* Needs a selector (class eoSelectOne) a crossover (eoQuad,
* i.e. a 2->2 operator) and a mutation with their respective rates,
* of course an evaluation function (eoEvalFunc) and a continuator
* (eoContinue) which gives the stopping criterion. Performs full
* generational replacement.
*/
*/
template <class EOT>
class eoSGA : public eoAlgo<EOT>
@ -57,8 +57,8 @@ public :
eoMonOp<EOT>& _mutate, float _mrate,
eoEvalFunc<EOT>& _eval,
eoContinue<EOT>& _cont)
: cont(_cont),
mutate(_mutate),
: cont(_cont),
mutate(_mutate),
mutationRate(_mrate),
cross(_cross),
crossoverRate(_crate),
@ -68,42 +68,44 @@ public :
void operator()(eoPop<EOT>& _pop)
{
eoPop<EOT> offspring;
do
{
select(_pop, offspring);
unsigned i;
for (i=0; i<_pop.size()/2; i++)
for (i=0; i<_pop.size()/2; i++)
{
if ( rng.flip(crossoverRate) )
if ( rng.flip(crossoverRate) )
{
// this crossover generates 2 offspring from two parents
cross(offspring[2*i], offspring[2*i+1]);
}
}
for (i=0; i < _pop.size(); i++)
for (i=0; i < _pop.size(); i++)
{
if (rng.flip(mutationRate) )
if (rng.flip(mutationRate) )
{
mutate(offspring[i]);
}
}
_pop.swap(offspring);
apply<EOT>(eval, _pop);
} while (cont(_pop));
}
private :
eoContinue<EOT>& cont;
eoMonOp<EOT>& mutate;
/// eoInvalidateMonOp invalidates the embedded operator
eoInvalidateMonOp<EOT> mutate;
float mutationRate;
eoQuadOp<EOT>& cross;
// eoInvalidateQuadOp invalidates the embedded operator
eoInvalidateQuadOp<EOT> cross;
float crossoverRate;
eoSelectPerc<EOT> select;
eoEvalFunc<EOT>& eval;

View file

@ -3,7 +3,7 @@
//-----------------------------------------------------------------------------
// eoSGA.h
// (c) Marc.Schoenauer 2000 - 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
@ -27,7 +27,7 @@
#ifndef _eoSGATransform_h
#define _eoSGATransform_h
#include <eoOp.h>
#include <eoInvalidateOps.h>
#include <eoPop.h>
///////////////////////////////////////////////////////////////////////////////
@ -148,16 +148,16 @@ template<class EOT> class eoDynSGATransform : public eoTransform<EOT>
};
// accessors - mainly for EASEA
double & PCrossHandle() { return crossoverProba;}
double & PMutHandle() { return mutationProba;}
double & PMutHandle() { return mutationProba;}
private:
// difference with eoSGATransform: the operator probabilities
// they can be passed by reference or by value.
// hence we need here to use a reference, and to eventually store a value
eoQuadOp<EOT>& cross;
eoInvalidateQuadOp<EOT> cross;
double crossoverProbaHolder; // the value, used only if ctor gets a value
double& crossoverProba; // the reference, to be used in operator()
eoMonOp<EOT>& mutate;
eoInvalidateMonOp<EOT> mutate;
double mutationProbaHolder; // the value, used only if ctor gets a value
double& mutationProba; // the reference, to be used in operator()
};

View file

@ -29,13 +29,12 @@
#include <eoFunctor.h>
#include <eoVariableLength.h>
#include <eoGenericBinOp.h>
#include <eoGenericQuadOp.h>
#include <eoOp.h>
/**
Base classes for generic crossovers on variable length chromosomes.
Base classes for generic crossovers on variable length chromosomes.
Basically, they exchange genes - we need some matching information to apply
Basically, they exchange genes - we need some matching information to apply
atom crossover
*/
@ -79,17 +78,17 @@ private:
*/
template <class EOT>
class eoVlAtomExchangeQuadOp : public eoGenericQuadOp<EOT>
class eoVlAtomExchangeQuadOp : public eoQuadOp<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):
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
@ -116,8 +115,8 @@ public :
i1++;
}
index++;
} while ( ( (i1<Min) || (i2<Min) ||
(i1>Max) || (i2>Max) )
} while ( ( (i1<Min) || (i2<Min) ||
(i1>Max) || (i2>Max) )
&& (index<10000) );
if (index >= 10000)
{
@ -157,21 +156,21 @@ private:
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!!!
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>
class eoVlUniformQuadOp : public eoQuadOp<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) :
eoVlUniformQuadOp(unsigned _Min, unsigned _Max, double _rate=0.5) :
Min(_Min), Max(_Max), rate(_rate) {}
bool operator()(EOT & _eo1, EOT & _eo2)
{
unsigned i;
@ -194,7 +193,7 @@ public :
tmp2.push_back(_eo2[i]);
}
index++;
} while ( ( (tmp1.size()<Min) || (tmp2.size()<Min) ||
} while ( ( (tmp1.size()<Min) || (tmp2.size()<Min) ||
(tmp1.size()>Max) || (tmp2.size()>Max) )
&& (index<10000) );
if (index >= 10000)
@ -218,21 +217,21 @@ private:
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!!!
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>
class eoVlUniformBinOp : public eoBinOp<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) :
eoVlUniformBinOp(unsigned _Min, unsigned _Max, double _rate=0.5) :
Min(_Min), Max(_Max), rate(_rate) {}
bool operator()(EOT & _eo1, const EOT & _eo2)
{
unsigned i;
@ -248,7 +247,7 @@ public :
tmpIsTwo = false;
}
else
tmpIsOne=false;
tmpIsOne=false;
// we should look for _eo1[i] inside _eo2 and erase it there if found!
}
for (i=0; i<_eo2.size(); i++)

View file

@ -3,7 +3,7 @@
//-----------------------------------------------------------------------------
// 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
@ -29,10 +29,10 @@
#include <eoFunctor.h>
#include <eoVariableLength.h>
#include <eoGenericMonOp.h>
#include <eoOp.h>
/**
Base classes for generic mutations on variable length chromosomes.
Base classes for generic mutations on variable length chromosomes.
THey all require a generic mutation for their simple genes
*/
@ -40,16 +40,16 @@ 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>
class eoVlAllMutation : public eoMonOp<EOT>
{
public :
typedef typename EOT::AtomType AtomType;
// default ctor: requires an Atom mutation
eoVlAllMutation(eoGenericMonOp<AtomType> & _atomMutation) :
eoVlAllMutation(eoMonOp<AtomType> & _atomMutation) :
atomMutation(_atomMutation) {}
bool operator()(EOT & _eo)
{
bool modified=false;
@ -61,23 +61,23 @@ public :
return modified;
}
private:
eoGenericMonOp<AtomType> & atomMutation;
eoMonOp<AtomType> & atomMutation;
};
/** This ones applies its atomic mutation to a fixed
/** This ones applies its atomic mutation to a fixed
number of genes (1 by default)
*/
template <class EOT>
class eoVlKMutation : public eoGenericMonOp<EOT>
class eoVlKMutation : public eoMonOp<EOT>
{
public :
typedef typename EOT::AtomType AtomType;
// default ctor: requires an Atom mutation
eoVlKMutation(eoGenericMonOp<AtomType> & _atomMutation, unsigned _nb=1) :
eoVlKMutation(eoMonOp<AtomType> & _atomMutation, unsigned _nb=1) :
nb(_nb), atomMutation(_atomMutation) {}
bool operator()(EOT & _eo)
{
bool modified=false;
@ -91,7 +91,7 @@ public :
}
private:
unsigned nb;
eoGenericMonOp<AtomType> & atomMutation;
eoMonOp<AtomType> & atomMutation;
};
/** Addition of a gene
@ -99,20 +99,20 @@ private:
order-dependent and order-independent
*/
template <class EOT>
class eoVlAddMutation : public eoGenericMonOp<EOT>
class eoVlAddMutation : public eoMonOp<EOT>
{
public :
typedef typename EOT::AtomType AtomType;
/** default ctor
/** default ctor
* @param nMax max number of atoms
* @param _atomInit an Atom initializer
*/
eoVlAddMutation(unsigned _nMax, eoInit<AtomType> & _atomInit) :
eoVlAddMutation(unsigned _nMax, eoInit<AtomType> & _atomInit) :
nMax(_nMax), atomInit(_atomInit) {}
bool operator()(EOT & _eo)
{
if (_eo.size() >= nMax)
@ -150,27 +150,27 @@ public:
can of course be applied to both order-dependent and order-independent
*/
template <class EOT>
class eoVlDelMutation : public eoGenericMonOp<EOT>
class eoVlDelMutation : public eoMonOp<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) :
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) :
eoVlDelMutation(unsigned _nMin) :
nMin(_nMin), uChooser(), chooser(uChooser) {}
bool operator()(EOT & _eo)
{
if (_eo.size() <= nMin)

View file

@ -80,22 +80,22 @@ public:
/// needed virtual dtor
virtual ~eoEsMutate() {};
/** Inherited from eoObject
/** Inherited from eoObject
@see eoObject
*/
virtual string className() const {return "eoESMutate";};
/**
Mutate eoEsSimple
*/
virtual void operator()( eoEsSimple<FitT>& _eo)
virtual bool operator()( eoEsSimple<FitT>& _eo)
{
_eo.stdev *= exp(TauLcl * rng.normal());
_eo.stdev *= exp(TauLcl * rng.normal());
if (_eo.stdev < stdev_eps)
_eo.stdev = stdev_eps;
// now apply to all
for (unsigned i = 0; i < _eo.size(); ++i)
@ -104,40 +104,40 @@ public:
}
bounds.foldsInBounds(_eo);
_eo.invalidate();
return true;
}
/// mutations - standard and correlated
// =========
// =========
/*
* Standard mutation of object variables and standard
* deviations in ESs.
* If there are fewer different standard deviations available
* than the dimension of the objective function requires, the
* Standard mutation of object variables and standard
* deviations in ESs.
* If there are fewer different standard deviations available
* than the dimension of the objective function requires, the
* last standard deviation is responsible for ALL remaining
* object variables.
* Schwefel 1977: Numerische Optimierung von Computer-Modellen
* mittels der Evolutionsstrategie, pp. 165 ff.
*/
virtual void operator()( eoEsStdev<FitT>& _eo )
virtual bool operator()( eoEsStdev<FitT>& _eo )
{
double global = exp(TauGlb * rng.normal());
for (unsigned i = 0; i < _eo.size(); i++)
for (unsigned i = 0; i < _eo.size(); i++)
{
double stdev = _eo.stdevs[i];
stdev *= global * exp(TauLcl * rng.normal());
stdev *= global * exp(TauLcl * rng.normal());
if (stdev < stdev_eps)
stdev = stdev_eps;
_eo.stdevs[i] = stdev;
_eo.stdevs[i] = stdev;
_eo[i] += stdev * rng.normal();
}
bounds.foldsInBounds(_eo);
_eo.invalidate();
return true;
}
/*
@ -148,43 +148,43 @@ public:
* G. Rudolph: Globale Optimierung mit parallelen Evolutions-
* strategien, Diploma Thesis, University of Dortmund, 1990
*/
// Code from Thomas Baeck
virtual void operator()( eoEsFull<FitT> & _eo )
// Code from Thomas Baeck
virtual bool operator()( eoEsFull<FitT> & _eo )
{
/*
* First: mutate standard deviations (as above).
*/
double global = exp(TauGlb * rng.normal());
unsigned i;
for (i = 0; i < _eo.size(); i++)
for (i = 0; i < _eo.size(); i++)
{
double stdev = _eo.stdevs[i];
stdev *= global * exp(TauLcl * rng.normal());
stdev *= global * exp(TauLcl * rng.normal());
if (stdev < stdev_eps)
stdev = stdev_eps;
_eo.stdevs[i] = stdev;
_eo.stdevs[i] = stdev;
}
/*
* Mutate rotation angles.
*/
for (i = 0; i < _eo.correlations.size(); i++)
for (i = 0; i < _eo.correlations.size(); i++)
{
_eo.correlations[i] += TauBeta * rng.normal();
if ( fabs(_eo.correlations[i]) > M_PI )
_eo.correlations[i] += TauBeta * rng.normal();
if ( fabs(_eo.correlations[i]) > M_PI )
{
_eo.correlations[i] -= M_PI * (int) (_eo.correlations[i]/M_PI) ;
}
}
/*
* Perform correlated mutations.
*/
@ -192,17 +192,17 @@ public:
double d1,d2, S, C;
vector<double> VarStp(_eo.size());
for (i = 0; i < _eo.size(); i++)
for (i = 0; i < _eo.size(); i++)
VarStp[i] = _eo.stdevs[i] * rng.normal();
unsigned nq = _eo.correlations.size() - 1;
for (k = 0; k < _eo.size()-1; k++)
for (k = 0; k < _eo.size()-1; k++)
{
n1 = _eo.size() - k - 1;
n2 = _eo.size() - 1;
for (i = 0; i < k; i++)
for (i = 0; i < k; i++)
{
d1 = VarStp[n1];
d2 = VarStp[n2];
@ -214,13 +214,13 @@ public:
nq--;
}
}
for (i = 0; i < _eo.size(); i++)
for (i = 0; i < _eo.size(); i++)
_eo[i] += VarStp[i];
bounds.foldsInBounds(_eo);
_eo.invalidate();
return true;
}
private :
@ -243,14 +243,14 @@ public:
TauLcl /= sqrt( 2.0 * sqrt( (double)size ) );
TauGlb /= sqrt( 2.0 * ( (double) size ) );
}
void init(eoEsFull<FitT>, eoEsMutationInit& _init)
{
init(eoEsStdev<FitT>(), _init);
TauBeta = _init.TauBeta();
}
// the data
// the data
//=========
double TauLcl; /* Local factor for mutation of std deviations */
double TauGlb; /* Global factor for mutation of std deviations */

View file

@ -33,10 +33,10 @@
/**
\ingroup EvolutionStrategies
Crossover for Evolutionary strategie style representation,
supporting co-evolving standard deviations.
Crossover for Evolutionary strategie style representation,
supporting co-evolving standard deviations.
Simply calls a crossover for the object variables,
Simply calls a crossover for the object variables,
and a crossover for teh StdDev
*/
@ -44,26 +44,30 @@ template <class EOT>
class eoEsStdevXOver : public eoQuadOp<EOT>
{
public :
eoEsStdevXOver(eoGenericQuadOp<vector<double> > & _objectXOver,
eoGenericQuadOp<vector<double> > & _stdDevXOver) :
eoEsStdevXOver(eoQuadOp<vector<double> > & _objectXOver,
eoQuadOp<vector<double> > & _stdDevXOver) :
objectXOver(_objectXOver), stdDevXOver(_stdDevXOver) {}
std::string className(void) const { return "eoEsStdevXOver"; }
void operator()(EOT & _eo1, EOT & _eo2)
bool operator()(EOT & _eo1, EOT & _eo2)
{
bool objectChanged = objectXOver(_eo1, _eo2); // as vector<double>
bool stdDevChanged = stdDevXOver(_eo1.stdevs, _eo2.stdevs);
/// Marc, I didn't change it, but if only the stdev has changed,
/// doesn't that mean that the fitness is stil valid. Maarten
if ( objectChanged || stdDevChanged )
{
_eo1.invalidate();
_eo2.invalidate();
return true;
}
return false;
}
private:
eoGenericQuadOp<vector<double> > & objectXOver;
eoGenericQuadOp<vector<double> > & stdDevXOver;
eoQuadOp<vector<double> > & objectXOver;
eoQuadOp<vector<double> > & stdDevXOver;
};
/* A question: it seems it really makes no difference to have

View file

@ -31,27 +31,26 @@
in eoRealOp.h.
So they can be used when part of the genotype is a vector<double> ...
In the long run, they should replace completely the operators from eoRealOp
when all constructs using eoOp will be able to use the corresponding
when all constructs using eoOp will be able to use the corresponding
eoGenericOp - as it is already done in eoProportinoalCombinedOp
MS January 25. 2001
*/
#include <algorithm> // swap_ranges
#include <utils/eoRNG.h>
#include <eoGenericMonOp.h>
#include <eoGenericQuadOp.h>
#include <eoOp.h>
#include <es/eoRealBounds.h>
//-----------------------------------------------------------------------------
/** eoUniformMutation --> changes all values of the vector
by uniform choice with range epsilon
/** eoUniformMutation --> changes all values of the vector
by uniform choice with range epsilon
with probability p_change per variable
\class eoUniformMutation eoRealOp.h Tutorial/eoRealOp.h
\ingroup parameteric
*/
template<class EOT> class eoGenericUniformMutation: public eoGenericMonOp<EOT>
template<class EOT> class eoGenericUniformMutation: public eoMonOp<EOT>
{
public:
/**
@ -61,8 +60,8 @@ template<class EOT> class eoGenericUniformMutation: public eoGenericMonOp<EOT>
* @param _epsilon the range for uniform nutation
* @param _p_change the probability to change a given coordinate
*/
eoGenericUniformMutation(const double& _epsilon,
const double& _p_change = 1.0):
eoGenericUniformMutation(const double& _epsilon,
const double& _p_change = 1.0):
bounds(eoDummyVectorNoBounds), epsilon(_epsilon), p_change(_p_change) {}
/**
@ -71,23 +70,23 @@ template<class EOT> class eoGenericUniformMutation: public eoGenericMonOp<EOT>
* @param _epsilon the range for uniform nutation
* @param _p_change the probability to change a given coordinate
*/
eoGenericUniformMutation(eoRealVectorBounds & _bounds,
const double& _epsilon, const double& _p_change = 1.0):
eoGenericUniformMutation(eoRealVectorBounds & _bounds,
const double& _epsilon, const double& _p_change = 1.0):
bounds(_bounds), epsilon(_epsilon), p_change(_p_change) {}
/// The class name.
string className() const { return "eoGenericUniformMutation"; }
/**
* Do it!
* @param _eo The cromosome undergoing the mutation
*/
bool operator()(EOT& _eo)
bool operator()(EOT& _eo)
{
bool hasChanged=false;
for (unsigned lieu=0; lieu<_eo.size(); lieu++)
for (unsigned lieu=0; lieu<_eo.size(); lieu++)
{
if (rng.flip(p_change))
if (rng.flip(p_change))
{
// check the bounds
double emin = _eo[lieu]-epsilon;
@ -104,21 +103,21 @@ template<class EOT> class eoGenericUniformMutation: public eoGenericMonOp<EOT>
return true;
return false;
}
private:
eoRealVectorBounds & bounds;
double epsilon;
double p_change;
};
/** eoDetUniformMutation --> changes exactly k values of the vector
by uniform choice with range epsilon
/** eoDetUniformMutation --> changes exactly k values of the vector
by uniform choice with range epsilon
\class eoDetUniformMutation eoRealOp.h Tutorial/eoRealOp.h
\ingroup parameteric
*/
template<class EOT> class eoGenericDetUniformMutation:
public eoGenericMonOp<EOT>
template<class EOT> class eoGenericDetUniformMutation:
public eoMonOp<EOT>
{
public:
/**
@ -126,8 +125,8 @@ template<class EOT> class eoGenericDetUniformMutation:
* @param _epsilon the range for uniform nutation
* @param number of coordinate to modify
*/
eoGenericDetUniformMutation(const double& _epsilon,
const unsigned& _no = 1):
eoGenericDetUniformMutation(const double& _epsilon,
const unsigned& _no = 1):
bounds(eoDummyVectorNoBounds), epsilon(_epsilon), no(_no) {}
/**
@ -136,18 +135,18 @@ template<class EOT> class eoGenericDetUniformMutation:
* @param _epsilon the range for uniform nutation
* @param number of coordinate to modify
*/
eoGenericDetUniformMutation(eoRealVectorBounds & _bounds,
const double& _epsilon, const unsigned& _no = 1):
eoGenericDetUniformMutation(eoRealVectorBounds & _bounds,
const double& _epsilon, const unsigned& _no = 1):
bounds(_bounds), epsilon(_epsilon), no(_no) {}
/// The class name.
string className() const { return "eoGenericDetUniformMutation"; }
/**
* Do it!
* @param _eo The cromosome undergoing the mutation
*/
bool operator()(EOT& _eo)
bool operator()(EOT& _eo)
{
for (unsigned i=0; i<no; i++)
{
@ -175,37 +174,37 @@ private:
// two arithmetical crossovers
/** eoSegmentCrossover --> uniform choice in segment
/** eoSegmentCrossover --> uniform choice in segment
== arithmetical with same value along all coordinates
\class eoSegmentCrossover eoRealOp.h Tutorial/eoRealOp.h
\ingroup parameteric
*/
template<class EOT> class eoGenericSegmentCrossover: public eoGenericQuadOp<EOT>
template<class EOT> class eoGenericSegmentCrossover: public eoQuadOp<EOT>
{
public:
/**
* (Default) Constructor.
* The bounds are initialized with the global object that says: no bounds.
*
* @param _alphaMin the amount of exploration OUTSIDE the parents
* @param _alphaMin the amount of exploration OUTSIDE the parents
* as in BLX-alpha notation (Eshelman and Schaffer)
* 0 == contractive application
* Must be positive
*/
eoGenericSegmentCrossover(const double& _alpha = 0.0) :
eoGenericSegmentCrossover(const double& _alpha = 0.0) :
bounds(eoDummyVectorNoBounds), alpha(_alpha), range(1+2*_alpha) {}
/**
* Constructor with bounds
* @param _bounds an eoRealVectorBounds that contains the bounds
* @param _alphaMin the amount of exploration OUTSIDE the parents
* @param _alphaMin the amount of exploration OUTSIDE the parents
* as in BLX-alpha notation (Eshelman and Schaffer)
* 0 == contractive application
* Must be positive
*/
eoGenericSegmentCrossover(eoRealVectorBounds & _bounds,
const double& _alpha = 0.0) :
eoGenericSegmentCrossover(eoRealVectorBounds & _bounds,
const double& _alpha = 0.0) :
bounds(_bounds), alpha(_alpha), range(1+2*_alpha) {}
/// The class name.
@ -216,12 +215,12 @@ template<class EOT> class eoGenericSegmentCrossover: public eoGenericQuadOp<EOT>
* @param _eo1 The first parent
* @param _eo2 The first parent
*/
bool operator()(EOT& _eo1, EOT& _eo2)
bool operator()(EOT& _eo1, EOT& _eo2)
{
unsigned i;
double r1, r2, fact;
double alphaMin = -alpha;
double alphaMax = 1+alpha;
double alphaMax = 1+alpha;
if ( (alpha == 0.0) || bounds.hasNoBoundAtAll() ) // no check to perform
fact = -alpha + rng.uniform(range); // in [-alpha,1+alpha)
else // look for the bounds for fact
@ -238,7 +237,7 @@ template<class EOT> class eoGenericSegmentCrossover: public eoGenericQuadOp<EOT>
{
alphaMin = max(alphaMin, (bounds.minimum(i)-rmin)/length);
alphaMin = max(alphaMin, (rmax-bounds.maximum(i))/length);
}
}
if (bounds.isMaxBounded(i))
{
alphaMax = min(alphaMax, (bounds.maximum(i)-rmin)/length);
@ -264,28 +263,28 @@ protected:
double alpha;
double range; // == 1+2*alpha
};
/** eoArithmeticCrossover --> uniform choice in hypercube
/** eoArithmeticCrossover --> uniform choice in hypercube
== arithmetical with different values for each coordinate
\class eoArithmeticCrossover eoRealOp.h Tutorial/eoRealOp.h
\ingroup parameteric
*/
template<class EOT> class eoGenericArithmeticCrossover:
public eoGenericQuadOp<EOT>
template<class EOT> class eoGenericArithmeticCrossover:
public eoQuadOp<EOT>
{
public:
/**
* (Default) Constructor.
* The bounds are initialized with the global object that says: no bounds.
*
* @param _alphaMin the amount of exploration OUTSIDE the parents
* @param _alphaMin the amount of exploration OUTSIDE the parents
* as in BLX-alpha notation (Eshelman and Schaffer)
* 0 == contractive application
* Must be positive
*/
eoGenericArithmeticCrossover(const double& _alpha = 0.0):
bounds(eoDummyVectorNoBounds), alpha(_alpha), range(1+2*_alpha)
eoGenericArithmeticCrossover(const double& _alpha = 0.0):
bounds(eoDummyVectorNoBounds), alpha(_alpha), range(1+2*_alpha)
{
if (_alpha < 0)
throw runtime_error("BLX coefficient should be positive");
@ -294,14 +293,14 @@ template<class EOT> class eoGenericArithmeticCrossover:
/**
* Constructor with bounds
* @param _bounds an eoRealVectorBounds that contains the bounds
* @param _alphaMin the amount of exploration OUTSIDE the parents
* @param _alphaMin the amount of exploration OUTSIDE the parents
* as in BLX-alpha notation (Eshelman and Schaffer)
* 0 == contractive application
* Must be positive
*/
eoGenericArithmeticCrossover(eoRealVectorBounds & _bounds,
const double& _alpha = 0.0):
bounds(_bounds), alpha(_alpha), range(1+2*_alpha)
eoGenericArithmeticCrossover(eoRealVectorBounds & _bounds,
const double& _alpha = 0.0):
bounds(_bounds), alpha(_alpha), range(1+2*_alpha)
{
if (_alpha < 0)
throw runtime_error("BLX coefficient should be positive");
@ -315,7 +314,7 @@ template<class EOT> class eoGenericArithmeticCrossover:
* @param _eo1 The first parent
* @param _eo2 The first parent
*/
bool operator()(EOT& _eo1, EOT& _eo2)
bool operator()(EOT& _eo1, EOT& _eo2)
{
unsigned i;
double r1, r2, fact;
@ -344,7 +343,7 @@ template<class EOT> class eoGenericArithmeticCrossover:
{
alphaMin = max(alphaMin, (bounds.minimum(i)-rmin)/length);
alphaMin = max(alphaMin, (rmax-bounds.maximum(i))/length);
}
}
if (bounds.isMaxBounded(i))
{
alphaMax = min(alphaMax, (bounds.maximum(i)-rmin)/length);
@ -363,14 +362,14 @@ protected:
double alpha;
double range; // == 1+2*alphaMin
};
/** eoRealUxOver --> Uniform crossover, also termed intermediate crossover
\class eoRealUxOver eoRealOp.h Tutorial/eoRealOp.h
\ingroup parameteric
*/
template<class EOT> class eoGenericRealUxOver: public eoGenericQuadOp<EOT>
template<class EOT> class eoGenericRealUxOver: public eoQuadOp<EOT>
{
public:
/**
@ -378,7 +377,7 @@ template<class EOT> class eoGenericRealUxOver: public eoGenericQuadOp<EOT>
* @param _preference bias in the choice (usually, no bias == 0.5)
*/
eoGenericRealUxOver(double _preference = 0.5): preference(_preference)
{
{
if ( (_preference <= 0.0) || (_preference >= 1.0) )
runtime_error("UxOver --> invalid preference");
}
@ -392,10 +391,10 @@ template<class EOT> class eoGenericRealUxOver: public eoGenericQuadOp<EOT>
* @param _eo2 The second parent
* @runtime_error if sizes don't match
*/
bool operator()(EOT& _eo1, EOT& _eo2)
bool operator()(EOT& _eo1, EOT& _eo2)
{
if ( _eo1.size() != _eo2.size())
runtime_error("eoRealUxOver --> chromosomes sizes don't match" );
if ( _eo1.size() != _eo2.size())
runtime_error("eoRealUxOver --> chromosomes sizes don't match" );
bool changed = false;
for (unsigned int i=0; i<_eo1.size(); i++)
{
@ -415,7 +414,7 @@ template<class EOT> class eoGenericRealUxOver: public eoGenericQuadOp<EOT>
private:
double preference;
};
//-----------------------------------------------------------------------------
//@}

View file

@ -41,7 +41,7 @@
* to enable dynamic mutations (see eoOenFithMutation below).
*
* As for the bounds, the values are here folded back into the bounds.
* The other possiblity would be to iterate until we fall inside the bounds -
* The other possiblity would be to iterate until we fall inside the bounds -
* but this sometimes takes a long time!!!
*/
@ -55,7 +55,7 @@ template<class EOT> class eoNormalMutation: public eoMonOp<EOT>
* @param _sigma the range for uniform nutation
* @param _p_change the probability to change a given coordinate
*/
eoNormalMutation(double & _sigma, const double& _p_change = 1.0):
eoNormalMutation(double & _sigma, const double& _p_change = 1.0):
sigma(_sigma), bounds(eoDummyVectorNoBounds), p_change(_p_change) {}
/**
@ -64,33 +64,32 @@ template<class EOT> class eoNormalMutation: public eoMonOp<EOT>
* @param _sigma the range for uniform nutation
* @param _p_change the probability to change a given coordinate
*/
eoNormalMutation(eoRealVectorBounds & _bounds,
double & _sigma, const double& _p_change = 1.0):
eoNormalMutation(eoRealVectorBounds & _bounds,
double & _sigma, const double& _p_change = 1.0):
sigma(_sigma), bounds(_bounds), p_change(_p_change) {}
/// The class name.
string className() const { return "eoNormalMutation"; }
/**
* Do it!
* @param _eo The cromosome undergoing the mutation
*/
void operator()(EOT& _eo)
bool operator()(EOT& _eo)
{
bool hasChanged=false;
for (unsigned lieu=0; lieu<_eo.size(); lieu++)
for (unsigned lieu=0; lieu<_eo.size(); lieu++)
{
if (rng.flip(p_change))
if (rng.flip(p_change))
{
_eo[lieu] += sigma*rng.normal();
bounds.foldsInBounds(lieu, _eo[lieu]);
hasChanged = true;
}
}
if (hasChanged)
_eo.invalidate();
return hasChanged;
}
protected:
double & sigma;
private:
@ -98,9 +97,9 @@ private:
double p_change;
};
/** the dynamic version: just say it is updatable -
/** the dynamic version: just say it is updatable -
* and write the update() method!
* here the 1 fifth rule: count the proportion of successful mutations, and
* here the 1 fifth rule: count the proportion of successful mutations, and
* increase sigma if more than threshold (1/5 !)
*/

View file

@ -35,8 +35,8 @@
//-----------------------------------------------------------------------------
/** eoUniformMutation --> changes all values of the vector
by uniform choice with range epsilon
/** eoUniformMutation --> changes all values of the vector
by uniform choice with range epsilon
with probability p_change per variable
\class eoUniformMutation eoRealOp.h Tutorial/eoRealOp.h
\ingroup parameteric
@ -52,7 +52,7 @@ template<class EOT> class eoUniformMutation: public eoMonOp<EOT>
* @param _epsilon the range for uniform nutation
* @param _p_change the probability to change a given coordinate
*/
eoUniformMutation(const double& _epsilon, const double& _p_change = 1.0):
eoUniformMutation(const double& _epsilon, const double& _p_change = 1.0):
bounds(eoDummyVectorNoBounds), epsilon(_epsilon), p_change(_p_change) {}
/**
@ -61,23 +61,23 @@ template<class EOT> class eoUniformMutation: public eoMonOp<EOT>
* @param _epsilon the range for uniform nutation
* @param _p_change the probability to change a given coordinate
*/
eoUniformMutation(eoRealVectorBounds & _bounds,
const double& _epsilon, const double& _p_change = 1.0):
eoUniformMutation(eoRealVectorBounds & _bounds,
const double& _epsilon, const double& _p_change = 1.0):
bounds(_bounds), epsilon(_epsilon), p_change(_p_change) {}
/// The class name.
string className() const { return "eoUniformMutation"; }
/**
* Do it!
* @param _eo The cromosome undergoing the mutation
*/
void operator()(EOT& _eo)
bool operator()(EOT& _eo)
{
bool hasChanged=false;
for (unsigned lieu=0; lieu<_eo.size(); lieu++)
for (unsigned lieu=0; lieu<_eo.size(); lieu++)
{
if (rng.flip(p_change))
if (rng.flip(p_change))
{
// check the bounds
double emin = _eo[lieu]-epsilon;
@ -90,18 +90,17 @@ template<class EOT> class eoUniformMutation: public eoMonOp<EOT>
hasChanged = true;
}
}
if (hasChanged)
_eo.invalidate();
return hasChanged;
}
private:
eoRealVectorBounds & bounds;
double epsilon;
double p_change;
};
/** eoDetUniformMutation --> changes exactly k values of the vector
by uniform choice with range epsilon
/** eoDetUniformMutation --> changes exactly k values of the vector
by uniform choice with range epsilon
\class eoDetUniformMutation eoRealOp.h Tutorial/eoRealOp.h
\ingroup parameteric
*/
@ -114,7 +113,7 @@ template<class EOT> class eoDetUniformMutation: public eoMonOp<EOT>
* @param _epsilon the range for uniform nutation
* @param number of coordinate to modify
*/
eoDetUniformMutation(const double& _epsilon, const unsigned& _no = 1):
eoDetUniformMutation(const double& _epsilon, const unsigned& _no = 1):
bounds(eoDummyVectorNoBounds), epsilon(_epsilon), no(_no) {}
/**
@ -134,12 +133,11 @@ template<class EOT> class eoDetUniformMutation: public eoMonOp<EOT>
* Do it!
* @param _eo The cromosome undergoing the mutation
*/
void operator()(EOT& _eo)
bool operator()(EOT& _eo)
{
_eo.invalidate();
for (unsigned i=0; i<no; i++)
{
unsigned lieu = rng.random(_eo.size());
{
unsigned lieu = rng.random(_eo.size());
// actually, we should test that we don't re-modify same variable!
// check the bounds
@ -150,7 +148,9 @@ template<class EOT> class eoDetUniformMutation: public eoMonOp<EOT>
if (bounds.isMaxBounded(lieu))
emax = min(bounds.maximum(lieu), emax);
_eo[lieu] = emin + (emax-emin)*rng.uniform();
}
}
return true;
}
private:
@ -162,7 +162,7 @@ private:
// two arithmetical crossovers
/** eoSegmentCrossover --> uniform choice in segment
/** eoSegmentCrossover --> uniform choice in segment
== arithmetical with same value along all coordinates
\class eoSegmentCrossover eoRealOp.h Tutorial/eoRealOp.h
\ingroup parameteric
@ -175,12 +175,12 @@ template<class EOT> class eoSegmentCrossover: public eoQuadOp<EOT>
* (Default) Constructor.
* The bounds are initialized with the global object that says: no bounds.
*
* @param _alphaMin the amount of exploration OUTSIDE the parents
* @param _alphaMin the amount of exploration OUTSIDE the parents
* as in BLX-alpha notation (Eshelman and Schaffer)
* 0 == contractive application
* Must be positive
*/
eoSegmentCrossover(const double& _alpha = 0.0) :
eoSegmentCrossover(const double& _alpha = 0.0) :
bounds(eoDummyVectorNoBounds), alpha(_alpha), range(1+2*_alpha) {}
/**
@ -203,12 +203,12 @@ template<class EOT> class eoSegmentCrossover: public eoQuadOp<EOT>
* @param _eo1 The first parent
* @param _eo2 The first parent
*/
void operator()(EOT& _eo1, EOT& _eo2)
bool operator()(EOT& _eo1, EOT& _eo2)
{
unsigned i;
double r1, r2, fact;
double alphaMin = -alpha;
double alphaMax = 1+alpha;
double alphaMax = 1+alpha;
if (alpha == 0.0) // no check to perform
fact = -alpha + rng.uniform(range); // in [-alpha,1+alpha)
else // look for the bounds for fact
@ -225,7 +225,7 @@ template<class EOT> class eoSegmentCrossover: public eoQuadOp<EOT>
{
alphaMin = max(alphaMin, (bounds.minimum(i)-rmin)/length);
alphaMin = max(alphaMin, (rmax-bounds.maximum(i))/length);
}
}
if (bounds.isMaxBounded(i))
{
alphaMax = min(alphaMax, (bounds.maximum(i)-rmin)/length);
@ -243,8 +243,7 @@ template<class EOT> class eoSegmentCrossover: public eoQuadOp<EOT>
_eo1[i] = fact * r1 + (1-fact) * r2;
_eo2[i] = (1-fact) * r1 + fact * r2;
}
_eo1.invalidate(); // shoudl test if fact was 0 or 1 :-)))
_eo2.invalidate();
return true; // shoudl test if fact was 0 or 1 :-)))
}
protected:
@ -252,8 +251,8 @@ protected:
double alpha;
double range; // == 1+2*alpha
};
/** eoArithmeticCrossover --> uniform choice in hypercube
/** eoArithmeticCrossover --> uniform choice in hypercube
== arithmetical with different values for each coordinate
\class eoArithmeticCrossover eoRealOp.h Tutorial/eoRealOp.h
\ingroup parameteric
@ -266,13 +265,13 @@ template<class EOT> class eoArithmeticCrossover: public eoQuadOp<EOT>
* (Default) Constructor.
* The bounds are initialized with the global object that says: no bounds.
*
* @param _alphaMin the amount of exploration OUTSIDE the parents
* @param _alphaMin the amount of exploration OUTSIDE the parents
* as in BLX-alpha notation (Eshelman and Schaffer)
* 0 == contractive application
* Must be positive
*/
eoArithmeticCrossover(const double& _alpha = 0.0):
bounds(eoDummyVectorNoBounds), alpha(_alpha), range(1+2*_alpha)
eoArithmeticCrossover(const double& _alpha = 0.0):
bounds(eoDummyVectorNoBounds), alpha(_alpha), range(1+2*_alpha)
{
if (_alpha < 0)
throw runtime_error("BLX coefficient should be positive");
@ -302,7 +301,7 @@ template<class EOT> class eoArithmeticCrossover: public eoQuadOp<EOT>
* @param _eo1 The first parent
* @param _eo2 The first parent
*/
void operator()(EOT& _eo1, EOT& _eo2)
bool operator()(EOT& _eo1, EOT& _eo2)
{
unsigned i;
double r1, r2, fact;
@ -331,7 +330,7 @@ template<class EOT> class eoArithmeticCrossover: public eoQuadOp<EOT>
{
alphaMin = max(alphaMin, (bounds.minimum(i)-rmin)/length);
alphaMin = max(alphaMin, (rmax-bounds.maximum(i))/length);
}
}
if (bounds.isMaxBounded(i))
{
alphaMax = min(alphaMax, (bounds.maximum(i)-rmin)/length);
@ -342,16 +341,16 @@ template<class EOT> class eoArithmeticCrossover: public eoQuadOp<EOT>
_eo2[i] = (1-fact) * rmin + fact * rmax;
}
}
_eo1.invalidate();
_eo2.invalidate();
}
return true;
}
protected:
eoRealVectorBounds & bounds;
double alpha;
double range; // == 1+2*alphaMin
};
/** eoRealUxOver --> Uniform crossover, also termed intermediate crossover
\class eoRealUxOver eoRealOp.h Tutorial/eoRealOp.h
@ -380,10 +379,10 @@ template<class EOT> class eoRealUxOver: public eoQuadOp<EOT>
* @param _eo2 The second parent
* @runtime_error if sizes don't match
*/
void operator()(EOT& _eo1, EOT& _eo2)
bool operator()(EOT& _eo1, EOT& _eo2)
{
if ( _eo1.size() != _eo2.size())
runtime_error("UxOver --> chromosomes sizes don't match" );
if ( _eo1.size() != _eo2.size())
runtime_error("UxOver --> chromosomes sizes don't match" );
bool changed = false;
for (unsigned int i=0; i<_eo1.size(); i++)
{
@ -396,11 +395,7 @@ template<class EOT> class eoRealUxOver: public eoQuadOp<EOT>
changed = true;
}
}
if (changed)
{
_eo1.invalidate();
_eo2.invalidate();
}
return changed;
}
private:
float preference;

View file

@ -60,7 +60,7 @@
#include <ga/eoBit.h>
/** eoBitFlip --> changes 1 bit
/** eoBitFlip --> changes 1 bit
\class eoBitBitFlip eoBitOp.h ga/eoBitOp.h
\ingroup bitstring
*/
@ -70,20 +70,20 @@ template<class Chrom> class eoOneBitFlip: public eoMonOp<Chrom>
public:
/// The class name.
string className() const { return "eoOneBitFlip"; }
/**
* Change one bit.
* @param chrom The cromosome which one bit is going to be changed.
*/
void operator()(Chrom& chrom)
bool operator()(Chrom& chrom)
{
unsigned i = eo::rng.random(chrom.size());
chrom[i] = (chrom[i]) ? false : true;
chrom.invalidate();
return true;
}
};
/** eoDetBitFlip --> changes exactly k bits
/** eoDetBitFlip --> changes exactly k bits
\class eoDetBitFlip eoBitOp.h ga/eoBitOp.h
\ingroup bitstring
*/
@ -100,12 +100,12 @@ template<class Chrom> class eoDetBitFlip: public eoMonOp<Chrom>
/// The class name.
string className() const { return "eoDetBitFlip"; }
/**
* Change num_bit bits.
* @param chrom The cromosome which one bit is going to be changed.
*/
void operator()(Chrom& chrom)
bool operator()(Chrom& chrom)
{
// does not check for duplicate: if someone volunteers ....
for (unsigned k=0; k<num_bit; k++)
@ -113,14 +113,14 @@ template<class Chrom> class eoDetBitFlip: public eoMonOp<Chrom>
unsigned i = eo::rng.random(chrom.size());
chrom[i] = (chrom[i]) ? false : true;
}
chrom.invalidate();
return true;
}
private:
unsigned num_bit;
};
/** eoBitMutation --> classical mutation
/** eoBitMutation --> classical mutation
\class eoBitMutation eoBitOp.h ga/eoBitOp.h
\ingroup bitstring
*/
@ -141,7 +141,7 @@ template<class Chrom> class eoBitMutation: public eoMonOp<Chrom>
* Mutate a chromosome.
* @param chrom The chromosome to be mutated.
*/
void operator()(Chrom& chrom)
bool operator()(Chrom& chrom)
{
bool changed_something = false;
for (unsigned i = 0; i < chrom.size(); i++)
@ -151,16 +151,15 @@ template<class Chrom> class eoBitMutation: public eoMonOp<Chrom>
changed_something = true;
}
if (changed_something)
chrom.invalidate();
return changed_something;
}
private:
double rate;
};
/** eoBitInversion: inverts the bits of the chromosome between an interval
/** eoBitInversion: inverts the bits of the chromosome between an interval
\class eoBitInversion eoBitOp.h ga/eoBitOp.h
\ingroup bitstring
*/
@ -175,20 +174,20 @@ template<class Chrom> class eoBitInversion: public eoMonOp<Chrom>
* Inverts a range of bits in a binary chromosome.
* @param chrom The chromosome whos bits are going to be inverted (a range).
*/
void operator()(Chrom& chrom)
bool operator()(Chrom& chrom)
{
unsigned u1 = eo::rng.random(chrom.size() + 1) , u2;
do u2 = eo::rng.random(chrom.size() + 1); while (u1 == u2);
unsigned r1 = min(u1, u2), r2 = max(u1, u2);
reverse(chrom.begin() + r1, chrom.begin() + r2);
chrom.invalidate();
return true;
}
};
/** eoBitNext --> next value when bitstring considered as binary value
/** eoBitNext --> next value when bitstring considered as binary value
\class eoBitNext eoBitOp.h ga/eoBitOp.h
\ingroup bitstring
*/
@ -198,12 +197,12 @@ template<class Chrom> class eoBitNext: public eoMonOp<Chrom>
public:
/// The class name.
string className() const { return "eoBitNext"; }
/**
* Change the bit string x to be x+1.
* @param chrom The chromosome to be added one.
*/
void operator()(Chrom& chrom)
bool operator()(Chrom& chrom)
{
for (int i = chrom.size() - 1; i >= 0; i--)
if (chrom[i])
@ -217,12 +216,12 @@ template<class Chrom> class eoBitNext: public eoMonOp<Chrom>
break;
}
chrom.invalidate();
return true;
}
};
/** eoBitPrev --> previous value when bitstring treated as binary value
/** eoBitPrev --> previous value when bitstring treated as binary value
\class eoBitPrev eoBitOp.h ga/eoBitOp.h
\ingroup bitstring
*/
@ -232,12 +231,12 @@ template<class Chrom> class eoBitPrev: public eoMonOp<Chrom>
public:
/// The class name.
string className() const { return "eoBitPrev"; }
/**
* Change the bit string x to be x-1.
* @param chrom The chromosome to be substracted one.
*/
void operator()(Chrom& chrom)
bool operator()(Chrom& chrom)
{
for (int i = chrom.size() - 1; i >= 0; i--)
if (chrom[i])
@ -249,14 +248,14 @@ template<class Chrom> class eoBitPrev: public eoMonOp<Chrom>
{
chrom[i] = 1;
continue;
}
}
chrom.invalidate();
return true;
}
};
/** eo1PtBitXover --> classic 1-point crossover
/** eo1PtBitXover --> classic 1-point crossover
\class eo1PtBitCrossover eoBitOp.h ga/eoBitOp.h
\ingroup bitstring
*/
@ -272,7 +271,7 @@ template<class Chrom> class eo1PtBitXover: public eoQuadOp<Chrom>
* @param chrom1 The first chromosome.
* @param chrom2 The first chromosome.
*/
void operator()(Chrom& chrom1, Chrom& chrom2)
bool operator()(Chrom& chrom1, Chrom& chrom2)
{
unsigned site = eo::rng.random(min(chrom1.size(), chrom2.size()));
@ -280,15 +279,15 @@ template<class Chrom> class eo1PtBitXover: public eoQuadOp<Chrom>
{
swap_ranges(chrom1.begin(), chrom1.begin() + site, chrom2.begin());
chrom1.invalidate();
chrom2.invalidate();
return true;
}
return false;
}
};
/** eoUBitXover --> classic Uniform crossover
/** eoUBitXover --> classic Uniform crossover
\class eoUBitXover eoBitOp.h ga/eoBitOp.h
\ingroup bitstring
*/
@ -298,7 +297,7 @@ template<class Chrom> class eoUBitXover: public eoQuadOp<Chrom>
public:
/// (Default) Constructor.
eoUBitXover(const float& _preference = 0.5): preference(_preference)
{
{
if ( (_preference <= 0.0) || (_preference >= 1.0) )
runtime_error("UxOver --> invalid preference");
}
@ -311,10 +310,10 @@ template<class Chrom> class eoUBitXover: public eoQuadOp<Chrom>
* @param chrom2 The first chromosome.
* @runtime_error if sizes don't match
*/
void operator()(Chrom& chrom1, Chrom& chrom2)
bool operator()(Chrom& chrom1, Chrom& chrom2)
{
if ( chrom1.size() != chrom2.size())
runtime_error("UxOver --> chromosomes sizes don't match" );
if ( chrom1.size() != chrom2.size())
runtime_error("UxOver --> chromosomes sizes don't match" );
bool changed = false;
for (unsigned int i=0; i<chrom1.size(); i++)
{
@ -326,18 +325,14 @@ template<class Chrom> class eoUBitXover: public eoQuadOp<Chrom>
changed = true;
}
}
if (changed)
{
chrom1.invalidate();
chrom2.invalidate();
}
}
return changed;
}
private:
float preference;
};
/** eoNPtsBitXover --> n-point crossover
/** eoNPtsBitXover --> n-point crossover
\class eoNPtsBitXover eoBitOp.h ga/eoBitOp.h
\ingroup bitstring
*/
@ -347,29 +342,29 @@ template<class Chrom> class eoNPtsBitXover: public eoQuadOp<Chrom>
public:
/// (Default) Constructor.
eoNPtsBitXover(const unsigned& _num_points = 2): num_points(_num_points)
{
{
if (num_points < 1)
runtime_error("NxOver --> invalid number of points");
}
/// The class name.
string className() const { return "eoNPtsBitXover"; }
/**
* n-point crossover for binary chromosomes.
* @param chrom1 The first chromosome.
* @param chrom2 The first chromosome.
*/
void operator()(Chrom& chrom1, Chrom& chrom2)
bool operator()(Chrom& chrom1, Chrom& chrom2)
{
unsigned max_size = min(chrom1.size(), chrom2.size());
unsigned max_points = min(max_size - 1, num_points);
vector<bool> points(max_size, false);
// select ranges of bits to swap
do {
unsigned bit = eo::rng.random(max_size) + 1;
unsigned bit = eo::rng.random(max_size) + 1;
if (points[bit])
continue;
else
@ -378,30 +373,29 @@ template<class Chrom> class eoNPtsBitXover: public eoQuadOp<Chrom>
max_points--;
}
} while (max_points);
// swap bits between chromosomes
bool change = false;
for (unsigned bit = 1; bit < points.size(); bit++)
{
if (points[bit])
change = !change;
if (change)
swap(chrom1[bit], chrom2[bit]);
}
chrom1.invalidate();
chrom2.invalidate();
return true;
}
private:
unsigned num_points;
};
/** eoBitGxOver --> Npts crossover when bistring considered
/** eoBitGxOver --> Npts crossover when bistring considered
as a string of binary-encoded genes (exchanges genes)
Is anybody still using it apart from historians ??? :-)
\class eoBitGxOver eoBitOp.h ga/eoBitOp.h
@ -412,28 +406,28 @@ template<class Chrom> class eoBitGxOver: public eoQuadOp<Chrom>
{
public:
/// Constructor.
eoBitGxOver(const unsigned _gene_size, const unsigned _num_points = 2):
eoBitGxOver(const unsigned _gene_size, const unsigned _num_points = 2):
gene_size(_gene_size), num_points(_num_points)
{
{
if (gene_size < 1)
runtime_error("GxOver --> invalid gene size");
if (num_points < 1)
runtime_error("GxOver --> invalid number of points");
}
/// The class name
string className() const { return "eoBitGxOver"; }
/**
* Gene crossover for binary chromosomes.
* @param chrom1 The first chromosome.
* @param chrom2 The first chromosome.
*/
void operator()(Chrom& chrom1, Chrom& chrom2)
bool operator()(Chrom& chrom1, Chrom& chrom2)
{
unsigned max_genes = min(chrom1.size(), chrom2.size()) / gene_size;
unsigned cut_genes = min(max_genes, num_points);
vector<bool> points(max_genes, false);
// selects genes to swap
@ -454,11 +448,10 @@ template<class Chrom> class eoBitGxOver: public eoQuadOp<Chrom>
swap_ranges(chrom1.begin() + i * gene_size,
chrom1.begin() + i * gene_size + gene_size,
chrom2.begin() + i * gene_size);
chrom1.invalidate();
chrom2.invalidate();
return true;
}
private:
unsigned gene_size;
unsigned num_points;

View file

@ -148,7 +148,7 @@ private :
unsigned max_depth;
std::vector<Node> initializor;
bool grow;
bool grow;
};
template<class FType, class Node>
@ -165,7 +165,7 @@ public:
/// Dtor
virtual ~eoSubtreeXOver () {};
void operator()(EoType & _eo1, EoType & _eo2 )
bool operator()(EoType & _eo1, EoType & _eo2 )
{
int i = rng.random(_eo1.size());
int j = rng.random(_eo2.size());
@ -173,26 +173,25 @@ public:
parse_tree<Node>::subtree tmp = _eo2[j];
_eo1[i] = _eo2[j]; // insert subtree
_eo2[j]=tmp;
_eo1.pruneTree(max_length);
_eo2.pruneTree(max_length);
_eo1.invalidate();
_eo2.invalidate();
return true;
}
unsigned max_length;
};
template<class FType, class Node>
class eoBranchMutation: public eoMonOp< eoParseTree<FType, Node> >
class eoBranchMutation: public eoMonOp< eoParseTree<FType, Node> >
{
public:
typedef eoParseTree<FType, Node> EoType;
eoBranchMutation(eoInit<EoType>& _init, unsigned _max_length)
: eoMonOp<EoType>(), max_length(_max_length), initializer(_init)
: eoMonOp<EoType>(), max_length(_max_length), initializer(_init)
{};
virtual string className() const { return "eoBranchMutation"; };
@ -200,26 +199,26 @@ public:
/// Dtor
virtual ~eoBranchMutation() {};
void operator()(EoType& _eo1 )
bool operator()(EoType& _eo1 )
{
int i = rng.random(_eo1.size());
EoType eo2;
initializer(eo2);
int j = rng.random(eo2.size());
_eo1[i] = eo2[j]; // insert subtree
_eo1.pruneTree(max_length);
_eo1.invalidate();
return true;
}
private :
unsigned max_length;
eoInit<EoType>& initializer;
eoInit<EoType>& initializer;
};

View file

@ -46,13 +46,13 @@ class eoExternalInit : public eoInit<ExternalEO>
{
public :
eoExternalInit(External (*_init)(void)) : init(_init) {}
void operator()(ExternalEO& _eo)
{
_eo = (*init)();
void operator()(ExternalEO& _eo)
{
_eo = (*init)();
_eo.invalidate();
}
@ -76,7 +76,7 @@ class eoExternalEvalFunc : public eoEvalFunc<ExternalEO>
eoExternalEvalFunc(F (*_eval)(const External&)) : eval(_eval) {}
void operator()(ExternalEO& eo)
void operator()(ExternalEO& eo)
{
if (eo.invalid())
eo.fitness( (*eval)(eo) );
@ -93,8 +93,8 @@ class eoExternalEvalFunc : public eoEvalFunc<ExternalEO>
bool func(External&);
Where External is the user defined struct or class.
Where External is the user defined struct or class.
The function should return true when it changed something, false otherwise
*/
@ -105,10 +105,9 @@ class eoExternalMonOp : public eoMonOp<ExternalEO>
eoExternalMonOp(bool (*_mutate)(External&)) : mutate(_mutate) {}
void operator()(ExternalEO& eo)
bool operator()(ExternalEO& eo)
{
if ((*mutate)(eo))
eo.invalidate();
return (*mutate)(eo);
}
private :
@ -132,10 +131,9 @@ class eoExternalBinOp : public eoBinOp<ExternalEO>
eoExternalBinOp(bool (*_binop)(External&, const External&)) : binop(_binop) {}
void operator()(ExternalEO& eo1, const ExternalEO& eo2)
bool operator()(ExternalEO& eo1, const ExternalEO& eo2)
{
if ((*binop)(eo1, eo2))
eo1.invalidate();
return (*binop)(eo1, eo2);
}
private :
@ -159,13 +157,9 @@ class eoExternalQuadOp : public eoQuadOp<ExternalEO>
eoExternalQuadOp(bool (*_quadop)(External&, External&)) : quadop(_quadop) {}
void operator()(ExternalEO& eo1, ExternalEO& eo2)
bool operator()(ExternalEO& eo1, ExternalEO& eo2)
{
if ((*quadop)(eo1, eo2))
{
eo1.invalidate();
eo2.invalidate();
}
return (*quadop)(eo1, eo2);
}
private :

View file

@ -38,11 +38,20 @@ class eoObject;
class eoPersistent;
/**
* eoState can be used to register derivants of eoPersistent. It will
* then in turn implement the persistence framework through members load
* and save, that will call readFrom and printOn for the registrated objects.
eoState can be used to register derivants of eoPersistent. It will
then in turn implement the persistence framework through members load
and save, that will call readFrom and printOn for the registrated objects.
It is derived from eoFunctorStore, so that it also serves as a place where
all those nifty eo functors can be stored. This is useful in the case you
want to use one of the make_* functions. These functions generally take as their
last argument an eoFunctorStore (or a state) which is used to hold all dynamically
generated data. Note however, that unlike with eoPersistent derived classes, eoFunctorBase
derived classes are not saved or loaded. To govern the creation of functors,
command-line parameters (which can be stored) are needed.
*/
class eoState
class eoState : public eoFunctorStore
{
public :
@ -68,12 +77,6 @@ public :
return static_cast<T&>(*ownedObjects.back());
}
void storeFunctor(eoFunctorBase* _functor)
{
// add it to the functorStore, fo
functorStore.add(_functor);
}
/**
* Loading error thrown when nothing seems to work.
*/
@ -123,9 +126,6 @@ private :
std::vector<ObjectMap::iterator> creationOrder;
std::vector<eoPersistent*> ownedObjects;
// And a functor store to boot
eoFunctorStore functorStore;
// private copy and assignment as eoState is supposed to be unique
eoState(const eoState&);
eoState& operator=(const eoState&);

View file

@ -36,6 +36,9 @@ echo "Testing t-eofitness"
echo "Testing t-eoGA"
./t-eoGA > t-eoGA.log
echo "Testing t-eoGenOp"
./t-eoGenOp > t-eoGenOp.log
echo "Finished"
#TODO test if an error occured

View file

@ -23,7 +23,7 @@
*/
//-----------------------------------------------------------------------------
/** test program for the general operator - millenium version!
/** test program for the general operator - millenium version!
* uses dummy individuals
*/
#include <eo>
@ -53,10 +53,11 @@ class monop : public eoMonOp<EOT>
{
public :
monop(char * _sig){sig=_sig;}
void operator()(EOT& _eo)
bool operator()(EOT& _eo)
{
_eo.s = sig + "(" + _eo.s + ")";
_eo.fitness(_eo.fitness()+pSize);
return false;
}
string className() {return sig;}
private:
@ -66,11 +67,12 @@ class monop : public eoMonOp<EOT>
class binop: public eoBinOp<EOT>
{
public :
void operator()(EOT& _eo1, const EOT& _eo2)
bool operator()(EOT& _eo1, const EOT& _eo2)
{
_eo1.s = "bin(" + _eo1.s + "," + _eo2.s + ")";
double f= (_eo1.fitness()+_eo2.fitness()) * pSize;
_eo1.fitness(_eo1.fitness()+f);
return false;
}
string className() {return "binop";}
};
@ -79,7 +81,7 @@ class quadop: public eoQuadOp<EOT>
{
public :
string className() {return "quadop";}
void operator()(EOT& a, EOT& b)
bool operator()(EOT& a, EOT& b)
{
EOT oi = a;
EOT oj = b;
@ -89,6 +91,7 @@ class quadop: public eoQuadOp<EOT>
double f= (a.fitness()+b.fitness()+2*pSize) * pSize;
a.fitness(a.fitness()+f);
b.fitness(b.fitness()+f);
return false;
}
};
// an eoQuadOp that does nothing
@ -96,7 +99,7 @@ class quadClone: public eoQuadOp<EOT>
{
public :
string className() {return "quadclone";}
void operator()(EOT& , EOT& ) {}
bool operator()(EOT& , EOT& ) {return false;}
};
// User defined General Operator... adapted from Marc's example