EvolvingObjects
|
00001 // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- 00002 00003 //----------------------------------------------------------------------------- 00004 // eoStat.h 00005 // (c) Marc Schoenauer, Maarten Keijzer and GeNeura Team, 2000 00006 // (c) 2010 Thales group 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: http://eodev.sourceforge.net 00023 00024 Authors: 00025 todos@geneura.ugr.es, http://geneura.ugr.es 00026 Marc.Schoenauer@polytechnique.fr 00027 mkeijzer@dhi.dk 00028 Johann Dréo <johann.dreo@thalesgroup.com> 00029 */ 00030 //----------------------------------------------------------------------------- 00031 00032 #ifndef _eoStat_h 00033 #define _eoStat_h 00034 00035 #include <numeric> // accumulate 00036 00037 #include <eoFunctor.h> 00038 #include <utils/eoParam.h> 00039 #include <eoPop.h> 00040 #include <utils/eoMonitor.h> 00041 //#include <utils/eoCheckPoint.h> 00042 00066 template <class EOT> 00067 class eoStatBase : public eoUF<const eoPop<EOT>&, void> 00068 { 00069 public: 00070 virtual void lastCall(const eoPop<EOT>&) {} 00071 virtual std::string className(void) const { return "eoStatBase"; } 00072 }; 00073 00074 00075 template <class EOT> class eoCheckPoint; 00076 00082 template <class EOT, class T> 00083 class eoStat : public eoValueParam<T>, public eoStatBase<EOT> 00084 { 00085 public: 00086 00087 eoStat(T _value, std::string _description) 00088 : eoValueParam<T>(_value, _description) 00089 {} 00090 00091 virtual std::string className(void) const 00092 { return "eoStat"; } 00093 00094 00095 eoStat<EOT, T>& addTo(eoCheckPoint<EOT>& cp) { cp.add(*this); return *this; } 00096 eoStat<EOT, T>& addTo(eoMonitor& mon) { mon.add(*this); return *this; } 00097 }; 00098 00099 00100 00104 template <class EOT> 00105 class eoSortedStatBase : public eoUF<const std::vector<const EOT*>&, void> 00106 { 00107 public: 00108 virtual void lastCall(const std::vector<const EOT*>&) {} 00109 virtual std::string className(void) const { return "eoSortedStatBase"; } 00110 00111 }; 00112 00118 template <class EOT, class ParamType> 00119 class eoSortedStat : public eoSortedStatBase<EOT>, public eoValueParam<ParamType> 00120 { 00121 public : 00122 eoSortedStat(ParamType _value, std::string _desc) : eoValueParam<ParamType>(_value, _desc) {} 00123 virtual std::string className(void) const { return "eoSortedStat"; } 00124 00125 eoSortedStat<EOT, ParamType>& addTo(eoCheckPoint<EOT>& cp) { cp.add(*this); return *this; } 00126 eoSortedStat<EOT, ParamType>& addTo(eoMonitor& mon) { mon.add(*this); return *this; } 00127 }; 00128 00137 #if defined(_MSC_VER) && (_MSC_VER < 1300) 00138 template <class EOT> class eoAverageStat : public eoStat<EOT, EOT::Fitness> 00139 #else 00140 template <class EOT> class eoAverageStat : public eoStat<EOT, typename EOT::Fitness> 00141 #endif 00142 { 00143 public : 00144 00145 using eoStat<EOT, typename EOT::Fitness>::value; 00146 00147 typedef typename EOT::Fitness Fitness; 00148 00149 eoAverageStat(std::string _description = "Average Fitness") 00150 : eoStat<EOT, Fitness>(Fitness(), _description) {} 00151 00152 static Fitness sumFitness(double _sum, const EOT& _eot){ 00153 _sum += _eot.fitness(); 00154 return _sum; 00155 } 00156 00157 eoAverageStat(double _value, std::string _desc) : eoStat<EOT, double>(_value, _desc) {} 00158 00159 virtual void operator()(const eoPop<EOT>& _pop){ 00160 doit(_pop, Fitness()); // specializations for scalar and std::vector 00161 } 00162 00163 virtual std::string className(void) const { return "eoAverageStat"; } 00164 00165 private : 00166 00167 // Default behavior 00168 template <class T> 00169 void doit(const eoPop<EOT>& _pop, T) 00170 { 00171 Fitness v = std::accumulate(_pop.begin(), _pop.end(), Fitness(0.0), eoAverageStat::sumFitness); 00172 00173 value() = v / _pop.size(); 00174 } 00175 00176 }; 00177 00181 template <class EOT> 00182 class eoSecondMomentStats : public eoStat<EOT, std::pair<double, double> > 00183 { 00184 public : 00185 00186 using eoStat<EOT, std::pair<double, double> >::value; 00187 00188 typedef typename EOT::Fitness fitness_type; 00189 00190 typedef std::pair<double, double> SquarePair; 00191 00192 eoSecondMomentStats(std::string _description = "Average & Stdev") 00193 : eoStat<EOT, SquarePair>(std::make_pair(0.0,0.0), _description) 00194 {} 00195 00196 static SquarePair sumOfSquares(SquarePair _sq, const EOT& _eo) 00197 { 00198 double fitness = _eo.fitness(); 00199 00200 _sq.first += fitness; 00201 _sq.second += fitness * fitness; 00202 return _sq; 00203 } 00204 00205 virtual void operator()(const eoPop<EOT>& _pop) 00206 { 00207 SquarePair result = std::accumulate(_pop.begin(), _pop.end(), std::make_pair(0.0, 0.0), eoSecondMomentStats::sumOfSquares); 00208 00209 double n = _pop.size(); 00210 value().first = result.first / n; // average 00211 value().second = sqrt( (result.second - n * value().first * value().first) / (n - 1.0)); // stdev 00212 } 00213 00214 virtual std::string className(void) const { return "eoSecondMomentStats"; } 00215 }; 00216 00220 #if defined(_MSC_VER) && (_MSC_VER < 1300) 00221 template <class EOT> 00222 class eoNthElementFitnessStat : public eoSortedStat<EOT, EOT::Fitness > 00223 #else 00224 template <class EOT> 00225 class eoNthElementFitnessStat : public eoSortedStat<EOT, typename EOT::Fitness > 00226 #endif 00227 { 00228 public : 00229 using eoSortedStat<EOT, typename EOT::Fitness >::value; 00230 00231 typedef typename EOT::Fitness Fitness; 00232 00233 eoNthElementFitnessStat(unsigned _whichElement, std::string _description = "nth element fitness") 00234 : eoSortedStat<EOT, Fitness>(Fitness(), _description), whichElement(_whichElement) {} 00235 00236 virtual void operator()(const std::vector<const EOT*>& _pop) 00237 { 00238 if (whichElement > _pop.size()) 00239 throw std::logic_error("fitness requested of element outside of pop"); 00240 00241 doit(_pop, Fitness()); 00242 } 00243 00244 virtual std::string className(void) const { return "eoNthElementFitnessStat"; } 00245 private : 00246 00247 struct CmpFitness 00248 { 00249 CmpFitness(unsigned _whichElement, bool _maxim) : whichElement(_whichElement), maxim(_maxim) {} 00250 00251 bool operator()(const EOT* a, const EOT* b) 00252 { 00253 if (maxim) 00254 return a->fitness()[whichElement] > b->fitness()[whichElement]; 00255 00256 return a->fitness()[whichElement] < b->fitness()[whichElement]; 00257 } 00258 00259 unsigned whichElement; 00260 bool maxim; 00261 }; 00262 00263 // for everything else 00264 template <class T> 00265 void doit(const std::vector<const EOT*>& _pop, T) 00266 { 00267 value() = _pop[whichElement]->fitness(); 00268 } 00269 00270 unsigned whichElement; 00271 }; 00272 00273 /* Actually, you shouldn't need to sort the population to get the best fitness 00274 MS - 17/11/00 00275 00276 But then again, if another stat needs sorted fitness anyway, getting the best 00277 out would be very fast. 00278 MK - 09/01/03 00279 00280 template <class EOT> 00281 class eoBestFitnessStat : public eoStat<EOT, typename EOT::Fitness > 00282 { 00283 public : 00284 typedef typename EOT::Fitness Fitness; 00285 00286 eoBestFitnessStat(std::string _description = "Best Fitness") : 00287 eoStat<EOT, Fitness>(Fitness(), _description) {} 00288 00289 virtual void operator()(const eoPop<EOT>& _pop) 00290 { 00291 value() = _pop.nth_element_fitness(0); 00292 } 00293 00294 }; 00295 */ 00296 00305 #if defined(_MSC_VER) && (_MSC_VER < 1300) 00306 template <class EOT> 00307 class eoBestFitnessStat : public eoStat<EOT, EOT::Fitness> 00308 #else 00309 template <class EOT> 00310 class eoBestFitnessStat : public eoStat<EOT, typename EOT::Fitness> 00311 #endif 00312 { 00313 public: 00314 00315 using eoStat<EOT, typename EOT::Fitness>::value; 00316 00317 typedef typename EOT::Fitness Fitness; 00318 00319 eoBestFitnessStat(std::string _description = "Best ") 00320 : eoStat<EOT, Fitness>(Fitness(), _description) 00321 {} 00322 00323 void operator()(const eoPop<EOT>& _pop) { 00324 doit(_pop, Fitness() ); // specializations for scalar and std::vector 00325 } 00326 00327 virtual std::string className(void) const { return "eoBestFitnessStat"; } 00328 00329 00330 private : 00331 00332 struct CmpFitness 00333 { 00334 CmpFitness(unsigned _which, bool _maxim) : which(_which), maxim(_maxim) {} 00335 00336 bool operator()(const EOT& a, const EOT& b) 00337 { 00338 if (maxim) 00339 return a.fitness()[which] < b.fitness()[which]; 00340 00341 return a.fitness()[which] > b.fitness()[which]; 00342 } 00343 00344 unsigned which; 00345 bool maxim; 00346 }; 00347 00348 // default 00349 template<class T> 00350 void doit(const eoPop<EOT>& _pop, T) 00351 { // find the largest elements 00352 value() = _pop.best_element().fitness(); 00353 } 00354 00355 }; 00359 template <class EOT> 00360 class eoDistanceStat : public eoStat<EOT, double> 00361 { 00362 public: 00363 00364 using eoStat<EOT, double>::value; 00365 00366 eoDistanceStat(std::string _name = "distance") 00367 : eoStat<EOT, double>(0.0, _name) 00368 {} 00369 00370 template <class T> 00371 double distance(T a, T b) 00372 { 00373 T res = a-b; 00374 return res < 0? -res : res; 00375 } 00376 00377 double distance(bool a, bool b) 00378 { 00379 return (a==b)? 0 : 1; 00380 } 00381 00382 void operator()(const eoPop<EOT>& _pop) 00383 { 00384 double& v = value(); 00385 v = 0.0; 00386 00387 for (unsigned i = 0; i < _pop.size(); ++i) 00388 { 00389 for (unsigned j = 0; j < _pop.size(); ++j) 00390 { 00391 for (unsigned k = 0; k < _pop[i].size(); ++k) 00392 { 00393 v += distance(_pop[i][k], _pop[j][k]); 00394 } 00395 } 00396 } 00397 00398 double sz = _pop.size(); 00399 v /= sz * sz * _pop[0].size(); 00400 } 00401 virtual std::string className(void) const { return "eoDistanceStat"; } 00402 00403 }; 00404 00405 00406 00407 /* 00408 template <class EOT> 00409 class eoStdevStat : public eoStat<EOT, double > 00410 { 00411 public : 00412 typedef typename eoSecondMomentStats<EOT>::SquarePair SquarePair; 00413 00414 eoStdevStat(std::string _description = "Stdev") : eoStat<EOT, double>(0.0, _description) {} 00415 00416 virtual void operator()(const eoPop<EOT>& _pop) 00417 { 00418 SquarePair result = std::accumulate(pop.begin(), pop.end(), std::make_pair(0.0, 0.0), eoSecondMomentStats::sumOfSquares); 00419 00420 double n = pop.size(); 00421 value() = sqrt( (result.second - (result.first / n)) / (n - 1.0)); // stdev 00422 } 00423 }; 00424 */ 00425 00426 00428 template<class EOT> 00429 class eoInterquartileRangeStat : public eoStat< EOT, typename EOT::Fitness > 00430 { 00431 public: 00432 using eoStat<EOT, typename EOT::Fitness>::value; 00433 00434 eoInterquartileRangeStat( typename EOT::Fitness start, std::string description = "IQR" ) : eoStat<EOT,typename EOT::Fitness>( start, description ) {} 00435 00436 virtual void operator()( const eoPop<EOT> & _pop ) 00437 { 00438 if( _pop.size() == 0 ) { 00439 // how to implement value() = 0 ? 00440 00441 } else { 00442 eoPop<EOT> pop = _pop; 00443 00444 unsigned int quartile = pop.size()/4; 00445 std::nth_element( pop.begin(), pop.begin()+quartile*1, pop.end() ); 00446 typename EOT::Fitness Q1 = pop[quartile].fitness(); 00447 00448 std::nth_element( pop.begin(), pop.begin()+quartile*3, pop.end() ); 00449 typename EOT::Fitness Q3 = pop[quartile*3].fitness(); 00450 00451 value() = Q3 - Q1; 00452 } 00453 } 00454 00455 virtual std::string className(void) const { return "eoInterquartileRangeStat"; } 00456 }; 00465 template<class EOT> 00466 class eoAverageSizeStat : public eoStat< EOT, double> 00467 { 00468 public: 00469 00470 using eoStat<EOT, double>::value; 00471 00472 eoAverageSizeStat( std::string description = "Av.Size" ) : 00473 eoStat<EOT,double>( 0.0, description ) {} // 0 by default 00474 00475 virtual void operator()( const eoPop<EOT> & pop ) 00476 { 00477 size_t pop_size = pop.size(); 00478 00479 std::vector<size_t> sizes; 00480 sizes.reserve(pop_size); 00481 00482 for( unsigned int i=0, s = pop_size; i<s; ++i ) { 00483 sizes.push_back( pop[i].size() ); 00484 } 00485 00486 size_t sum = std::accumulate( sizes.begin(), sizes.end(), 0 ); 00487 00488 value() = static_cast<double>(sum) / static_cast<double>(pop_size); 00489 } 00490 00491 virtual std::string className(void) const { return "eoAverageSizeStat"; } 00492 }; 00493 00495 #endif