EvolvingObjects
|
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 00046 template<class EOT> class eoReduceSplit: public eoBF<eoPop<EOT>&, eoPop<EOT> &, void > 00047 {}; 00048 00050 template <class EOT> 00051 class eoTruncateSplit : public eoReduceSplit<EOT> 00052 { 00053 public: 00057 eoTruncateSplit(eoHowMany _howMany, bool _returnEliminated = false): 00058 howMany(_howMany), returnEliminated(_returnEliminated) {} 00059 00061 void operator()(eoPop<EOT>& _newgen, eoPop<EOT> & _eliminated) 00062 { 00063 unsigned popSize = _newgen.size(); 00064 unsigned eliminated = howMany(popSize); 00065 if (!eliminated) // nothing to do 00066 return ; 00067 unsigned newsize = popSize - eliminated; 00068 if (newsize < 0) 00069 throw std::logic_error("eoTruncateSplit: Cannot truncate to a larger size!\n"); 00070 00071 _newgen.nth_element(newsize); 00072 00073 // save poor losers if necessary 00074 if (returnEliminated) 00075 for (unsigned i=0; i<eliminated; i++) 00076 _eliminated.push_back(_newgen[newsize+i]); 00077 // truncate 00078 _newgen.resize(newsize); 00079 return ; 00080 } 00081 00082 private: 00083 eoHowMany howMany; 00084 bool returnEliminated; 00085 }; 00086 00090 template <class EOT> 00091 class eoLinearTruncateSplit : public eoReduceSplit<EOT> 00092 { 00093 public: 00097 eoLinearTruncateSplit(eoHowMany _howMany, bool _returnEliminated = false): 00098 howMany(_howMany), returnEliminated(_returnEliminated) {} 00099 00101 void operator()(eoPop<EOT>& _newgen, eoPop<EOT> & _eliminated) 00102 { 00103 unsigned popSize = _newgen.size(); 00104 unsigned eliminated = howMany(popSize); 00105 if (!eliminated) // nothing to do 00106 return ; 00107 long newsize = static_cast<long>(popSize) - static_cast<long>(eliminated); 00108 if (newsize < 0) 00109 throw std::logic_error("eoLinearTruncateSplit: Cannot truncate to a larger size!\n"); 00110 00111 _eliminated.reserve(_eliminated.size()+eliminated); //in case not empty? 00112 for (unsigned i=0; i<eliminated; i++) 00113 { 00114 typename eoPop<EOT>::iterator it = _newgen.it_worse_element(); 00115 if (returnEliminated) 00116 _eliminated.push_back(*it); 00117 _newgen.erase(it); 00118 } 00119 } 00120 00121 private: 00122 eoHowMany howMany; 00123 bool returnEliminated; 00124 }; 00125 00127 template <class EOT> 00128 class eoRandomSplit : public eoReduceSplit<EOT> 00129 { 00130 public: 00134 eoRandomSplit(eoHowMany _howMany, bool _returnEliminated = false): 00135 howMany(_howMany), returnEliminated(_returnEliminated) {} 00136 00138 void operator()(eoPop<EOT>& _newgen, eoPop<EOT> & _eliminated) 00139 { 00140 unsigned popSize = _newgen.size(); 00141 unsigned eliminated = howMany(popSize); 00142 if (!eliminated) // nothing to do 00143 return ; 00144 unsigned newsize = popSize - eliminated; 00145 if (newsize < 0) 00146 throw std::logic_error("eoRandomSplit: Cannot truncate to a larger size!\n"); 00147 00148 _newgen.shuffle(); 00149 00150 // save poor losers if necessary 00151 if (returnEliminated) 00152 for (unsigned i=0; i<eliminated; i++) 00153 _eliminated.push_back(_newgen[newsize+i]); 00154 // truncate 00155 _newgen.resize(newsize); 00156 return ; 00157 } 00158 00159 private: 00160 eoHowMany howMany; 00161 bool returnEliminated; 00162 }; 00163 00164 00166 template <class EOT> 00167 class eoLinearRandomSplit : public eoReduceSplit<EOT> 00168 { 00169 public: 00173 eoLinearRandomSplit(eoHowMany _howMany, bool _returnEliminated = false): 00174 howMany(_howMany), returnEliminated(_returnEliminated) {} 00175 00177 void operator()(eoPop<EOT>& _newgen, eoPop<EOT> & _eliminated) 00178 { 00179 unsigned popSize = _newgen.size(); 00180 unsigned eliminated = howMany(popSize); 00181 if (!eliminated) // nothing to do 00182 return ; 00183 unsigned newsize = popSize - eliminated; 00184 if (newsize < 0) 00185 throw std::logic_error("eoLinearRandomSplit: Cannot truncate to a larger size!\n"); 00186 00187 _eliminated.reserve(_eliminated.size()+eliminated); //in case not empty? 00188 for (unsigned i=0; i<eliminated; i++) 00189 { 00190 unsigned loser=random(_newgen.size()); 00191 typename eoPop<EOT>::iterator it = _newgen.begin()+loser; 00192 if (returnEliminated) 00193 _eliminated.push_back(*it); 00194 _newgen.erase(it); 00195 } 00196 return ; 00197 } 00198 00199 private: 00200 eoHowMany howMany; 00201 bool returnEliminated; 00202 }; 00203 00204 00208 template <class EOT> 00209 class eoDetTournamentTruncateSplit : public eoReduceSplit<EOT> 00210 { 00211 public: 00215 eoDetTournamentTruncateSplit(unsigned _t_size, eoHowMany _howMany, 00216 bool _returnEliminated = false): 00217 t_size(_t_size), howMany(_howMany), 00218 returnEliminated(_returnEliminated) 00219 { 00220 if (t_size < 2) 00221 { 00222 eo::log << eo::warnings << "Warning, Size for eoDetTournamentTruncateSplit adjusted to 2" << std::endl; 00223 t_size = 2; 00224 } 00225 } 00226 00228 void operator()(eoPop<EOT>& _newgen, eoPop<EOT> & _eliminated) 00229 // BUG??? void operator()(eoPop<EOT>& _newgen, unsigned _newsize) 00230 { 00231 unsigned popSize = _newgen.size(); 00232 unsigned eliminated = howMany(popSize); 00233 if (!eliminated) // nothing to do 00234 return ; 00235 unsigned newsize = popSize - eliminated; 00236 if (newsize < 0) 00237 throw std::logic_error("eoDetTournamentTruncateSplit: Cannot truncate to a larger size!\n"); 00238 00239 00240 _eliminated.reserve(_eliminated.size()+eliminated); //in case not empty? 00241 for (unsigned i=0; i<eliminated; i++) 00242 { 00243 typename eoPop<EOT>::iterator it = inverse_deterministic_tournament(_newgen.begin(), _newgen.end(), t_size); 00244 if (returnEliminated) 00245 _eliminated.push_back(*it); 00246 _newgen.erase(it); 00247 } 00248 } 00249 00250 private: 00251 unsigned t_size; 00252 eoHowMany howMany; 00253 bool returnEliminated; 00254 }; 00255 00259 template <class EOT> 00260 class eoStochTournamentTruncateSplit : public eoReduce<EOT> 00261 { 00262 public: 00266 eoStochTournamentTruncateSplit(double _t_rate, eoHowMany _howMany, 00267 bool _returnEliminated = false): 00268 t_rate(_t_rate), howMany(_howMany), 00269 returnEliminated(_returnEliminated) 00270 { 00271 if (t_rate <= 0.5) 00272 { 00273 eo::log << eo::warnings << "Warning, Rate for eoStochTournamentTruncateSplit adjusted to 0.51" << std::endl; 00274 t_rate = 0.51; 00275 } 00276 if (t_rate > 1) 00277 { 00278 eo::log << eo::warnings << "Warning, Rate for eoStochTournamentTruncateSplit adjusted to 1" << std::endl; 00279 t_rate = 1; 00280 } 00281 } 00282 00284 void operator()(eoPop<EOT>& _newgen, eoPop<EOT> & _eliminated) 00285 //BUG??? void operator()(eoPop<EOT>& _newgen, unsigned _newsize) 00286 { 00287 /* old version 00288 if (!_eliminated.size()) // nothing to do 00289 return; 00290 unsigned oldSize = _newgen.size(); 00291 unsigned newSize = oldSize - _eliminated.size(); 00292 unsigned eliminated = howMany(popSize); 00293 if (newSize < 0) 00294 throw std::logic_error("eoStochTournamentTruncateSplit: Cannot truncate to a larger size!\n"); 00295 00296 end of old version */ 00297 00298 unsigned popSize = _newgen.size(); 00299 unsigned eliminated = howMany(popSize); 00300 if (!eliminated) // nothing to do 00301 return ; 00302 unsigned newsize = popSize - eliminated; 00303 if (newsize < 0) 00304 throw std::logic_error("eoDetTournamentTruncateSplit: Cannot truncate to a larger size!\n"); 00305 00306 00307 00308 _eliminated.reserve(_eliminated.size()+eliminated); //in case not empty? 00309 for (unsigned i=0; i<_eliminated.size(); i++) 00310 { 00311 typename eoPop<EOT>::iterator it = inverse_stochastic_tournament(_newgen.begin(), _newgen.end(), t_rate); 00312 if (returnEliminated) 00313 _eliminated.push_back(*it); 00314 _newgen.erase(it); 00315 } 00316 } 00317 00318 00319 private: 00320 double t_rate; 00321 eoHowMany howMany; 00322 bool returnEliminated; 00323 }; 00324 00325 //----------------------------------------------------------------------------- 00326 00328 #endif