# eoReduceSplit.h

    00001 // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
    00002
    00003 //-----------------------------------------------------------------------------
    00004 // eoReduceSplit.h
    00005 //   Base class for population-reducing classes - retaining the poor losers
    00006 // (c) GeNeura Team, 1998, Marc Schoenauer, 2002
    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: Marc.Schoenauer@inria.fr
    00023  */
    00024 //-----------------------------------------------------------------------------
    00025
    00026 #ifndef eoReduceSplit_h
    00027 #define eoReduceSplit_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
    00042 template<class EOT> class eoReduceSplit: public eoBF<eoPop<EOT>&, eoPop<EOT> &, void >
    00043 {};
    00044
    00046 template <class EOT>
    00047 class eoTruncateSplit : public eoReduceSplit<EOT>
    00048 {
    00049 public:
    00053   eoTruncateSplit(eoHowMany _howMany, bool _returnEliminated = false):
    00054     howMany(_howMany), returnEliminated(_returnEliminated) {}
    00055
    00057   void operator()(eoPop<EOT>& _newgen, eoPop<EOT> & _eliminated)
    00058   {
    00059     unsigned popSize = _newgen.size();
    00060     unsigned eliminated = howMany(popSize);
    00061     if (!eliminated)   // nothing to do
    00062       return ;
    00063     unsigned newsize = popSize - eliminated;
    00064     if (newsize < 0)
    00065       throw std::logic_error("eoTruncateSplit: Cannot truncate to a larger size!\n");
    00066
    00067     _newgen.nth_element(newsize);
    00068
    00069     // save poor losers if necessary
    00070     if (returnEliminated)
    00071       for (unsigned i=0; i<eliminated; i++)
    00072         _eliminated.push_back(_newgen[newsize+i]);
    00073     // truncate
    00074     _newgen.resize(newsize);
    00075     return ;
    00076   }
    00077
    00078 private:
    00079   eoHowMany howMany;
    00080   bool returnEliminated;
    00081 };
    00082
    00086 template <class EOT>
    00087 class eoLinearTruncateSplit : public eoReduceSplit<EOT>
    00088 {
    00089 public:
    00093   eoLinearTruncateSplit(eoHowMany _howMany, bool _returnEliminated = false):
    00094     howMany(_howMany), returnEliminated(_returnEliminated) {}
    00095
    00097   void operator()(eoPop<EOT>& _newgen, eoPop<EOT> & _eliminated)
    00098   {
    00099     unsigned popSize = _newgen.size();
    00100     unsigned eliminated = howMany(popSize);
    00101     if (!eliminated)   // nothing to do
    00102       return ;
    00103     unsigned newsize = popSize - eliminated;
    00104     if (newsize < 0)
    00105       throw std::logic_error("eoLinearTruncateSplit: Cannot truncate to a larger size!\n");
    00106
    00107     _eliminated.reserve(_eliminated.size()+eliminated); //in case not empty?
    00108     for (unsigned i=0; i<eliminated; i++)
    00109       {
    00110         typename eoPop<EOT>::iterator it = _newgen.it_worse_element();
    00111         if (returnEliminated)
    00112           _eliminated.push_back(*it);
    00113         _newgen.erase(it);
    00114       }
    00115   }
    00116
    00117 private:
    00118   eoHowMany howMany;
    00119   bool returnEliminated;
    00120 };
    00121
    00123 template <class EOT>
    00124 class eoRandomSplit : public eoReduceSplit<EOT>
    00125 {
    00126 public:
    00130   eoRandomSplit(eoHowMany _howMany, bool _returnEliminated = false):
    00131     howMany(_howMany), returnEliminated(_returnEliminated) {}
    00132
    00134   void operator()(eoPop<EOT>& _newgen, eoPop<EOT> & _eliminated)
    00135   {
    00136     unsigned popSize = _newgen.size();
    00137     unsigned eliminated = howMany(popSize);
    00138     if (!eliminated)   // nothing to do
    00139       return ;
    00140     unsigned newsize = popSize - eliminated;
    00141     if (newsize < 0)
    00142       throw std::logic_error("eoRandomSplit: Cannot truncate to a larger size!\n");
    00143
    00144     _newgen.shuffle();
    00145
    00146     // save poor losers if necessary
    00147     if (returnEliminated)
    00148       for (unsigned i=0; i<eliminated; i++)
    00149         _eliminated.push_back(_newgen[newsize+i]);
    00150     // truncate
    00151     _newgen.resize(newsize);
    00152     return ;
    00153   }
    00154
    00155 private:
    00156   eoHowMany howMany;
    00157   bool returnEliminated;
    00158 };
    00159
    00160
    00162 template <class EOT>
    00163 class eoLinearRandomSplit : public eoReduceSplit<EOT>
    00164 {
    00165 public:
    00169   eoLinearRandomSplit(eoHowMany _howMany, bool _returnEliminated = false):
    00170     howMany(_howMany), returnEliminated(_returnEliminated) {}
    00171
    00173   void operator()(eoPop<EOT>& _newgen, eoPop<EOT> & _eliminated)
    00174   {
    00175     unsigned popSize = _newgen.size();
    00176     unsigned eliminated = howMany(popSize);
    00177     if (!eliminated)   // nothing to do
    00178       return ;
    00179     unsigned newsize = popSize - eliminated;
    00180     if (newsize < 0)
    00181       throw std::logic_error("eoLinearRandomSplit: Cannot truncate to a larger size!\n");
    00182
    00183     _eliminated.reserve(_eliminated.size()+eliminated); //in case not empty?
    00184     for (unsigned i=0; i<eliminated; i++)
    00185       {
    00186         unsigned loser=random(_newgen.size());
    00187         typename eoPop<EOT>::iterator it = _newgen.begin()+loser;
    00188         if (returnEliminated)
    00189           _eliminated.push_back(*it);
    00190         _newgen.erase(it);
    00191       }
    00192     return ;
    00193   }
    00194
    00195 private:
    00196   eoHowMany howMany;
    00197   bool returnEliminated;
    00198 };
    00199
    00200
    00204 template <class EOT>
    00205 class eoDetTournamentTruncateSplit : public eoReduceSplit<EOT>
    00206 {
    00207 public:
    00211   eoDetTournamentTruncateSplit(unsigned _t_size, eoHowMany _howMany,
    00212                       bool _returnEliminated = false):
    00213     t_size(_t_size), howMany(_howMany),
    00214     returnEliminated(_returnEliminated)
    00215   {
    00216     if (t_size < 2)
    00217       {
    00218         std::cout << "Warning, Size for eoDetTournamentTruncateSplit adjusted to 2\n";
    00219         t_size = 2;
    00220       }
    00221   }
    00222
    00224   void operator()(eoPop<EOT>& _newgen, eoPop<EOT> & _eliminated)
    00225   // BUG???  void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
    00226   {
    00227     unsigned popSize = _newgen.size();
    00228     unsigned eliminated = howMany(popSize);
    00229     if (!eliminated)   // nothing to do
    00230       return ;
    00231     unsigned newsize = popSize - eliminated;
    00232     if (newsize < 0)
    00233       throw std::logic_error("eoDetTournamentTruncateSplit: Cannot truncate to a larger size!\n");
    00234
    00235
    00236     _eliminated.reserve(_eliminated.size()+eliminated); //in case not empty?
    00237     for (unsigned i=0; i<eliminated; i++)
    00238       {
    00239         typename eoPop<EOT>::iterator it = inverse_deterministic_tournament(_newgen.begin(), _newgen.end(), t_size);
    00240         if (returnEliminated)
    00241           _eliminated.push_back(*it);
    00242         _newgen.erase(it);
    00243       }
    00244   }
    00245
    00246 private:
    00247   unsigned t_size;
    00248   eoHowMany howMany;
    00249   bool returnEliminated;
    00250 };
    00251
    00255 template <class EOT>
    00256 class eoStochTournamentTruncateSplit : public eoReduce<EOT>
    00257 {
    00258 public:
    00262   eoStochTournamentTruncateSplit(double _t_rate, eoHowMany _howMany,
    00263                       bool _returnEliminated = false):
    00264     t_rate(_t_rate), howMany(_howMany),
    00265     returnEliminated(_returnEliminated)
    00266   {
    00267     if (t_rate <= 0.5)
    00268       {
    00269         std::cout << "Warning, Rate for eoStochTournamentTruncateSplit adjusted to 0.51\n";
    00270         t_rate = 0.51;
    00271       }
    00272     if (t_rate > 1)
    00273       {
    00274         std::cout << "Warning, Rate for eoStochTournamentTruncateSplit adjusted to 1\n";
    00275         t_rate = 1;
    00276       }
    00277   }
    00278
    00280   void operator()(eoPop<EOT>& _newgen, eoPop<EOT> & _eliminated)
    00281   //BUG???  void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
    00282   {
    00283     /* old version
    00284     if (!_eliminated.size())       // nothing to do
    00285       return;
    00286     unsigned oldSize = _newgen.size();
    00287     unsigned newSize = oldSize - _eliminated.size();
    00288     unsigned eliminated = howMany(popSize);
    00289     if (newSize < 0)
    00290       throw std::logic_error("eoStochTournamentTruncateSplit: Cannot truncate to a larger size!\n");
    00291
    00292 end of old version    */
    00293
    00294     unsigned popSize = _newgen.size();
    00295     unsigned eliminated = howMany(popSize);
    00296     if (!eliminated)   // nothing to do
    00297       return ;
    00298     unsigned newsize = popSize - eliminated;
    00299     if (newsize < 0)
    00300       throw std::logic_error("eoDetTournamentTruncateSplit: Cannot truncate to a larger size!\n");
    00301
    00302
    00303
    00304     _eliminated.reserve(_eliminated.size()+eliminated); //in case not empty?
    00305     for (unsigned i=0; i<_eliminated.size(); i++)
    00306       {
    00307         typename eoPop<EOT>::iterator it = inverse_stochastic_tournament(_newgen.begin(), _newgen.end(), t_rate);
    00308         if (returnEliminated)
    00309           _eliminated.push_back(*it);
    00310         _newgen.erase(it);
    00311       }
    00312   }
    00313
    00314
    00315 private:
    00316   double t_rate;
    00317   eoHowMany howMany;
    00318   bool returnEliminated;
    00319 };
    00320
    00321 //-----------------------------------------------------------------------------
    00322
    00323 #endif