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)
This commit is contained in:
evomarc 2001-02-16 08:21:25 +00:00
commit 7e849e2082
8 changed files with 465 additions and 121 deletions

View file

@ -29,78 +29,25 @@
//-----------------------------------------------------------------------------
#include <utils/eoRNG.h>
#include <utils/selectors.h>
#include <eoSelectOne.h>
#include <eoSelectFromWorth.h>
#include <eoLinearFitScaling.h>
//-----------------------------------------------------------------------------
/** 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 EOT> class eoFitnessScalingSelect: public eoSelectOne<EOT>
template <class EOT>
class eoFitnessScalingSelect: public eoRouletteWorthSelect<EOT, double>
{
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<EOT>& _pop = eoPop<EOT>()):
pressure(_p), scaledFitness(0)
{
if (minimizing_fitness<EOT>())
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<EOT>& _pop)
{
unsigned pSize =_pop.size();
scaledFitness.resize(pSize);
// best and worse fitnesses
double bestFitness = static_cast<double> (_pop.best_element().fitness());
double worstFitness = static_cast<double> (_pop.worse_element().fitness());
// average fitness
double sum=0.0;
for (unsigned i=0; i<pSize; i++)
sum += static_cast<double>(_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<pSize; i++) // truncate to 0
{
scaledFitness[i] = max(alpha*_pop[i].fitness()+beta, 0.0);
}
}
/** do the selection, call roulette_wheel on rankFitness
*/
const EOT& operator()(const eoPop<EOT>& _pop)
{
unsigned selected = rng.roulette_wheel(scaledFitness);
return _pop[selected];
}
eoFitnessScalingSelect(double _p = 2.0):
eoRouletteWorthSelect<EOT, double>(scaling), scaling(_p) {}
private :
double pressure;
vector<double> scaledFitness;
eoLinearFitScaling<EOT> scaling; // derived from eoPerf2Worth
};
#endif

View file

@ -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 <eoSelectFromWorth.h>
#include <eoPerf2Worth.h>
/* 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 EOT>
class eoLinearFitScaling : public eoPerf2Worth<EOT>
{
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<EOT>& _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<double> (_pop.best_element().fitness());
// double worstFitness = static_cast<double> (_pop.worse_element().fitness());
// average fitness
double sum=0.0;
for (unsigned i=0; i<pSize; i++)
sum += static_cast<double>(_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<pSize; i++) // truncate to 0
{
value()[i] = max(alpha*_pop[i].fitness()+beta, 0.0);
}
}
private:
double pressure; // selective pressure
};
#endif

48
eo/src/eoPerf2Worth.h Normal file
View file

@ -0,0 +1,48 @@
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoPerf2Worth.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 eoPerf2Worth_h
#define eoPerf2Worth_h
#include <utils/eoStat.h>
/** 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 EOT, class WorthT = double>
class eoPerf2Worth : public eoStat<EOT, vector<WorthT> >
{
public:
eoPerf2Worth():eoStat<EOT, vector<WorthT> >(vector<WorthT>(0),
"Worthes") {}
};
#endif

104
eo/src/eoRanking.h Normal file
View file

@ -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 <eoPerf2Worth.h>
/* 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 EOT>
class eoRanking : public eoPerf2Worth<EOT>
{
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<EOT>& _pop)
{
eoPop<EOT>::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<EOT>& _pop)
{
vector<const EOT *> 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<pSize; i++)
{
int which = lookfor(rank[i], _pop);
value()[which] = alpha*(pSizeMinusOne-i)+beta;
}
}
else // exponent != 1
{
double gamma = (2*pressure-2)/pSize;
for (unsigned i=0; i<pSize; i++)
{
int which = lookfor(rank[i], _pop);
// value in in [0,1]
double tmp = ((double)(pSizeMinusOne-i))/pSizeMinusOne;
// to the exponent, and back to [m,M]
value()[which] = gamma*pow(tmp, exponent)+beta;
}
}
}
private:
double pressure; // selective pressure
double exponent;
};
#endif

View file

@ -18,8 +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: todos@geneura.ugr.es, http://geneura.ugr.es
Marc.Schoenauer@polytechnique.fr
Contact: Marc.Schoenauer@polytechnique.fr
mak@dhi.dk
*/
//-----------------------------------------------------------------------------
@ -29,61 +28,28 @@
//-----------------------------------------------------------------------------
#include <utils/eoRNG.h>
#include <utils/selectors.h>
#include <eoSelectOne.h>
#include <eoSelectFromWorth.h>
#include <eoRanking.h>
//-----------------------------------------------------------------------------
/** 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<EOT, double>
*/
//-----------------------------------------------------------------------------
template <class EOT> class eoRankingSelect: public eoSelectOne<EOT>
template <class EOT>
class eoRankingSelect: public eoRouletteWorthSelect<EOT, double>
{
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<EOT>& _pop = eoPop<EOT>()):
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<EOT>& _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<pSize; i++)
{
rankFitness[i] = alpha*(pSize-1-i)+beta;
}
}
/** do the selection, call roulette_wheel on rankFitness
*/
const EOT& operator()(const eoPop<EOT>& _pop)
{
unsigned selected = rng.roulette_wheel(rankFitness);
return *(rank[selected]);
}
eoRankingSelect(double _p = 2.0, double _e=1.0):
eoRouletteWorthSelect<EOT, double>(ranking), ranking(_p, _e) {}
private :
double pressure;
vector<const EOT *> rank;
vector<double> rankFitness;
eoRanking<EOT> ranking; // derived from eoPerf2Worth
};
#endif

175
eo/src/eoSelectFromWorth.h Normal file
View file

@ -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 <eoSelectOne.h>
#include <eoPerf2Worth.h>
#include <utils/selectors.h>
//-----------------------------------------------------------------------------
/** 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 EOT, class WorthType = double>
class eoSelectFromWorth : public eoSelectOne<EOT>
{
public:
/* Default ctor from an eoPerf2Worth object
*/
eoSelectFromWorth(eoPerf2Worth<EOT, WorthType> & _perf2Worth) :
perf2Worth(_perf2Worth) {}
/* setup the worthes */
virtual void setup(const eoPop<EOT>& _pop)
{
perf2Worth(_pop);
}
protected:
eoPerf2Worth<EOT, WorthType> & perf2Worth;
};
/** An instance of eoSelectPerf2Worth that does selection from the Worthes
* using a ... determinisitic tournament, yes!
*/
template <class EOT, class WorthT = double>
class eoDetTournamentWorthSelect : public eoSelectFromWorth<EOT, WorthT>
{
public:
typedef vector<WorthT>::iterator worthIterator;
/* Default ctor from an eoPerf2Worth object + tournament size
*/
eoDetTournamentWorthSelect(eoPerf2Worth<EOT, WorthT> &_perf2Worth,
unsigned _tSize) :
eoSelectFromWorth<EOT, WorthT>(_perf2Worth), tSize(_tSize) {}
/* Perform deterministic tournament on worthes
by calling the appropriate fn
see selectors.h
*/
virtual const EOT& operator()(const eoPop<EOT>& _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 EOT, class WorthT = double>
class eoStochTournamentWorthSelect : public eoSelectFromWorth<EOT, WorthT>
{
public:
typedef vector<WorthT>::iterator worthIterator;
/* Default ctor from an eoPerf2Worth object + tournament rate
*/
eoStochTournamentWorthSelect(eoPerf2Worth<EOT, WorthT> &_perf2Worth,
double _tRate) :
eoSelectFromWorth<EOT, WorthT>(_perf2Worth), tRate(_tRate) {}
/* Perform stochastic tournament on worthes
by calling the appropriate fn in selectors.h
*/
virtual const EOT& operator()(const eoPop<EOT>& _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 EOT, class WorthT = double>
class eoRouletteWorthSelect : public eoSelectFromWorth<EOT, WorthT>
{
public:
typedef vector<WorthT>::iterator worthIterator;
/* Default ctor from an eoPerf2Worth object
*/
eoRouletteWorthSelect(eoPerf2Worth<EOT, WorthT> &_perf2Worth) :
eoSelectFromWorth<EOT, WorthT>(_perf2Worth) {}
/* We have to override the default behavior to compute the total
* only once!
*/
virtual void setup(const eoPop<EOT>& _pop)
{
perf2Worth(_pop);
total = 0.0;
for (worthIterator it = perf2Worth.value().begin();
it<perf2Worth.value().end(); ++it)
total += (*it);
}
/* Perform deterministic tournament on worthes
by calling the appropriate fn
see selectors.h
*/
virtual const EOT& operator()(const eoPop<EOT>& _pop)
{
worthIterator it = roulette_wheel(
perf2Worth.value().begin(),
perf2Worth.value().end(),
total);
return _pop[it-perf2Worth.value().begin()];
}
private:
double total;
};
#endif

View file

@ -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;

View file

@ -16,6 +16,8 @@
// general
#include <eo>
#include <eoFitnessScalingSelect.h>
#include <eoSelectFromWorth.h>
#include <eoLinearFitScaling.h>
//-----------------------------------------------------------------------------
struct Dummy : public EO<double>
@ -123,8 +125,6 @@ eoValueParam<unsigned int> tournamentSizeParam = parser.createParam<unsigned int
exit(1);
}
unsigned i;
cout << "Testing the Selections\nParents size = " << pSize
<< ", offspring rate = " << oRate << endl;
@ -132,16 +132,26 @@ eoValueParam<unsigned int> tournamentSizeParam = parser.createParam<unsigned int
// the selection procedures under test
eoDetSelect<Dummy> detSelect(oRate);
testSelectMany(detSelect, "detSelect");
// eoDetSelect<Dummy> detSelect(oRate);
// testSelectMany(detSelect, "detSelect");
// Roulette
eoProportionalSelect<Dummy> propSelect;
testSelectOne<Dummy>(propSelect, oRate, "propSelect");
// eoProportionalSelect<Dummy> propSelect;
// testSelectOne<Dummy>(propSelect, oRate, "propSelect");
// Ranking
eoRankingSelect<Dummy> rankSelect(rankingPressure);
testSelectOne<Dummy>(rankSelect, oRate, "rankSelect");
// eoRankingSelect<Dummy> rankSelect(rankingPressure);
// testSelectOne<Dummy>(rankSelect, oRate, "rankSelect");
// New ranking using the perf2Worth construct
cout << "Avant appel a LinearRanking()" << endl;
eoRankingSelect<Dummy> newRankingSelect(rankingPressure); // pressure 2 by default
testSelectOne<Dummy>(newRankingSelect, oRate, "newRankSelect");
// New ranking using the perf2Worth construct
cout << "Avant appel a exponentialRanking()" << endl;
eoRankingSelect<Dummy> expRankingSelect(rankingPressure,2);
testSelectOne<Dummy>(expRankingSelect, oRate, "expRankingSelect");
// Det tournament
eoDetTournamentSelect<Dummy> detTourSelect(tSize);
@ -152,8 +162,12 @@ eoValueParam<unsigned int> tournamentSizeParam = parser.createParam<unsigned int
testSelectOne<Dummy>(stochTourSelect, oRate, "stochTourSelect");
// Fitness scaling
eoFitnessScalingSelect<Dummy> fitScaleSelect(rankingPressure);
testSelectOne<Dummy>(fitScaleSelect, oRate, "fitScaleSelect");
// eoFitnessScalingSelect<Dummy> fitScaleSelect(rankingPressure);
// testSelectOne<Dummy>(fitScaleSelect, oRate, "fitScaleSelect");
// NEW Fitness scaling
eoFitnessScalingSelect<Dummy> newFitScaleSelect(rankingPressure);
testSelectOne<Dummy>(newFitScaleSelect, oRate, "NewFitScaleSelect");
return 1;
}