diff --git a/eo/src/eoRanking.h b/eo/src/eoRanking.h index 63a031071..212074aae 100644 --- a/eo/src/eoRanking.h +++ b/eo/src/eoRanking.h @@ -28,6 +28,7 @@ #define eoRanking_h #include "eoPerf2Worth.h" +#include /** An instance of eoPerfFromWorth * COmputes the ranked fitness: fitnesses range in [m,M] @@ -40,73 +41,93 @@ template class eoRanking : public eoPerf2Worth // false: do not cache fitness { public: - - using eoPerf2Worth::value; + using eoPerf2Worth::value; /* 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) {} + eoRanking(double _p = 2.0, double _e = 1.0) : pressure(_p), exponent(_e), cached_pSize(0) {} /* helper function: finds index in _pop of _eo, an EOT * */ - int lookfor(const EOT *_eo, const eoPop& _pop) + /* + int lookfor(const EOT *_eo, const eoPop &_pop) + { + typename eoPop::const_iterator it; + for (it = _pop.begin(); it < _pop.end(); it++) { - typename eoPop::const_iterator it; - for (it=_pop.begin(); it<_pop.end(); it++) - { - if (_eo == &(*it)) - return it-_pop.begin(); - } - throw eoException("Not found in eoLinearRanking"); + if (_eo == &(*it)) + return it - _pop.begin(); } + throw eoException("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 depstd::ends on exponent (linear if 1). */ - virtual void operator()(const eoPop& _pop) + virtual void operator()(const eoPop &_pop) + { + + unsigned pSize = _pop.size(); + + if (pSize <= 1) + throw eoPopSizeException(pSize, "cannot do ranking with population of size <= 1"); + + // value() refers to the std::vector of worthes (we're in an eoParamvalue) + value().resize(pSize); + + // Cache only if population size changed + if (pSize != cached_pSize) { - std::vector rank; - _pop.sort(rank); - unsigned pSize =_pop.size(); - unsigned int pSizeMinusOne = pSize-1; - - if (pSize <= 1) - throw eoPopSizeException(pSize,"cannot do ranking with population of size <= 1"); - - // value() refers to the std::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 1/[P(P-1)/2] - } - } - else // exponent != 1 - { - double gamma = (2*pressure-2)/pSize; - for (unsigned i=0; i rank; + _pop.sort(rank); + + // vector of indices sorted by fitness + std::vector indices(pSize); + for (size_t i = 0; i < pSize; ++i) + indices[i] = i; + + if (exponent == 1.0) // no need for exponetial then + { + for (unsigned i = 0; i < pSize; i++) + { + int which = indices[i]; + ; + value()[which] = cached_alpha * (pSize - i) + cached_beta; // worst -> 1/[P(P-1)/2] + } + } + else // exponent != 1 + { + for (unsigned i = 0; i < pSize; i++) + { + int which = indices[i]; + // value in in [0,1] + double tmp = ((double)(pSize - i)) / pSize; + // to the exponent, and back to [m,M] + value()[which] = cached_gamma * pow(tmp, exponent) + cached_beta; + } + } + } + +private: + double pressure; // selective pressure double exponent; + + // Cached values + unsigned cached_pSize; + unsigned cached_pSizeMinusOne; + double cached_alpha; + double cached_beta; + double cached_gamma; }; - - #endif