EvolvingObjects
eoReduce.h
00001 // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
00002 
00003 //-----------------------------------------------------------------------------
00004 // eoReduce.h
00005 //   Base class for population-merging classes
00006 // (c) GeNeura Team, 1998
00007 /*
00008    This library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Lesser General Public
00010    License as published by the Free Software Foundation; either
00011    version 2 of the License, or (at your option) any later version.
00012 
00013    This library is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016    Lesser General Public License for more details.
00017 
00018    You should have received a copy of the GNU Lesser General Public
00019    License along with this library; if not, write to the Free Software
00020    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021 
00022    Contact: todos@geneura.ugr.es, http://geneura.ugr.es
00023  */
00024 //-----------------------------------------------------------------------------
00025 
00026 #ifndef eoReduce_h
00027 #define eoReduce_h
00028 
00029 //-----------------------------------------------------------------------------
00030 
00031 #include <iostream>
00032 
00033 // EO includes
00034 #include <eoPop.h>     // eoPop
00035 #include <eoFunctor.h>  // eoReduce
00036 #include <utils/selectors.h>
00037 #include <utils/eoLogger.h>
00038 
00047 template<class EOT> class eoReduce: public eoBF<eoPop<EOT>&, unsigned, void>
00048 {};
00049 
00053 template <class EOT> class eoTruncate : public eoReduce<EOT>
00054 {
00055     void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
00056     {
00057         if (_newgen.size() == _newsize)
00058             return;
00059         if (_newgen.size() < _newsize)
00060           throw std::logic_error("eoTruncate: Cannot truncate to a larger size!\n");
00061 
00062         _newgen.sort();
00063         _newgen.resize(_newsize);
00064     }
00065 };
00066 
00070 template <class EOT> class eoRandomReduce : public eoReduce<EOT>
00071 {
00072     void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
00073     {
00074         if (_newgen.size() == _newsize)
00075             return;
00076         if (_newgen.size() < _newsize)
00077           throw std::logic_error("eoRandomReduce: Cannot truncate to a larger size!\n");
00078 
00079         // shuffle the population, then trucate
00080         _newgen.shuffle();
00081         _newgen.resize(_newsize);
00082     }
00083 };
00084 
00090 template <class EOT> class eoEPReduce : public eoReduce<EOT>
00091 {
00092 public:
00093     typedef typename EOT::Fitness Fitness;
00094 
00095     eoEPReduce(unsigned _t_size  ):
00096         t_size(_t_size)
00097     {
00098         if (t_size < 2)
00099             {
00100                 eo::log << eo::warnings << "Warning: EP tournament size should be >= 2. Adjusted" << std::endl;
00101                 t_size = 2;
00102             }
00103     }
00104 
00106     // compares the scores
00107     // uses the fitness if scores are equals ????
00108     typedef std::pair<float, typename eoPop<EOT>::iterator>  EPpair;
00109     struct Cmp {
00110         bool operator()(const EPpair a, const EPpair b) const
00111         {
00112             if (b.first == a.first)
00113                 return  (*b.second < *a.second);
00114             return b.first < a.first;
00115         }
00116     };
00117 
00118 
00119     void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
00120     {
00121         unsigned int presentSize = _newgen.size();
00122 
00123         if (presentSize == _newsize)
00124             return;
00125         if (presentSize < _newsize)
00126             throw std::logic_error("eoTruncate: Cannot truncate to a larger size!\n");
00127         std::vector<EPpair> scores(presentSize);
00128         for (unsigned i=0; i<presentSize; i++)
00129             {
00130                 scores[i].second = _newgen.begin()+i;
00131                 Fitness fit = _newgen[i].fitness();
00132                 for (unsigned itourn = 0; itourn < t_size; ++itourn)
00133                     {
00134                         const EOT & competitor = _newgen[rng.random(presentSize)];
00135                         if (fit > competitor.fitness())
00136                             scores[i].first += 1;
00137                         else if (fit == competitor.fitness())
00138                             scores[i].first += 0.5;
00139                     }
00140             }
00141 
00142         // now we have the scores
00143         typename std::vector<EPpair>::iterator it = scores.begin() + _newsize;
00144         std::nth_element(scores.begin(), it, scores.end(), Cmp());
00145         // sort(scores.begin(), scores.end(), Cmp());
00146         unsigned j;
00147         //      std::cout << "Les scores apres tri\n";
00148         //      for (j=0; j<scores.size(); j++)
00149         //        {
00150         //          std::cout << scores[j].first << " " << *scores[j].second << std::endl;
00151         //        }
00152 
00153         tmPop.reserve(presentSize);
00154         tmPop.clear();
00155 
00156         for (j=0; j<_newsize; j++)
00157             {
00158                 tmPop.push_back(*scores[j].second);
00159             }
00160 
00161         _newgen.swap(tmPop);
00162 
00163         // erase does not work, but I'm sure there is a way in STL to mark
00164         // and later delete all inside a std::vector ??????
00165         // this would avoid all copies here
00166 
00167         //      it = scores.begin() + _newsize;
00168         //      while (it < scores.end())
00169         //        _newgen.erase(it->second);
00170     }
00171 private:
00172     unsigned t_size;
00173     eoPop<EOT> tmPop;
00174 };
00175 
00180 template <class EOT>
00181 class eoLinearTruncate : public eoReduce<EOT>
00182 {
00183   void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
00184   {
00185     unsigned oldSize = _newgen.size();
00186     if (oldSize == _newsize)
00187       return;
00188     if (oldSize < _newsize)
00189       throw std::logic_error("eoLinearTruncate: Cannot truncate to a larger size!\n");
00190     for (unsigned i=0; i<oldSize - _newsize; i++)
00191       {
00192         typename eoPop<EOT>::iterator it = _newgen.it_worse_element();
00193         _newgen.erase(it);
00194       }
00195   }
00196 };
00197 
00202 template <class EOT>
00203 class eoDetTournamentTruncate : public eoReduce<EOT>
00204 {
00205 public:
00206   eoDetTournamentTruncate(unsigned _t_size):
00207     t_size(_t_size)
00208   {
00209     if (t_size < 2)
00210       {
00211           eo::log << eo::warnings << "Warning, Size for eoDetTournamentTruncate adjusted to 2" << std::endl;
00212         t_size = 2;
00213       }
00214   }
00215 
00216   void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
00217   {
00218     unsigned oldSize = _newgen.size();
00219     if (_newsize == 0)
00220       {
00221         _newgen.resize(0);
00222         return;
00223       }
00224     if (oldSize == _newsize)
00225       return;
00226     if (oldSize < _newsize)
00227       throw std::logic_error("eoDetTournamentTruncate: Cannot truncate to a larger size!\n");
00228 
00229 
00230     // Now OK to erase some losers
00231     std::cout << "oldSize - _newsize: " << oldSize - _newsize << std::endl;
00232     for (unsigned i=0; i<oldSize - _newsize; i++)
00233       {
00234         //OLDCODE EOT & eo = inverse_deterministic_tournament<EOT>(_newgen, t_size);
00235         //OLDCODE _newgen.erase(&eo);
00236 
00237         // Jeroen Eggermont stdc++v3  patch
00238         // in the new code from stdc++v3 an iterator from a container<T> is no longer an pointer to T
00239         // Because eo already contained a fuction using eoPop<EOT>::iterator's we will use the following
00240 
00241         _newgen.erase( inverse_deterministic_tournament(_newgen.begin(), _newgen.end(), t_size) );
00242 
00243       }
00244   }
00245 private:
00246   unsigned t_size;
00247 };
00248 
00253 template <class EOT>
00254 class eoStochTournamentTruncate : public eoReduce<EOT>
00255 {
00256 public:
00257   eoStochTournamentTruncate(double _t_rate):
00258     t_rate(_t_rate)
00259   {
00260     if (t_rate <= 0.5)
00261       {
00262           eo::log << eo::warnings << "Warning, Rate for eoStochTournamentTruncate adjusted to 0.51" << std::endl;
00263         t_rate = 0.51;
00264       }
00265     if (t_rate > 1)
00266       {
00267           eo::log << eo::warnings << "Warning, Rate for eoStochTournamentTruncate adjusted to 1" << std::endl;
00268         t_rate = 1;
00269       }
00270   }
00271 
00272   void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
00273   {
00274     unsigned oldSize = _newgen.size();
00275     if (_newsize == 0)
00276       {
00277         _newgen.resize(0);
00278         return;
00279       }
00280     if (oldSize == _newsize)
00281       return;
00282     if (oldSize < _newsize)
00283       throw std::logic_error("eoStochTournamentTruncate: Cannot truncate to a larger size!\n");
00284     // Now OK to erase some losers
00285     for (unsigned i=0; i<oldSize - _newsize; i++)
00286       {
00287         //OLDCODE EOT & eo = inverse_stochastic_tournament<EOT>(_newgen, t_rate);
00288         //OLDCODE _newgen.erase(&eo);
00289 
00290         // Jeroen Eggermont stdc++v3  patch
00291         // in the new code from stdc++v3 an iterator from a container<T> is no longer an pointer to T
00292         // Because eo already contained a fuction using eoPop<EOT>::iterator's we will use the following
00293 
00294         _newgen.erase( inverse_stochastic_tournament(_newgen.begin(), _newgen.end(), t_rate) );
00295 
00296 
00297       }
00298   }
00299 
00300 private:
00301   double t_rate;
00302 };
00303 
00304 //-----------------------------------------------------------------------------
00305 
00306 #endif
 All Classes Namespaces Files Functions Variables Typedefs Friends