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 
00045 template<class EOT> class eoReduce: public eoBF<eoPop<EOT>&, unsigned, void>
00046 {};
00047 
00049 template <class EOT> class eoTruncate : public eoReduce<EOT>
00050 {
00051     void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
00052     {
00053         if (_newgen.size() == _newsize)
00054             return;
00055         if (_newgen.size() < _newsize)
00056           throw std::logic_error("eoTruncate: Cannot truncate to a larger size!\n");
00057 
00058         _newgen.nth_element(_newsize);
00059         _newgen.resize(_newsize);
00060     }
00061 };
00062 
00064 template <class EOT> class eoRandomReduce : public eoReduce<EOT>
00065 {
00066     void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
00067     {
00068         if (_newgen.size() == _newsize)
00069             return;
00070         if (_newgen.size() < _newsize)
00071           throw std::logic_error("eoRandomReduce: Cannot truncate to a larger size!\n");
00072 
00073         // shuffle the population, then trucate
00074         _newgen.shuffle();
00075         _newgen.resize(_newsize);
00076     }
00077 };
00078 
00083 template <class EOT> class eoEPReduce : public eoReduce<EOT>
00084 {
00085 public:
00086 typedef typename EOT::Fitness Fitness; 
00087 
00088   eoEPReduce(unsigned _t_size  ):
00089     t_size(_t_size)
00090   {
00091     if (t_size < 2)
00092       { 
00093         std::cout << "Warning: EP tournament size should be >= 2. Adjusted" << std::endl;
00094         t_size = 2;
00095       }
00096   }
00097 
00099   // compares the scores
00100   // uses the fitness if scores are equals ????
00101   typedef std::pair<float, typename eoPop<EOT>::iterator>  EPpair;
00102   struct Cmp {
00103     bool operator()(const EPpair a, const EPpair b) const
00104     { 
00105       if (b.first == a.first)
00106         return  (*b.second < *a.second);
00107       return b.first < a.first; 
00108     }
00109   };
00110   
00111   
00112   void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
00113   {
00114     unsigned int presentSize = _newgen.size();
00115     
00116     if (presentSize == _newsize)
00117             return;
00118         if (presentSize < _newsize)
00119           throw std::logic_error("eoTruncate: Cannot truncate to a larger size!\n");
00120         std::vector<EPpair> scores(presentSize);
00121         for (unsigned i=0; i<presentSize; i++)
00122           {
00123             scores[i].second = _newgen.begin()+i;
00124             Fitness fit = _newgen[i].fitness();
00125             for (unsigned itourn = 0; itourn < t_size; ++itourn)
00126               {
00127                 const EOT & competitor = _newgen[rng.random(presentSize)];
00128                 if (fit > competitor.fitness())
00129                   scores[i].first += 1;
00130                 else if (fit == competitor.fitness())
00131                   scores[i].first += 0.5;
00132               }
00133           }
00134 
00135         // now we have the scores
00136         typename std::vector<EPpair>::iterator it = scores.begin() + _newsize;
00137         std::nth_element(scores.begin(), it, scores.end(), Cmp());
00138         // sort(scores.begin(), scores.end(), Cmp());
00139         unsigned j;
00140 //      std::cout << "Les scores apres tri\n";
00141 //      for (j=0; j<scores.size(); j++)
00142 //        {
00143 //          std::cout << scores[j].first << " " << *scores[j].second << std::endl;
00144 //        }
00145         eoPop<EOT> tmPop;
00146         for (j=0; j<_newsize; j++)
00147           {
00148             tmPop.push_back(*scores[j].second);
00149           }
00150         _newgen.swap(tmPop);
00151         // erase does not work, but I'm sure there is a way in STL to mark
00152         // and later delete all inside a std::vector ??????
00153         // this would avoid all copies here
00154 
00155 //      it = scores.begin() + _newsize;
00156 //      while (it < scores.end())
00157 //        _newgen.erase(it->second);
00158     }
00159 private:
00160   unsigned t_size;
00161 };
00162 
00166 template <class EOT> 
00167 class eoLinearTruncate : public eoReduce<EOT>
00168 {
00169   void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
00170   {
00171     unsigned oldSize = _newgen.size();
00172     if (oldSize == _newsize)
00173       return;
00174     if (oldSize < _newsize)
00175       throw std::logic_error("eoLinearTruncate: Cannot truncate to a larger size!\n");
00176     for (unsigned i=0; i<oldSize - _newsize; i++)
00177       {
00178         typename eoPop<EOT>::iterator it = _newgen.it_worse_element();
00179         _newgen.erase(it);          
00180       }
00181   }
00182 };
00183 
00187 template <class EOT> 
00188 class eoDetTournamentTruncate : public eoReduce<EOT>
00189 {
00190 public:
00191   eoDetTournamentTruncate(unsigned _t_size):
00192     t_size(_t_size)
00193   {
00194     if (t_size < 2)
00195       { 
00196         std::cout << "Warning, Size for eoDetTournamentTruncate adjusted to 2\n";
00197         t_size = 2;
00198       }
00199   }
00200 
00201   void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
00202   {
00203     unsigned oldSize = _newgen.size();
00204     if (_newsize == 0)
00205       {
00206         _newgen.resize(0);
00207         return;
00208       }
00209     if (oldSize == _newsize)
00210       return;
00211     if (oldSize < _newsize)
00212       throw std::logic_error("eoDetTournamentTruncate: Cannot truncate to a larger size!\n");
00213 
00214     // Now OK to erase some losers
00215     for (unsigned i=0; i<oldSize - _newsize; i++)
00216       {
00217         //OLDCODE EOT & eo = inverse_deterministic_tournament<EOT>(_newgen, t_size);
00218         //OLDCODE _newgen.erase(&eo);
00219         
00220         // Jeroen Eggermont stdc++v3  patch
00221         // in the new code from stdc++v3 an iterator from a container<T> is no longer an pointer to T
00222         // Because eo already contained a fuction using eoPop<EOT>::iterator's we will use the following
00223         
00224         _newgen.erase( inverse_deterministic_tournament(_newgen.begin(), _newgen.end(), t_size) );
00225         
00226       }
00227   }
00228 private:
00229   unsigned t_size;
00230 };
00231 
00235 template <class EOT> 
00236 class eoStochTournamentTruncate : public eoReduce<EOT>
00237 {
00238 public:
00239   eoStochTournamentTruncate(double _t_rate):
00240     t_rate(_t_rate)
00241   {
00242     if (t_rate <= 0.5)
00243       { 
00244         std::cout << "Warning, Rate for eoStochTournamentTruncate adjusted to 0.51\n";
00245         t_rate = 0.51;
00246       }
00247     if (t_rate > 1)
00248       {
00249         std::cout << "Warning, Rate for eoStochTournamentTruncate adjusted to 1\n";
00250         t_rate = 1;
00251       }
00252   }
00253 
00254   void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
00255   {
00256     unsigned oldSize = _newgen.size();
00257     if (_newsize == 0)
00258       {
00259         _newgen.resize(0);
00260         return;
00261       }
00262     if (oldSize == _newsize)
00263       return;
00264     if (oldSize < _newsize)
00265       throw std::logic_error("eoStochTournamentTruncate: Cannot truncate to a larger size!\n");
00266     // Now OK to erase some losers
00267     for (unsigned i=0; i<oldSize - _newsize; i++)
00268       {
00269         //OLDCODE EOT & eo = inverse_stochastic_tournament<EOT>(_newgen, t_rate);
00270         //OLDCODE _newgen.erase(&eo);
00271         
00272         // Jeroen Eggermont stdc++v3  patch
00273         // in the new code from stdc++v3 an iterator from a container<T> is no longer an pointer to T
00274         // Because eo already contained a fuction using eoPop<EOT>::iterator's we will use the following
00275         
00276         _newgen.erase( inverse_stochastic_tournament(_newgen.begin(), _newgen.end(), t_rate) );
00277         
00278         
00279       }
00280   }
00281 
00282 private:
00283   double t_rate;
00284 };
00285 
00286 //-----------------------------------------------------------------------------
00287 
00288 #endif

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