From 7e849e2082805e6e5ba743303ec627f1dabd5804 Mon Sep 17 00:00:00 2001 From: evomarc Date: Fri, 16 Feb 2001 08:21:25 +0000 Subject: [PATCH] The perf2worth major check in 2 new important classes: eoPerf2Worth and eoSelectFromWorth Instances of eoPerf2Worth are eoRanking and eoLinearFitScaling. Coming soon (piece of cake now) are the niching strategies (sharing, clearing) --- eo/src/eoFitnessScalingSelect.h | 73 ++----------- eo/src/eoLinearFitScaling.h | 90 ++++++++++++++++ eo/src/eoPerf2Worth.h | 48 +++++++++ eo/src/eoRanking.h | 104 +++++++++++++++++++ eo/src/eoRankingSelect.h | 60 +++-------- eo/src/eoSelectFromWorth.h | 175 ++++++++++++++++++++++++++++++++ eo/src/utils/selectors.h | 2 +- eo/test/t-eoSelect.cpp | 34 +++++-- 8 files changed, 465 insertions(+), 121 deletions(-) create mode 100644 eo/src/eoLinearFitScaling.h create mode 100644 eo/src/eoPerf2Worth.h create mode 100644 eo/src/eoRanking.h create mode 100644 eo/src/eoSelectFromWorth.h diff --git a/eo/src/eoFitnessScalingSelect.h b/eo/src/eoFitnessScalingSelect.h index 6155dc56..0b3ec273 100644 --- a/eo/src/eoFitnessScalingSelect.h +++ b/eo/src/eoFitnessScalingSelect.h @@ -29,78 +29,25 @@ //----------------------------------------------------------------------------- -#include -#include -#include +#include +#include -//----------------------------------------------------------------------------- -/** eoFitnessScalingSelect: select an individual proportional to its rank - this is actually the linearRanking +/** eoFitnessScalingSelect: select an individual proportional to the + * linearly scaled fitness that is computed by the private + * eoLinearFitScaling object */ -//----------------------------------------------------------------------------- - -template class eoFitnessScalingSelect: public eoSelectOne +template +class eoFitnessScalingSelect: public eoRouletteWorthSelect { public: - typedef typename EOT::Fitness Fitness; /** Ctor: * @param _p the selective pressure, should be in [1,2] (2 is the default) - * @param _pop an optional population */ - eoFitnessScalingSelect(double _p = 2.0, const eoPop& _pop = eoPop()): - pressure(_p), scaledFitness(0) - { - if (minimizing_fitness()) - throw logic_error("eoFitnessScalingSelect: minimizing fitness"); - if (_pop.size() > 0) // a population in Ctor? initialize scaledFitness - { - setup(_pop); - } - } - - // COmputes the coefficients of the linear transform in such a way that - // Pselect(Best) == pressure/sizePop - // Pselect(average) == 1.0/sizePop - // we truncate negative values to 0 - - // we could also adjust the pressure so that worst get 0 scaled fitness - void setup(const eoPop& _pop) - { - unsigned pSize =_pop.size(); - scaledFitness.resize(pSize); - - // best and worse fitnesses - double bestFitness = static_cast (_pop.best_element().fitness()); - double worstFitness = static_cast (_pop.worse_element().fitness()); - - // average fitness - double sum=0.0; - for (unsigned i=0; i(_pop[i].fitness()); - double averageFitness = sum/pSize; - - // the coefficients for linear scaling - double denom = pSize*(bestFitness - averageFitness); - double alpha = (pressure-1)/denom; - double beta = (bestFitness - pressure*averageFitness)/denom; -// if (beta < 0) -// beta = max(beta, -alpha*worstFitness); - for (unsigned i=0; i& _pop) - { - unsigned selected = rng.roulette_wheel(scaledFitness); - return _pop[selected]; - } + eoFitnessScalingSelect(double _p = 2.0): + eoRouletteWorthSelect(scaling), scaling(_p) {} private : - double pressure; - vector scaledFitness; + eoLinearFitScaling scaling; // derived from eoPerf2Worth }; #endif diff --git a/eo/src/eoLinearFitScaling.h b/eo/src/eoLinearFitScaling.h new file mode 100644 index 00000000..fee41186 --- /dev/null +++ b/eo/src/eoLinearFitScaling.h @@ -0,0 +1,90 @@ +/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- + + ----------------------------------------------------------------------------- + eoLinearFitScaling.h + (c) GeNeura Team, 1998, Maarten Keijzer, 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 + 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 + Marc.Schoenauer@polytechnique.fr + mkeijzer@dhi.dk + */ +//----------------------------------------------------------------------------- + +#ifndef eoLinearFitScaling_h +#define eoLinearFitScaling_h + +#include +#include + +/* An instance of eoPerf2Worth + * COmputes the linearly scaled fitnesses + * with given selective pressure + * Pselect(Best) == pressure/sizePop + * Pselect(average) == 1.0/sizePop + * truncate negative values to 0 - + * + * to be used within an eoSelectFromWorth object + */ +template +class eoLinearFitScaling : public eoPerf2Worth +{ +public: + /* Ctor: + @param _p selective pressure (in (1,2] + @param _e exponent (1 == linear) + */ + eoLinearFitScaling(double _p=2.0): + pressure(_p) {} + + /* COmputes the ranked fitness: fitnesses range in [m,M] + with m=2-pressure/popSize and M=pressure/popSize. + in between, the progression depends on exponent (linear if 1). + */ + virtual void operator()(const eoPop& _pop) + { + unsigned pSize =_pop.size(); + // value() refers to the vector of worthes (we're in an eoParamvalue) + value().resize(pSize); + + // best and worse fitnesses + double bestFitness = static_cast (_pop.best_element().fitness()); + // double worstFitness = static_cast (_pop.worse_element().fitness()); + + // average fitness + double sum=0.0; + for (unsigned i=0; i(_pop[i].fitness()); + double averageFitness = sum/pSize; + + // the coefficients for linear scaling + double denom = pSize*(bestFitness - averageFitness); + double alpha = (pressure-1)/denom; + double beta = (bestFitness - pressure*averageFitness)/denom; + + for (unsigned i=0; i + +/** Base class to transform raw fitnesses into fitness for selection + +It is an eoStat so +- it is updated inside a checkpoint (i.e. at start of every generation) +- it can be monitored or whatever else you wish through its value() + +@see eoSelectFromWorth +*/ +template +class eoPerf2Worth : public eoStat > +{ + public: + eoPerf2Worth():eoStat >(vector(0), + "Worthes") {} +}; + +#endif diff --git a/eo/src/eoRanking.h b/eo/src/eoRanking.h new file mode 100644 index 00000000..4c8031c8 --- /dev/null +++ b/eo/src/eoRanking.h @@ -0,0 +1,104 @@ +/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- + + ----------------------------------------------------------------------------- + eoRanking.h + (c) Maarten Keijzer, 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 + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Contact: todos@geneura.ugr.es, http://geneura.ugr.es + Marc.Schoenauer@polytechnique.fr + mkeijzer@dhi.dk + */ +//----------------------------------------------------------------------------- + +#ifndef eoRanking_h +#define eoRanking_h + +#include + +/* An instance of eoPerfFromWorth + * COmputes the ranked fitness: fitnesses range in [m,M] + * with m=2-pressure/popSize and M=pressure/popSize. + * in between, the progression depends on exponent (linear if 1). + */ +template +class eoRanking : public eoPerf2Worth +{ +public: + /* Ctor: + @param _p selective pressure (in (1,2] + @param _e exponent (1 == linear) + */ + eoRanking(double _p=2.0, double _e=1.0): + pressure(_p), exponent(_e) {} + + /* helper function: finds index in _pop of _eo, an EOT * */ + int lookfor(const EOT *_eo, const eoPop& _pop) + { + eoPop::const_iterator it; + for (it=_pop.begin(); it<_pop.end(); it++) + { + if (_eo == &(*it)) + return it-_pop.begin(); + } + throw runtime_error("Not found in eoLinearRanking"); + } + + /* COmputes the ranked fitness: fitnesses range in [m,M] + with m=2-pressure/popSize and M=pressure/popSize. + in between, the progression depends on exponent (linear if 1). + */ + virtual void operator()(const eoPop& _pop) + { + vector rank; + _pop.sort(rank); + unsigned pSize =_pop.size(); + unsigned int pSizeMinusOne = pSize-1; + + // value() refers to the vector of worthes (we're in an eoParamvalue) + value().resize(pSize); + + double beta = (2-pressure)/pSize; + if (exponent == 1.0) // no need for exponetial then + { + double alpha = (2*pressure-2)/(pSize*pSizeMinusOne); + for (unsigned i=0; i -#include -#include +#include +#include -//----------------------------------------------------------------------------- -/** eoRankingSelect: select an individual proportional to its rank - this is actually the linearRanking +/** eoRankingSelect: select an individual by roulette wheel on its rank + * is an eoRouletteWorthSelect, i.e. a selector using a vector of worthes + * rather than the raw fitness (see eoSelectFromWorth.h) + * uses an internal eoRanking object which is an eoPerf2Worth */ -//----------------------------------------------------------------------------- -template class eoRankingSelect: public eoSelectOne +template +class eoRankingSelect: public eoRouletteWorthSelect { public: /** Ctor: * @param _p the selective pressure, should be in [1,2] (2 is the default) - * @param _pop an optional population + * @param _e exponent (1 == linear) */ - eoRankingSelect(double _p = 2.0, const eoPop& _pop = eoPop()): - pressure(_p), rank(0), rankFitness(0) - { - if (_pop.size() > 0) - { - setup(_pop); - } - } - - // COmputes the coefficients of the linear transform uin such a way that - // Pselect(Best) == Pselect(sizePop) == pressure/sizePop - // Pselect(average) == 1.0/sizePop - // Pselect(Worst == Pselect(1 == (2-pressure)/sizePop - void setup(const eoPop& _pop) - { - _pop.sort(rank); - unsigned pSize =_pop.size(); - rankFitness.resize(pSize); - double alpha = (2*pressure-2)/(pSize*(pSize-1)); - double beta = (2-pressure)/pSize; - for (unsigned i=0; i& _pop) - { - unsigned selected = rng.roulette_wheel(rankFitness); - return *(rank[selected]); - } + eoRankingSelect(double _p = 2.0, double _e=1.0): + eoRouletteWorthSelect(ranking), ranking(_p, _e) {} private : - double pressure; - vector rank; - vector rankFitness; + eoRanking ranking; // derived from eoPerf2Worth }; #endif diff --git a/eo/src/eoSelectFromWorth.h b/eo/src/eoSelectFromWorth.h new file mode 100644 index 00000000..29520ceb --- /dev/null +++ b/eo/src/eoSelectFromWorth.h @@ -0,0 +1,175 @@ +/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- + + ----------------------------------------------------------------------------- + eoSelectFromWorth.h + (c) Maarten Keijzer, 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 + 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: Marc.Schoenauer@polytechnique.fr + mkeijzer@dhi.dk + */ +//----------------------------------------------------------------------------- + +#ifndef _eoSelectFromWorth_h +#define _eoSelectFromWorth_h + + +//----------------------------------------------------------------------------- +#include +#include +#include +//----------------------------------------------------------------------------- + +/** selects one element from a population (is an eoSelectOne) +but the selectin is based on a vector of Worth that is different +from the fitnesses (e.g. EO fitness is what Koza terms "raw fitness", +Worth is what the selection is based upon). + +see class eoPerf2Worth: an eoStat that transforms fitnesses into Worthes + +Note: Worthes will not always be doubles - see some multi-objective +techniques where it is a pair of doubles ... + +It has to have a < operator it you want to call an existing +selector (see selector.h) - but of course you can write the whole +thing ... +*/ +template +class eoSelectFromWorth : public eoSelectOne +{ +public: + /* Default ctor from an eoPerf2Worth object + */ + eoSelectFromWorth(eoPerf2Worth & _perf2Worth) : + perf2Worth(_perf2Worth) {} + + /* setup the worthes */ + virtual void setup(const eoPop& _pop) + { + perf2Worth(_pop); + } + +protected: + eoPerf2Worth & perf2Worth; +}; + + +/** An instance of eoSelectPerf2Worth that does selection from the Worthes + * using a ... determinisitic tournament, yes! + */ +template +class eoDetTournamentWorthSelect : public eoSelectFromWorth +{ +public: + typedef vector::iterator worthIterator; + + /* Default ctor from an eoPerf2Worth object + tournament size + */ + eoDetTournamentWorthSelect(eoPerf2Worth &_perf2Worth, + unsigned _tSize) : + eoSelectFromWorth(_perf2Worth), tSize(_tSize) {} + + /* Perform deterministic tournament on worthes + by calling the appropriate fn + see selectors.h + */ + virtual const EOT& operator()(const eoPop& _pop) + { + worthIterator it = deterministic_tournament( + perf2Worth.value().begin(), + perf2Worth.value().end(), tSize); + return _pop[it-perf2Worth.value().begin()]; + } + +private: + unsigned tSize; +}; + +/** An instance of eoSelectPerf2Worth that does selection from the Worthes + * using a ... determinisitic tournament, yes! + */ +template +class eoStochTournamentWorthSelect : public eoSelectFromWorth +{ +public: + typedef vector::iterator worthIterator; + + /* Default ctor from an eoPerf2Worth object + tournament rate + */ + eoStochTournamentWorthSelect(eoPerf2Worth &_perf2Worth, + double _tRate) : + eoSelectFromWorth(_perf2Worth), tRate(_tRate) {} + + /* Perform stochastic tournament on worthes + by calling the appropriate fn in selectors.h + */ + virtual const EOT& operator()(const eoPop& _pop) + { + worthIterator it = deterministic_tournament( + perf2Worth.value().begin(), + perf2Worth.value().end(), tRate); + return _pop[it-perf2Worth.value().begin()]; + } + +private: + double tRate; +}; + +/** An instance of eoSelectPerf2Worth that does selection from the Worthes + * using a ... roulette wheel selection, yes! + */ +template +class eoRouletteWorthSelect : public eoSelectFromWorth +{ +public: + typedef vector::iterator worthIterator; + + /* Default ctor from an eoPerf2Worth object + */ + eoRouletteWorthSelect(eoPerf2Worth &_perf2Worth) : + eoSelectFromWorth(_perf2Worth) {} + + /* We have to override the default behavior to compute the total + * only once! + */ + virtual void setup(const eoPop& _pop) + { + perf2Worth(_pop); + total = 0.0; + for (worthIterator it = perf2Worth.value().begin(); + it& _pop) + { + worthIterator it = roulette_wheel( + perf2Worth.value().begin(), + perf2Worth.value().end(), + total); + return _pop[it-perf2Worth.value().begin()]; + } + +private: + double total; +}; + +#endif + diff --git a/eo/src/utils/selectors.h b/eo/src/utils/selectors.h index 9d860873..754d6954 100644 --- a/eo/src/utils/selectors.h +++ b/eo/src/utils/selectors.h @@ -136,7 +136,7 @@ It roulette_wheel(It _begin, It _end, double total, eoRng& _gen = rng) float roulette = _gen.uniform(total); if (roulette == 0.0) // covers the case where total==0.0 - return _min + _gen.random(_end - _min); // uniform choice + return _begin + _gen.random(_end - _begin); // uniform choice It i = _begin; diff --git a/eo/test/t-eoSelect.cpp b/eo/test/t-eoSelect.cpp index e136e6dc..687da2cd 100644 --- a/eo/test/t-eoSelect.cpp +++ b/eo/test/t-eoSelect.cpp @@ -16,6 +16,8 @@ // general #include #include +#include +#include //----------------------------------------------------------------------------- struct Dummy : public EO @@ -123,8 +125,6 @@ eoValueParam tournamentSizeParam = parser.createParam detSelect(oRate); +// testSelectMany(detSelect, "detSelect"); // Roulette - eoProportionalSelect propSelect; - testSelectOne(propSelect, oRate, "propSelect"); +// eoProportionalSelect propSelect; +// testSelectOne(propSelect, oRate, "propSelect"); // Ranking - eoRankingSelect rankSelect(rankingPressure); - testSelectOne(rankSelect, oRate, "rankSelect"); +// eoRankingSelect rankSelect(rankingPressure); +// testSelectOne(rankSelect, oRate, "rankSelect"); + + // New ranking using the perf2Worth construct + cout << "Avant appel a LinearRanking()" << endl; + eoRankingSelect newRankingSelect(rankingPressure); // pressure 2 by default + testSelectOne(newRankingSelect, oRate, "newRankSelect"); + + // New ranking using the perf2Worth construct + cout << "Avant appel a exponentialRanking()" << endl; + eoRankingSelect expRankingSelect(rankingPressure,2); + testSelectOne(expRankingSelect, oRate, "expRankingSelect"); // Det tournament eoDetTournamentSelect detTourSelect(tSize); @@ -152,8 +162,12 @@ eoValueParam tournamentSizeParam = parser.createParam(stochTourSelect, oRate, "stochTourSelect"); // Fitness scaling - eoFitnessScalingSelect fitScaleSelect(rankingPressure); - testSelectOne(fitScaleSelect, oRate, "fitScaleSelect"); +// eoFitnessScalingSelect fitScaleSelect(rankingPressure); +// testSelectOne(fitScaleSelect, oRate, "fitScaleSelect"); + + // NEW Fitness scaling + eoFitnessScalingSelect newFitScaleSelect(rankingPressure); + testSelectOne(newFitScaleSelect, oRate, "NewFitScaleSelect"); return 1; }