EvolvingObjects
eoStat.h
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
 All Classes Namespaces Files Functions Variables Typedefs Friends