EvolvingObjects
|
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