selectors.h

00001 /* -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
00002 
00003   -----------------------------------------------------------------------------
00004   selectors.h
00005     A bunch of useful selector functions. They generally have three forms:
00006 
00007     template <class It>
00008     It select(It begin, It end, params, eoRng& gen = rng);
00009 
00010     template <class EOT>
00011     const EOT& select(const eoPop<EOT>& pop, params, eoRng& gen = rng);
00012 
00013     template <class EOT>
00014     EOT& select(eoPop<EOT>& pop, params, eoRng& gen = rng);
00015 
00016     where select is one of: roulette_wheel, deterministic_tournament
00017     and stochastic_tournament (at the moment).
00018 
00019  (c) Maarten Keijzer (mak@dhi.dk) and GeNeura Team, 1999, 2000
00020 
00021     This library is free software; you can redistribute it and/or
00022     modify it under the terms of the GNU Lesser General Public
00023     License as published by the Free Software Foundation; either
00024     version 2 of the License, or (at your option) any later version.
00025 
00026     This library is distributed in the hope that it will be useful,
00027     but WITHOUT ANY WARRANTY; without even the implied warranty of
00028     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00029     Lesser General Public License for more details.
00030 
00031     You should have received a copy of the GNU Lesser General Public
00032     License along with this library; if not, write to the Free Software
00033     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00034 
00035     Contact: todos@geneura.ugr.es, http://geneura.ugr.es
00036  */
00037 
00038 #ifndef SELECT__H
00039 #define SELECT__H
00040 
00041 #include <stdexcept>
00042 
00043 #include "eoRNG.h"
00044 #include <eoPop.h>
00049 template <class EOT>
00050 bool minimizing_fitness()
00051 {
00052     EOT eo1; // Assuming people don't do anything fancy in the default constructor!
00053     EOT eo2;
00054 
00055     /* Dear user, when the two line below do not compile you are most
00056        likely not working with scalar fitness values. In that case we're sorry
00057        but you cannot use lottery or roulette_wheel selection...
00058     */
00059 
00060 #ifdef _MSC_VER
00061     eo1.fitness( EOT::Fitness(0.0) );
00062     eo2.fitness( EOT::Fitness(1.0) );
00063 #else
00064     eo1.fitness( typename EOT::Fitness(0.0) ); // tried to cast it to an EOT::Fitness, but for some reason GNU barfs on this
00065     eo2.fitness( typename EOT::Fitness(1.0) );
00066 #endif
00067 
00068     return eo2 < eo1; // check whether we have a minimizing fitness
00069 }
00070 
00071 inline double scale_fitness(const std::pair<double, double>& _minmax, double _value)
00072 {
00073     if (_minmax.first == _minmax.second)
00074     {
00075         return 0.0; // no differences in fitness, population converged!
00076     }
00077     // else
00078 
00079     return (_value - _minmax.first) / (_minmax.second - _minmax.first);
00080 }
00081 
00082 template <class It>
00083 double sum_fitness(It begin, It end)
00084 {
00085     double sum = 0.0;
00086 
00087     for (; begin != end; ++begin)
00088     {
00089         double v = static_cast<double>(begin->fitness());
00090         if (v < 0.0)
00091             throw std::logic_error("sum_fitness: negative fitness value encountered");
00092         sum += v;
00093     }
00094 
00095     return sum;
00096 }
00097 
00098 template <class EOT>
00099 double sum_fitness(const eoPop<EOT>& _pop)
00100 {
00101     return sum_fitness(_pop.begin(), _pop.end());
00102 }
00103 
00104 template <class EOT>
00105 double sum_fitness(const eoPop<EOT>& _pop, std::pair<double, double>& _minmax)
00106 {
00107     double rawTotal, scaledTotal;
00108 
00109     typename eoPop<EOT>::const_iterator it = _pop.begin();
00110 
00111     _minmax.first = it->fitness();
00112     _minmax.second = it++->fitness();
00113 
00114     for(; it != _pop.end(); ++it)
00115     {
00116         double v = static_cast<double>(it->fitness());
00117 
00118         _minmax.first = std::min(_minmax.first, v);
00119         _minmax.second = std::max(_minmax.second, v);
00120 
00121         rawTotal += v;
00122     }
00123 
00124     if (minimizing_fitness<EOT>())
00125     {
00126         std::swap(_minmax.first, _minmax.second);
00127     }
00128 
00129     scaledTotal = 0.0;
00130 
00131     // unfortunately a second loop is neccessary to scale the fitness
00132     for (it = _pop.begin(); it != _pop.end(); ++it)
00133     {
00134         double v = scale_fitness(_minmax, static_cast<double>(it->fitness()));
00135 
00136         scaledTotal += v;
00137     }
00138 
00139     return scaledTotal;
00140 }
00141 
00142 template <class It>
00143 It roulette_wheel(It _begin, It _end, double total, eoRng& _gen = rng)
00144 {
00145 
00146     float roulette = _gen.uniform(total);
00147 
00148     if (roulette == 0.0)           // covers the case where total==0.0
00149       return _begin + _gen.random(_end - _begin); // uniform choice
00150 
00151     It i = _begin;
00152 
00153     while (roulette > 0.0)
00154     {
00155             roulette -= static_cast<double>(*(i++));
00156     }
00157 
00158     return --i;
00159 }
00160 
00161 template <class EOT>
00162 const EOT& roulette_wheel(const eoPop<EOT>& _pop, double total, eoRng& _gen = rng)
00163 {
00164     float roulette = _gen.uniform(total);
00165 
00166     if (roulette == 0.0)           // covers the case where total==0.0
00167       return _pop[_gen.random(_pop.size())]; // uniform choice
00168 
00169     typename eoPop<EOT>::const_iterator i = _pop.begin();
00170 
00171     while (roulette > 0.0)
00172     {
00173             roulette -= static_cast<double>((i++)->fitness());
00174     }
00175 
00176     return *--i;
00177 }
00178 
00179 template <class EOT>
00180 EOT& roulette_wheel(eoPop<EOT>& _pop, double total, eoRng& _gen = rng)
00181 {
00182     float roulette = _gen.uniform(total);
00183 
00184     if (roulette == 0.0)           // covers the case where total==0.0
00185       return _pop[_gen.random(_pop.size())]; // uniform choice
00186 
00187     typename eoPop<EOT>::iterator i = _pop.begin();
00188 
00189     while (roulette > 0.0)
00190     {
00191             roulette -= static_cast<double>((i++)->fitness());
00192     }
00193 
00194     return *--i;
00195 }
00196 
00197 template <class It>
00198 It deterministic_tournament(It _begin, It _end, unsigned _t_size, eoRng& _gen = rng)
00199 {
00200     It best = _begin + _gen.random(_end - _begin);
00201 
00202     for (unsigned i = 0; i < _t_size - 1; ++i)
00203     {
00204         It competitor = _begin + _gen.random(_end - _begin);
00205 
00206         if (*best < *competitor)
00207         {
00208             best = competitor;
00209         }
00210     }
00211 
00212     return best;
00213 }
00214 
00215 template <class EOT>
00216 const EOT& deterministic_tournament(const eoPop<EOT>& _pop, unsigned _t_size, eoRng& _gen = rng)
00217 {
00218     return *deterministic_tournament(_pop.begin(), _pop.end(), _t_size, _gen);
00219 }
00220 
00221 template <class EOT>
00222 EOT& deterministic_tournament(eoPop<EOT>& _pop, unsigned _t_size, eoRng& _gen = rng)
00223 {
00224     return *deterministic_tournament(_pop.begin(), _pop.end(), _t_size, _gen);
00225 }
00226 
00227 template <class It>
00228 It inverse_deterministic_tournament(It _begin, It _end, unsigned _t_size, eoRng& _gen = rng)
00229 {
00230     It worst = _begin + _gen.random(_end - _begin);
00231 
00232     for (unsigned i = 1; i < _t_size; ++i)
00233     {
00234         It competitor = _begin + _gen.random(_end - _begin);
00235 
00236         if (competitor == worst)
00237         {
00238             --i;
00239             continue; // try again
00240         }
00241 
00242         if (*competitor < *worst)
00243         {
00244             worst = competitor;
00245         }
00246     }
00247 
00248     return worst;
00249 }
00250 
00251 template <class EOT>
00252 const EOT& inverse_deterministic_tournament(const eoPop<EOT>& _pop, unsigned _t_size, eoRng& _gen = rng)
00253 {
00254     return *inverse_deterministic_tournament<EOT>(_pop.begin(), _pop.end(), _t_size, _gen);
00255 }
00256 
00257 template <class EOT>
00258 EOT& inverse_deterministic_tournament(eoPop<EOT>& _pop, unsigned _t_size, eoRng& _gen = rng)
00259 {
00260     return *inverse_deterministic_tournament(_pop.begin(), _pop.end(), _t_size, _gen);
00261 }
00262 
00263 template <class It>
00264 It stochastic_tournament(It _begin, It _end, double _t_rate, eoRng& _gen = rng)
00265 {
00266   It i1 = _begin + _gen.random(_end - _begin);
00267   It i2 = _begin + _gen.random(_end - _begin);
00268 
00269   bool return_better = _gen.flip(_t_rate);
00270 
00271   if (*i1 < *i2)
00272   {
00273       if (return_better) return i2;
00274       // else
00275 
00276       return i1;
00277    }
00278     else
00279     {
00280       if (return_better) return i1;
00281       // else
00282     }
00283     // else
00284 
00285     return i2;
00286 }
00287 
00288 template <class EOT>
00289 const EOT& stochastic_tournament(const eoPop<EOT>& _pop, double _t_rate, eoRng& _gen = rng)
00290 {
00291     return *stochastic_tournament(_pop.begin(), _pop.end(), _t_rate, _gen);
00292 }
00293 
00294 template <class EOT>
00295 EOT& stochastic_tournament(eoPop<EOT>& _pop, double _t_rate, eoRng& _gen = rng)
00296 {
00297     return *stochastic_tournament(_pop.begin(), _pop.end(), _t_rate, _gen);
00298 }
00299 
00300 template <class It>
00301 It inverse_stochastic_tournament(It _begin, It _end, double _t_rate, eoRng& _gen = rng)
00302 {
00303   It i1 = _begin + _gen.random(_end - _begin);
00304   It i2 = _begin + _gen.random(_end - _begin);
00305 
00306   bool return_worse = _gen.flip(_t_rate);
00307 
00308   if (*i1 < *i2)
00309   {
00310       if (return_worse) return i1;
00311       // else
00312 
00313       return i2;
00314    }
00315     else
00316     {
00317       if (return_worse) return i2;
00318       // else
00319     }
00320     // else
00321 
00322     return i1;
00323 }
00324 
00325 template <class EOT>
00326 const EOT& inverse_stochastic_tournament(const eoPop<EOT>& _pop, double _t_rate, eoRng& _gen = rng)
00327 {
00328     return *inverse_stochastic_tournament(_pop.begin(), _pop.end(), _t_rate, _gen);
00329 }
00330 
00331 template <class EOT>
00332 EOT& inverse_stochastic_tournament(eoPop<EOT>& _pop, double _t_rate, eoRng& _gen = rng)
00333 {
00334     return *inverse_stochastic_tournament(_pop.begin(), _pop.end(), _t_rate, _gen);
00335 }
00336 
00337 
00338 #endif

Generated on Thu Oct 19 05:06:42 2006 for EO by  doxygen 1.3.9.1