added an #ifdef _MSC_VER statement to hide "typename" identifier for Visual Studio

This commit is contained in:
okoenig 2003-02-20 19:13:33 +00:00
commit 4052187a6c

View file

@ -1,328 +1,334 @@
/* -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- /* -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
selectors.h selectors.h
A bunch of useful selector functions. They generally have three forms: A bunch of useful selector functions. They generally have three forms:
template <class It> template <class It>
It select(It begin, It end, params, eoRng& gen = rng); It select(It begin, It end, params, eoRng& gen = rng);
template <class EOT> template <class EOT>
const EOT& select(const eoPop<EOT>& pop, params, eoRng& gen = rng); const EOT& select(const eoPop<EOT>& pop, params, eoRng& gen = rng);
template <class EOT> template <class EOT>
EOT& select(eoPop<EOT>& pop, params, eoRng& gen = rng); EOT& select(eoPop<EOT>& pop, params, eoRng& gen = rng);
where select is one of: roulette_wheel, deterministic_tournament where select is one of: roulette_wheel, deterministic_tournament
and stochastic_tournament (at the moment). and stochastic_tournament (at the moment).
(c) Maarten Keijzer (mak@dhi.dk) and GeNeura Team, 1999, 2000 (c) Maarten Keijzer (mak@dhi.dk) and GeNeura Team, 1999, 2000
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version. version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: todos@geneura.ugr.es, http://geneura.ugr.es Contact: todos@geneura.ugr.es, http://geneura.ugr.es
*/ */
#ifndef SELECT__H #ifndef SELECT__H
#define SELECT__H #define SELECT__H
#include <stdexcept> #include <stdexcept>
#include "eoRNG.h" #include "eoRNG.h"
#include <eoPop.h> #include <eoPop.h>
/** /**
\defgroup selectors \defgroup selectors
*/ */
template <class EOT> template <class EOT>
bool minimizing_fitness() bool minimizing_fitness()
{ {
EOT eo1; // Assuming people don't do anything fancy in the default constructor! EOT eo1; // Assuming people don't do anything fancy in the default constructor!
EOT eo2; EOT eo2;
/* Dear user, when the two line below do not compile you are most /* Dear user, when the two line below do not compile you are most
likely not working with scalar fitness values. In that case we're sorry likely not working with scalar fitness values. In that case we're sorry
but you cannot use lottery or roulette_wheel selection... but you cannot use lottery or roulette_wheel selection...
*/ */
eo1.fitness( typename EOT::Fitness(0.0) ); // tried to cast it to an EOT::Fitness, but for some reason GNU barfs on this
eo2.fitness( typename EOT::Fitness(1.0) ); #ifdef _MSC_VER
eo1.fitness( EOT::Fitness(0.0) );
return eo2 < eo1; // check whether we have a minimizing fitness eo2.fitness( EOT::Fitness(1.0) );
}; #else
eo1.fitness( typename EOT::Fitness(0.0) ); // tried to cast it to an EOT::Fitness, but for some reason GNU barfs on this
inline double scale_fitness(const std::pair<double, double>& _minmax, double _value) eo2.fitness( typename EOT::Fitness(1.0) );
{ #endif
if (_minmax.first == _minmax.second)
{ return eo2 < eo1; // check whether we have a minimizing fitness
return 0.0; // no differences in fitness, population converged! };
}
// else inline double scale_fitness(const std::pair<double, double>& _minmax, double _value)
{
return (_value - _minmax.first) / (_minmax.second - _minmax.first); if (_minmax.first == _minmax.second)
} {
return 0.0; // no differences in fitness, population converged!
template <class It> }
double sum_fitness(It begin, It end) // else
{
double sum = 0.0; return (_value - _minmax.first) / (_minmax.second - _minmax.first);
}
for (; begin != end; ++begin)
{ template <class It>
double v = static_cast<double>(begin->fitness()); double sum_fitness(It begin, It end)
if (v < 0.0) {
throw std::logic_error("sum_fitness: negative fitness value encountered"); double sum = 0.0;
sum += v;
} for (; begin != end; ++begin)
{
return sum; double v = static_cast<double>(begin->fitness());
} if (v < 0.0)
throw std::logic_error("sum_fitness: negative fitness value encountered");
template <class EOT> sum += v;
double sum_fitness(const eoPop<EOT>& _pop) }
{
return sum_fitness(_pop.begin(), _pop.end()); return sum;
} }
template <class EOT> template <class EOT>
double sum_fitness(const eoPop<EOT>& _pop, std::pair<double, double>& _minmax) double sum_fitness(const eoPop<EOT>& _pop)
{ {
typename eoPop<EOT>::const_iterator it = _pop.begin(); return sum_fitness(_pop.begin(), _pop.end());
}
_minmax.first = it->fitness();
_minmax.second = it++->fitness(); template <class EOT>
double sum_fitness(const eoPop<EOT>& _pop, std::pair<double, double>& _minmax)
for(; it != _pop.end(); ++it) {
{ typename eoPop<EOT>::const_iterator it = _pop.begin();
double v = static_cast<double>(it->fitness());
_minmax.first = it->fitness();
_minmax.first = std::min(_minmax.first, v); _minmax.second = it++->fitness();
_minmax.second = std::max(_minmax.second, v);
for(; it != _pop.end(); ++it)
rawTotal += v; {
} double v = static_cast<double>(it->fitness());
if (minimizing_fitness<EOT>()) _minmax.first = std::min(_minmax.first, v);
{ _minmax.second = std::max(_minmax.second, v);
std::swap(_minmax.first, _minmax.second);
} rawTotal += v;
}
scaledTotal = 0.0;
if (minimizing_fitness<EOT>())
// unfortunately a second loop is neccessary to scale the fitness {
for (it = _pop.begin(); it != _pop.end(); ++it) std::swap(_minmax.first, _minmax.second);
{ }
double v = scale_fitness(static_cast<double>(it->fitness()));
scaledTotal = 0.0;
scaledTotal += v;
} // unfortunately a second loop is neccessary to scale the fitness
} for (it = _pop.begin(); it != _pop.end(); ++it)
{
template <class It> double v = scale_fitness(static_cast<double>(it->fitness()));
It roulette_wheel(It _begin, It _end, double total, eoRng& _gen = rng)
{ scaledTotal += v;
}
float roulette = _gen.uniform(total); }
if (roulette == 0.0) // covers the case where total==0.0 template <class It>
return _begin + _gen.random(_end - _begin); // uniform choice It roulette_wheel(It _begin, It _end, double total, eoRng& _gen = rng)
{
It i = _begin;
float roulette = _gen.uniform(total);
while (roulette > 0.0)
{ if (roulette == 0.0) // covers the case where total==0.0
roulette -= static_cast<double>(*(i++)); return _begin + _gen.random(_end - _begin); // uniform choice
}
It i = _begin;
return --i;
} while (roulette > 0.0)
{
template <class EOT> roulette -= static_cast<double>(*(i++));
const EOT& roulette_wheel(const eoPop<EOT>& _pop, double total, eoRng& _gen = rng) }
{
float roulette = _gen.uniform(total); return --i;
}
if (roulette == 0.0) // covers the case where total==0.0
return _pop[_gen.random(_pop.size())]; // uniform choice template <class EOT>
const EOT& roulette_wheel(const eoPop<EOT>& _pop, double total, eoRng& _gen = rng)
typename eoPop<EOT>::const_iterator i = _pop.begin(); {
float roulette = _gen.uniform(total);
while (roulette > 0.0)
{ if (roulette == 0.0) // covers the case where total==0.0
roulette -= static_cast<double>((i++)->fitness()); return _pop[_gen.random(_pop.size())]; // uniform choice
}
typename eoPop<EOT>::const_iterator i = _pop.begin();
return *--i;
} while (roulette > 0.0)
{
template <class EOT> roulette -= static_cast<double>((i++)->fitness());
EOT& roulette_wheel(eoPop<EOT>& _pop, double total, eoRng& _gen = rng) }
{
float roulette = _gen.uniform(total); return *--i;
}
if (roulette == 0.0) // covers the case where total==0.0
return _pop[_gen.random(_pop.size())]; // uniform choice template <class EOT>
EOT& roulette_wheel(eoPop<EOT>& _pop, double total, eoRng& _gen = rng)
typename eoPop<EOT>::iterator i = _pop.begin(); {
float roulette = _gen.uniform(total);
while (roulette > 0.0)
{ if (roulette == 0.0) // covers the case where total==0.0
roulette -= static_cast<double>((i++)->fitness()); return _pop[_gen.random(_pop.size())]; // uniform choice
}
typename eoPop<EOT>::iterator i = _pop.begin();
return *--i;
} while (roulette > 0.0)
{
template <class It> roulette -= static_cast<double>((i++)->fitness());
It deterministic_tournament(It _begin, It _end, unsigned _t_size, eoRng& _gen = rng) }
{
It best = _begin + _gen.random(_end - _begin); return *--i;
}
for (unsigned i = 0; i < _t_size - 1; ++i)
{ template <class It>
It competitor = _begin + _gen.random(_end - _begin); It deterministic_tournament(It _begin, It _end, unsigned _t_size, eoRng& _gen = rng)
{
if (*best < *competitor) It best = _begin + _gen.random(_end - _begin);
{
best = competitor; for (unsigned i = 0; i < _t_size - 1; ++i)
} {
} It competitor = _begin + _gen.random(_end - _begin);
return best; if (*best < *competitor)
} {
best = competitor;
template <class EOT> }
const EOT& deterministic_tournament(const eoPop<EOT>& _pop, unsigned _t_size, eoRng& _gen = rng) }
{
return *deterministic_tournament(_pop.begin(), _pop.end(), _t_size, _gen); return best;
} }
template <class EOT> template <class EOT>
EOT& deterministic_tournament(eoPop<EOT>& _pop, unsigned _t_size, eoRng& _gen = rng) const EOT& deterministic_tournament(const eoPop<EOT>& _pop, unsigned _t_size, eoRng& _gen = rng)
{ {
return *deterministic_tournament(_pop.begin(), _pop.end(), _t_size, _gen); return *deterministic_tournament(_pop.begin(), _pop.end(), _t_size, _gen);
} }
template <class It> template <class EOT>
It inverse_deterministic_tournament(It _begin, It _end, unsigned _t_size, eoRng& _gen = rng) EOT& deterministic_tournament(eoPop<EOT>& _pop, unsigned _t_size, eoRng& _gen = rng)
{ {
It worst = _begin + _gen.random(_end - _begin); return *deterministic_tournament(_pop.begin(), _pop.end(), _t_size, _gen);
}
for (unsigned i = 1; i < _t_size; ++i)
{ template <class It>
It competitor = _begin + _gen.random(_end - _begin); It inverse_deterministic_tournament(It _begin, It _end, unsigned _t_size, eoRng& _gen = rng)
{
if (competitor == worst) It worst = _begin + _gen.random(_end - _begin);
{
--i; for (unsigned i = 1; i < _t_size; ++i)
continue; // try again {
} It competitor = _begin + _gen.random(_end - _begin);
if (*competitor < *worst) if (competitor == worst)
{ {
worst = competitor; --i;
} continue; // try again
} }
return worst; if (*competitor < *worst)
} {
worst = competitor;
template <class EOT> }
const EOT& inverse_deterministic_tournament(const eoPop<EOT>& _pop, unsigned _t_size, eoRng& _gen = rng) }
{
return *inverse_deterministic_tournament<EOT>(_pop.begin(), _pop.end(), _t_size, _gen); return worst;
} }
template <class EOT> template <class EOT>
EOT& inverse_deterministic_tournament(eoPop<EOT>& _pop, unsigned _t_size, eoRng& _gen = rng) const EOT& inverse_deterministic_tournament(const eoPop<EOT>& _pop, unsigned _t_size, eoRng& _gen = rng)
{ {
return *inverse_deterministic_tournament(_pop.begin(), _pop.end(), _t_size, _gen); return *inverse_deterministic_tournament<EOT>(_pop.begin(), _pop.end(), _t_size, _gen);
} }
template <class It> template <class EOT>
It stochastic_tournament(It _begin, It _end, double _t_rate, eoRng& _gen = rng) EOT& inverse_deterministic_tournament(eoPop<EOT>& _pop, unsigned _t_size, eoRng& _gen = rng)
{ {
It i1 = _begin + _gen.random(_end - _begin); return *inverse_deterministic_tournament(_pop.begin(), _pop.end(), _t_size, _gen);
It i2 = _begin + _gen.random(_end - _begin); }
bool return_better = _gen.flip(_t_rate); template <class It>
It stochastic_tournament(It _begin, It _end, double _t_rate, eoRng& _gen = rng)
if (*i1 < *i2) {
{ It i1 = _begin + _gen.random(_end - _begin);
if (return_better) return i2; It i2 = _begin + _gen.random(_end - _begin);
// else
bool return_better = _gen.flip(_t_rate);
return i1;
} if (*i1 < *i2)
else {
{ if (return_better) return i2;
if (return_better) return i1; // else
// else
} return i1;
// else }
else
return i2; {
} if (return_better) return i1;
// else
template <class EOT> }
const EOT& stochastic_tournament(const eoPop<EOT>& _pop, double _t_rate, eoRng& _gen = rng) // else
{
return *stochastic_tournament(_pop.begin(), _pop.end(), _t_rate, _gen); return i2;
} }
template <class EOT> template <class EOT>
EOT& stochastic_tournament(eoPop<EOT>& _pop, double _t_rate, eoRng& _gen = rng) const EOT& stochastic_tournament(const eoPop<EOT>& _pop, double _t_rate, eoRng& _gen = rng)
{ {
return *stochastic_tournament(_pop.begin(), _pop.end(), _t_rate, _gen); return *stochastic_tournament(_pop.begin(), _pop.end(), _t_rate, _gen);
} }
template <class It> template <class EOT>
It inverse_stochastic_tournament(It _begin, It _end, double _t_rate, eoRng& _gen = rng) EOT& stochastic_tournament(eoPop<EOT>& _pop, double _t_rate, eoRng& _gen = rng)
{ {
It i1 = _begin + _gen.random(_end - _begin); return *stochastic_tournament(_pop.begin(), _pop.end(), _t_rate, _gen);
It i2 = _begin + _gen.random(_end - _begin); }
bool return_worse = _gen.flip(_t_rate); template <class It>
It inverse_stochastic_tournament(It _begin, It _end, double _t_rate, eoRng& _gen = rng)
if (*i1 < *i2) {
{ It i1 = _begin + _gen.random(_end - _begin);
if (return_worse) return i1; It i2 = _begin + _gen.random(_end - _begin);
// else
bool return_worse = _gen.flip(_t_rate);
return i2;
} if (*i1 < *i2)
else {
{ if (return_worse) return i1;
if (return_worse) return i2; // else
// else
} return i2;
// else }
else
return i1; {
} if (return_worse) return i2;
// else
template <class EOT> }
const EOT& inverse_stochastic_tournament(const eoPop<EOT>& _pop, double _t_rate, eoRng& _gen = rng) // else
{
return *inverse_stochastic_tournament(_pop.begin(), _pop.end(), _t_rate, _gen); return i1;
} }
template <class EOT> template <class EOT>
EOT& inverse_stochastic_tournament(eoPop<EOT>& _pop, double _t_rate, eoRng& _gen = rng) const EOT& inverse_stochastic_tournament(const eoPop<EOT>& _pop, double _t_rate, eoRng& _gen = rng)
{ {
return *inverse_stochastic_tournament(_pop.begin(), _pop.end(), _t_rate, _gen); return *inverse_stochastic_tournament(_pop.begin(), _pop.end(), _t_rate, _gen);
} }
template <class EOT>
#endif EOT& inverse_stochastic_tournament(eoPop<EOT>& _pop, double _t_rate, eoRng& _gen = rng)
{
return *inverse_stochastic_tournament(_pop.begin(), _pop.end(), _t_rate, _gen);
}
#endif