diff --git a/eo/app/gprop/Makefile.am b/eo/app/gprop/Makefile.am index bc4a7b85..eb87ebb5 100644 --- a/eo/app/gprop/Makefile.am +++ b/eo/app/gprop/Makefile.am @@ -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 diff --git a/eo/app/gprop/gprop.h b/eo/app/gprop/gprop.h index 6f630207..a0c7c0ec 100644 --- a/eo/app/gprop/gprop.h +++ b/eo/app/gprop/gprop.h @@ -109,11 +109,11 @@ mlp::set trn_set, val_set, tst_set; class eoChromMutation: public eoMonOp { 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 { 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; } }; diff --git a/eo/app/mastermind/mastermind.h b/eo/app/mastermind/mastermind.h index c23d921d..44b64b85 100644 --- a/eo/app/mastermind/mastermind.h +++ b/eo/app/mastermind/mastermind.h @@ -116,7 +116,7 @@ void init_eoChromEvaluator(const unsigned& c, const unsigned& l, string s) uniform_generator color(0, num_colors); generate(solution.begin(), solution.end(), color); } - + solution.fitness(eoChromEvaluator(solution)); } @@ -143,14 +143,14 @@ public: class eoChromMutation: public eoMonOp { // many operators in one :( - void operator()(Chrom& chrom) + bool operator()(Chrom& chrom) { uniform_generator what(0, 2); uniform_generator position(0, chrom.size()); switch(what()) { - case 0: + case 0: { // mutation uniform_generator color(0, num_colors); @@ -171,7 +171,7 @@ class eoChromMutation: public eoMonOp } } - chrom.invalidate(); + return true; } }; @@ -182,12 +182,11 @@ class eoChromMutation: public eoMonOp class eoChromXover: public eoQuadOp { public: - void operator()(Chrom& chrom1, Chrom& chrom2) + bool operator()(Chrom& chrom1, Chrom& chrom2) { uniform_generator 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: diff --git a/eo/src/Makefile.am b/eo/src/Makefile.am index 051db2f9..3982f482 100644 --- a/eo/src/Makefile.am +++ b/eo/src/Makefile.am @@ -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 diff --git a/eo/src/eoCounter.h b/eo/src/eoCounter.h index af55f20f..05e08b21 100644 --- a/eo/src/eoCounter.h +++ b/eo/src/eoCounter.h @@ -196,7 +196,7 @@ template eoProcedureCounter& make_counter(eoFunctorBase::procedure_tag, Procedure& _proc, eoFunctorStore& store, std::string _name = "proc_counter") { eoProcedureCounter* result = new eoProcedureCounter(_proc, _name); - store.add(result); + store.storeFunctor(result); return *result; } @@ -204,7 +204,7 @@ template eoUnaryFunctorCounter& make_counter(eoFunctorBase::unary_function_tag, UnaryFunctor& _proc, eoFunctorStore& store, std::string _name = "uf_counter") { eoUnaryFunctorCounter* result = new eoUnaryFunctorCounter(_proc, _name); - store.add(result); + store.storeFunctor(result); return *result; } @@ -212,7 +212,7 @@ template eoBinaryFunctorCounter& make_counter(eoFunctorBase::binary_function_tag, BinaryFunctor& _proc, eoFunctorStore& store, std::string _name = "uf_counter") { eoBinaryFunctorCounter* result = new eoBinaryFunctorCounter(_proc, _name); - store.add(result); + store.storeFunctor(result); return *result; } diff --git a/eo/src/eoFunctorStore.h b/eo/src/eoFunctorStore.h index 21980906..1655fb00 100644 --- a/eo/src/eoFunctorStore.h +++ b/eo/src/eoFunctorStore.h @@ -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 + 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 vec; diff --git a/eo/src/eoGenOp.h b/eo/src/eoGenOp.h index badbde71..a8143a9e 100644 --- a/eo/src/eoGenOp.h +++ b/eo/src/eoGenOp.h @@ -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 #include - +#include /** @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 eoGenOp : public eoOp, public eoUF &, void> { public : /// Ctor that honors its superclass - eoGenOp(): eoOp( eoOp::general ) {} + eoGenOp(): eoOp( eoOp::general ) {} - virtual unsigned max_production(void) = 0; + virtual unsigned max_production(void) = 0; virtual string className() = 0; void operator()(eoPopulator& _pop) { @@ -57,6 +64,7 @@ class eoGenOp : public eoOp, public eoUF &, void> apply(_pop); } + protected : /** the function that will do the work */ @@ -75,7 +83,8 @@ class eoMonGenOp : public eoGenOp void apply(eoPopulator& _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& 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 eoSelBinGenOp : public eoGenOp { public: - eoSelBinGenOp(eoBinOp& _op, eoSelectOne& _sel) : + eoSelBinGenOp(eoBinOp& _op, eoSelectOne& _sel) : op(_op), sel(_sel) {} - + unsigned max_production(void) { return 1; } - + void apply(eoPopulator& _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& op; eoSelectOne& sel; @@ -147,7 +158,11 @@ class eoQuadGenOp : public eoGenOp 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 eoQuadOp& 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 called my_quad, and you want to feed it to an eoTransform + derived class that expects an eoGenOp. If you have an eoState lying around + (which is generally a good idea) you can say: + + eoDerivedTransform trans(eoGenOp::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 + eoGenOp& wrap_op(eoOp& _op, eoFunctorStore& _store) + { + switch(_op.getType()) + { + case eoOp::unary : return _store.storeFunctor(new eoMonGenOp(static_cast&>(_op))); + case eoOp::binary : return _store.storeFunctor(new eoBinGenOp(static_cast&>(_op))); + case eoOp::quadratic : return _store.storeFunctor(new eoQuadGenOp(static_cast&>(_op))); + case eoOp::general : return static_cast&>(_op); + } + } #endif diff --git a/eo/src/eoInit.h b/eo/src/eoInit.h index 4db408a3..6af2ff2d 100644 --- a/eo/src/eoInit.h +++ b/eo/src/eoInit.h @@ -104,10 +104,11 @@ class eoInitAdaptor : public eoMonOp { public : eoInitAdaptor(eoInit& _init) : init(_init) {} - - void operator()(EOT& _eot) + + bool operator()(EOT& _eot) { init(_eot); + return true; } private : diff --git a/eo/src/eoInvalidateOps.h b/eo/src/eoInvalidateOps.h new file mode 100644 index 00000000..711456e6 --- /dev/null +++ b/eo/src/eoInvalidateOps.h @@ -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 + +/** +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 eoInvalidateMonOp : public eoMonOp +{ + public: + eoInvalidateMonOp(eoMonOp& _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& 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 eoInvalidateBinOp : public eoBinOp +{ + public: + eoInvalidateBinOp(eoBinOp& _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& 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 eoInvalidateQuadOp : public eoQuadOp +{ + public: + eoInvalidateQuadOp(eoQuadOp& _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& op; +}; + +#endif diff --git a/eo/src/eoOp.h b/eo/src/eoOp.h index dfbaecab..607962f3 100644 --- a/eo/src/eoOp.h +++ b/eo/src/eoOp.h @@ -29,23 +29,23 @@ #include #include /** -\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, there are operators that work specifically + on vector, but you might also find that generic operators + working on vector are what you need. + +*/ template 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 eoMonOp: public eoOp, public eoUF +class eoMonOp: public eoOp, public eoUF { 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 eoBinOp: public eoOp, public eoBF +class eoBinOp: public eoOp, public eoBF { 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 eoQuadOp: public eoOp, public eoBF { +class eoQuadOp: public eoOp, public eoBF { 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: diff --git a/eo/src/eoOpContainer.h b/eo/src/eoOpContainer.h index fd64289b..15053485 100644 --- a/eo/src/eoOpContainer.h +++ b/eo/src/eoOpContainer.h @@ -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 /** 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 @@ -43,15 +43,11 @@ class eoOpContainer : public eoGenOp { 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 return max_to_produce; } - /** wraps then add a simple eoMonOp */ - void add(eoMonOp& _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& _op, double _rate) { - owned_genops.push_back(new eoMonGenOp(_op)); - ops.push_back(owned_genops.back()); + ops.push_back(&wrap_op(_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& _op, double _rate) - { - owned_genops.push_back(new eoBinGenOp(_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& _op, eoSelectOne & _sel, double _rate) - { - owned_genops.push_back(new eoSelBinGenOp(_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& _op, double _rate) - { - owned_genops.push_back(new eoQuadGenOp(_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& _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 vector*> ops; private : - vector*> owned_genops; + eoFunctorStore store; unsigned max_to_produce; }; diff --git a/eo/src/eoProportionalCombinedOp.h b/eo/src/eoProportionalCombinedOp.h index 20b3eb7a..b36c1d2c 100644 --- a/eo/src/eoProportionalCombinedOp.h +++ b/eo/src/eoProportionalCombinedOp.h @@ -28,19 +28,16 @@ #include #include #include -#include -#include -#include #include /** \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 public: /// Ctor from a "true" operator eoPropCombinedMonOp(eoMonOp & _first, const double _rate) - { - ops.push_back(&_first); - rates.push_back(_rate); - } - - /// Ctor from a generic operator - eoPropCombinedMonOp(eoGenericMonOp & _first, const double _rate) - { - eoGeneric2TrueMonOp *trueFirst = - new eoGeneric2TrueMonOp(_first); - ops.push_back(trueFirst); + { + ops.push_back(&_first); rates.push_back(_rate); } virtual string className() const { return "eoPropCombinedMonOp"; } virtual void add(eoMonOp & _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 & _op, const double _rate, bool _verbose=false) - { - eoGeneric2TrueMonOp *trueOp = new eoGeneric2TrueMonOp(_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*> ops; @@ -124,7 +102,7 @@ std::vector rates; //// combined BinOp ////////////////////////////////////////////////////// -/** COmbined Binary genetic operator: +/** COmbined Binary genetic operator: * operator() has two operands, only the first one can be modified */ template @@ -133,16 +111,16 @@ class eoPropCombinedBinOp: public eoBinOp public: /// Ctor eoPropCombinedBinOp(eoBinOp & _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 & _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 & _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*> ops; @@ -172,13 +150,13 @@ std::vector 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 @@ -187,17 +165,8 @@ class eoPropCombinedQuadOp: public eoQuadOp public: /// Ctor from a true operator eoPropCombinedQuadOp(eoQuadOp & _first, const double _rate) - { - ops.push_back(&_first); - rates.push_back(_rate); - } - - /// Ctor from a generic operator - eoPropCombinedQuadOp(eoGenericQuadOp & _first, const double _rate) - { - eoGeneric2TrueQuadOp *trueFirst = - new eoGeneric2TrueQuadOp(_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 & _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 & _op, const double _rate, bool _verbose=false) - { - eoGeneric2TrueQuadOp *trueOp = new eoGeneric2TrueQuadOp(_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 & _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*> ops; @@ -247,6 +205,6 @@ std::vector rates; }; -// for General Ops, it's another story - see eoGOpSelector -#endif +// for General Ops, it's another story - +#endif diff --git a/eo/src/eoSGA.h b/eo/src/eoSGA.h index 53054658..3cd90fd0 100644 --- a/eo/src/eoSGA.h +++ b/eo/src/eoSGA.h @@ -27,7 +27,7 @@ #ifndef _eoSGA_h #define _eoSGA_h -#include +#include #include #include #include @@ -36,13 +36,13 @@ #include #include -/** 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 eoSGA : public eoAlgo @@ -57,8 +57,8 @@ public : eoMonOp& _mutate, float _mrate, eoEvalFunc& _eval, eoContinue& _cont) - : cont(_cont), - mutate(_mutate), + : cont(_cont), + mutate(_mutate), mutationRate(_mrate), cross(_cross), crossoverRate(_crate), @@ -68,42 +68,44 @@ public : void operator()(eoPop& _pop) { eoPop 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(eval, _pop); - + } while (cont(_pop)); } - + private : eoContinue& cont; - eoMonOp& mutate; + /// eoInvalidateMonOp invalidates the embedded operator + eoInvalidateMonOp mutate; float mutationRate; - eoQuadOp& cross; + // eoInvalidateQuadOp invalidates the embedded operator + eoInvalidateQuadOp cross; float crossoverRate; eoSelectPerc select; eoEvalFunc& eval; diff --git a/eo/src/eoSGATransform.h b/eo/src/eoSGATransform.h index 98af3dd5..e06aad6d 100644 --- a/eo/src/eoSGATransform.h +++ b/eo/src/eoSGATransform.h @@ -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 +#include #include /////////////////////////////////////////////////////////////////////////////// @@ -148,16 +148,16 @@ template class eoDynSGATransform : public eoTransform }; // 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& cross; + eoInvalidateQuadOp cross; double crossoverProbaHolder; // the value, used only if ctor gets a value double& crossoverProba; // the reference, to be used in operator() - eoMonOp& mutate; + eoInvalidateMonOp mutate; double mutationProbaHolder; // the value, used only if ctor gets a value double& mutationProba; // the reference, to be used in operator() }; diff --git a/eo/src/eoVariableLengthCrossover.h b/eo/src/eoVariableLengthCrossover.h index 9e6aa72f..72f7cba5 100644 --- a/eo/src/eoVariableLengthCrossover.h +++ b/eo/src/eoVariableLengthCrossover.h @@ -29,13 +29,12 @@ #include #include -#include -#include +#include /** - 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 eoVlAtomExchangeQuadOp : public eoGenericQuadOp +class eoVlAtomExchangeQuadOp : public eoQuadOp { public : - + typedef typename EOT::AtomType AtomType; - + // default ctor: requires bounds on number of genes + a rate - eoVlAtomExchangeQuadOp(unsigned _Min, unsigned _Max, - eoAtomExchange& _atomExchange): + eoVlAtomExchangeQuadOp(unsigned _Min, unsigned _Max, + eoAtomExchange& _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 ( ( (i1Max) || (i2>Max) ) + } while ( ( (i1Max) || (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 eoVlUniformQuadOp : public eoGenericQuadOp +class eoVlUniformQuadOp : public eoQuadOp { 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()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 eoVlUniformBinOp : public eoGenericBinOp +class eoVlUniformBinOp : public eoBinOp { 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++) diff --git a/eo/src/eoVariableLengthMutation.h b/eo/src/eoVariableLengthMutation.h index a23f0b88..6bea7d11 100644 --- a/eo/src/eoVariableLengthMutation.h +++ b/eo/src/eoVariableLengthMutation.h @@ -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 #include -#include +#include /** - 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 eoVlAllMutation : public eoGenericMonOp +class eoVlAllMutation : public eoMonOp { public : - + typedef typename EOT::AtomType AtomType; - + // default ctor: requires an Atom mutation - eoVlAllMutation(eoGenericMonOp & _atomMutation) : + eoVlAllMutation(eoMonOp & _atomMutation) : atomMutation(_atomMutation) {} - + bool operator()(EOT & _eo) { bool modified=false; @@ -61,23 +61,23 @@ public : return modified; } private: - eoGenericMonOp & atomMutation; + eoMonOp & 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 eoVlKMutation : public eoGenericMonOp +class eoVlKMutation : public eoMonOp { public : - + typedef typename EOT::AtomType AtomType; - + // default ctor: requires an Atom mutation - eoVlKMutation(eoGenericMonOp & _atomMutation, unsigned _nb=1) : + eoVlKMutation(eoMonOp & _atomMutation, unsigned _nb=1) : nb(_nb), atomMutation(_atomMutation) {} - + bool operator()(EOT & _eo) { bool modified=false; @@ -91,7 +91,7 @@ public : } private: unsigned nb; - eoGenericMonOp & atomMutation; + eoMonOp & atomMutation; }; /** Addition of a gene @@ -99,20 +99,20 @@ private: order-dependent and order-independent */ template -class eoVlAddMutation : public eoGenericMonOp +class eoVlAddMutation : public eoMonOp { 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 & _atomInit) : + eoVlAddMutation(unsigned _nMax, eoInit & _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 eoVlDelMutation : public eoGenericMonOp +class eoVlDelMutation : public eoMonOp { 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 & _chooser) : + eoVlDelMutation(unsigned _nMin, eoGeneDelChooser & _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) diff --git a/eo/src/es/eoEsMutate.h b/eo/src/es/eoEsMutate.h index 7521eb04..9b453ecd 100644 --- a/eo/src/es/eoEsMutate.h +++ b/eo/src/es/eoEsMutate.h @@ -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& _eo) + virtual bool operator()( eoEsSimple& _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& _eo ) + virtual bool operator()( eoEsStdev& _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 & _eo ) + + // Code from Thomas Baeck + + virtual bool operator()( eoEsFull & _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 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, eoEsMutationInit& _init) { init(eoEsStdev(), _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 */ diff --git a/eo/src/es/eoEsStdevXOver.h b/eo/src/es/eoEsStdevXOver.h index 035cdf78..c13adf6e 100644 --- a/eo/src/es/eoEsStdevXOver.h +++ b/eo/src/es/eoEsStdevXOver.h @@ -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 eoEsStdevXOver : public eoQuadOp { public : - eoEsStdevXOver(eoGenericQuadOp > & _objectXOver, - eoGenericQuadOp > & _stdDevXOver) : + eoEsStdevXOver(eoQuadOp > & _objectXOver, + eoQuadOp > & _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 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 > & objectXOver; - eoGenericQuadOp > & stdDevXOver; + eoQuadOp > & objectXOver; + eoQuadOp > & stdDevXOver; }; /* A question: it seems it really makes no difference to have diff --git a/eo/src/es/eoGenericRealOp.h b/eo/src/es/eoGenericRealOp.h index c29fd162..d037df8d 100644 --- a/eo/src/es/eoGenericRealOp.h +++ b/eo/src/es/eoGenericRealOp.h @@ -31,27 +31,26 @@ in eoRealOp.h. So they can be used when part of the genotype is a vector ... 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 // swap_ranges #include -#include -#include +#include #include //----------------------------------------------------------------------------- -/** 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 eoGenericUniformMutation: public eoGenericMonOp +template class eoGenericUniformMutation: public eoMonOp { public: /** @@ -61,8 +60,8 @@ template class eoGenericUniformMutation: public eoGenericMonOp * @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 eoGenericUniformMutation: public eoGenericMonOp * @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 eoGenericUniformMutation: public eoGenericMonOp 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 eoGenericDetUniformMutation: - public eoGenericMonOp +template class eoGenericDetUniformMutation: + public eoMonOp { public: /** @@ -126,8 +125,8 @@ template 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 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 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 eoGenericSegmentCrossover: public eoGenericQuadOp +template class eoGenericSegmentCrossover: public eoQuadOp { 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 eoGenericSegmentCrossover: public eoGenericQuadOp * @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 eoGenericSegmentCrossover: public eoGenericQuadOp { 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 eoGenericArithmeticCrossover: - public eoGenericQuadOp +template class eoGenericArithmeticCrossover: + public eoQuadOp { 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 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 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 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 eoGenericRealUxOver: public eoGenericQuadOp +template class eoGenericRealUxOver: public eoQuadOp { public: /** @@ -378,7 +377,7 @@ template class eoGenericRealUxOver: public eoGenericQuadOp * @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 eoGenericRealUxOver: public eoGenericQuadOp * @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 eoGenericRealUxOver: public eoGenericQuadOp private: double preference; }; - + //----------------------------------------------------------------------------- //@} diff --git a/eo/src/es/eoNormalMutation.h b/eo/src/es/eoNormalMutation.h index 922ee6aa..3398e7a0 100644 --- a/eo/src/es/eoNormalMutation.h +++ b/eo/src/es/eoNormalMutation.h @@ -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 eoNormalMutation: public eoMonOp * @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 eoNormalMutation: public eoMonOp * @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 !) */ diff --git a/eo/src/es/eoRealOp.h b/eo/src/es/eoRealOp.h index 05238671..b13619d6 100644 --- a/eo/src/es/eoRealOp.h +++ b/eo/src/es/eoRealOp.h @@ -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 eoUniformMutation: public eoMonOp * @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 eoUniformMutation: public eoMonOp * @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 eoUniformMutation: public eoMonOp 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 eoDetUniformMutation: public eoMonOp * @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 eoDetUniformMutation: public eoMonOp * Do it! * @param _eo The cromosome undergoing the mutation */ - void operator()(EOT& _eo) + bool operator()(EOT& _eo) { - _eo.invalidate(); for (unsigned i=0; i class eoDetUniformMutation: public eoMonOp 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 eoSegmentCrossover: public eoQuadOp * (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 eoSegmentCrossover: public eoQuadOp * @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 eoSegmentCrossover: public eoQuadOp { 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 eoSegmentCrossover: public eoQuadOp _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 eoArithmeticCrossover: public eoQuadOp * (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 eoArithmeticCrossover: public eoQuadOp * @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 eoArithmeticCrossover: public eoQuadOp { 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 eoArithmeticCrossover: public eoQuadOp _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 eoRealUxOver: public eoQuadOp * @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 eoRealUxOver: public eoQuadOp changed = true; } } - if (changed) - { - _eo1.invalidate(); - _eo2.invalidate(); - } + return changed; } private: float preference; diff --git a/eo/src/ga/eoBitOp.h b/eo/src/ga/eoBitOp.h index c798d991..816d5cbe 100644 --- a/eo/src/ga/eoBitOp.h +++ b/eo/src/ga/eoBitOp.h @@ -60,7 +60,7 @@ #include -/** eoBitFlip --> changes 1 bit +/** eoBitFlip --> changes 1 bit \class eoBitBitFlip eoBitOp.h ga/eoBitOp.h \ingroup bitstring */ @@ -70,20 +70,20 @@ template class eoOneBitFlip: public eoMonOp 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 eoDetBitFlip: public eoMonOp /// 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 class eoDetBitFlip: public eoMonOp 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 eoBitMutation: public eoMonOp * 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 eoBitMutation: public eoMonOp 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 eoBitInversion: public eoMonOp * 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 eoBitNext: public eoMonOp 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 eoBitNext: public eoMonOp 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 eoBitPrev: public eoMonOp 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 eoBitPrev: public eoMonOp { 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 eo1PtBitXover: public eoQuadOp * @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 eo1PtBitXover: public eoQuadOp { 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 eoUBitXover: public eoQuadOp 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 eoUBitXover: public eoQuadOp * @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 class eoUBitXover: public eoQuadOp 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 eoNPtsBitXover: public eoQuadOp 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 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 eoNPtsBitXover: public eoQuadOp 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 eoBitGxOver: public eoQuadOp { 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 points(max_genes, false); // selects genes to swap @@ -454,11 +448,10 @@ template class eoBitGxOver: public eoQuadOp 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; diff --git a/eo/src/gp/eoParseTree.h b/eo/src/gp/eoParseTree.h index fb6e55c2..2a7f5571 100644 --- a/eo/src/gp/eoParseTree.h +++ b/eo/src/gp/eoParseTree.h @@ -148,7 +148,7 @@ private : unsigned max_depth; std::vector initializor; - bool grow; + bool grow; }; template @@ -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::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 eoBranchMutation: public eoMonOp< eoParseTree > +class eoBranchMutation: public eoMonOp< eoParseTree > { public: typedef eoParseTree EoType; eoBranchMutation(eoInit& _init, unsigned _max_length) - : eoMonOp(), max_length(_max_length), initializer(_init) + : eoMonOp(), 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& initializer; + eoInit& initializer; }; diff --git a/eo/src/eoGenericBinOp.h b/eo/src/obsolete/eoGenericBinOp.h similarity index 100% rename from eo/src/eoGenericBinOp.h rename to eo/src/obsolete/eoGenericBinOp.h diff --git a/eo/src/eoGenericMonOp.h b/eo/src/obsolete/eoGenericMonOp.h similarity index 100% rename from eo/src/eoGenericMonOp.h rename to eo/src/obsolete/eoGenericMonOp.h diff --git a/eo/src/eoGenericQuadOp.h b/eo/src/obsolete/eoGenericQuadOp.h similarity index 100% rename from eo/src/eoGenericQuadOp.h rename to eo/src/obsolete/eoGenericQuadOp.h diff --git a/eo/src/other/eoExternalOpFunctions.h b/eo/src/other/eoExternalOpFunctions.h index 906460fb..62fd757c 100644 --- a/eo/src/other/eoExternalOpFunctions.h +++ b/eo/src/other/eoExternalOpFunctions.h @@ -46,13 +46,13 @@ class eoExternalInit : public eoInit { 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 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 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 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 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 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 : diff --git a/eo/src/utils/eoState.h b/eo/src/utils/eoState.h index d069338d..ffb19536 100644 --- a/eo/src/utils/eoState.h +++ b/eo/src/utils/eoState.h @@ -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(*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 creationOrder; std::vector 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&); diff --git a/eo/test/run_tests b/eo/test/run_tests index 59e02684..7d269d1f 100755 --- a/eo/test/run_tests +++ b/eo/test/run_tests @@ -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 diff --git a/eo/test/t-eoGenOp.cpp b/eo/test/t-eoGenOp.cpp index 88b04f42..40c79d19 100644 --- a/eo/test/t-eoGenOp.cpp +++ b/eo/test/t-eoGenOp.cpp @@ -23,7 +23,7 @@ */ //----------------------------------------------------------------------------- -/** test program for the general operator - millenium version! +/** test program for the general operator - millenium version! * uses dummy individuals */ #include @@ -53,10 +53,11 @@ class monop : public eoMonOp { 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 class binop: public eoBinOp { 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 { 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 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 { public : string className() {return "quadclone";} - void operator()(EOT& , EOT& ) {} + bool operator()(EOT& , EOT& ) {return false;} }; // User defined General Operator... adapted from Marc's example