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 /*
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 
00021     Contact: todos@geneura.ugr.es, http://geneura.ugr.es
00022              Marc.Schoenauer@polytechnique.fr
00023              mkeijzer@dhi.dk
00024  */
00025 //-----------------------------------------------------------------------------
00026 
00027 #ifndef _eoStat_h
00028 #define _eoStat_h
00029 
00030 #include <numeric> // accumulate
00031 
00032 #include <eoFunctor.h>
00033 #include <utils/eoParam.h>
00034 #include <eoPop.h>
00035 #include <eoParetoFitness.h>
00036 
00044 template <class EOT>
00045 class eoStatBase : public eoUF<const eoPop<EOT>&, void>
00046 {
00047 public:
00048   virtual void lastCall(const eoPop<EOT>&) {}
00049   virtual std::string className(void) const { return "eoStatBase"; }
00050 };
00051 
00057 template <class EOT, class T>
00058 class eoStat : public eoValueParam<T>, public eoStatBase<EOT>
00059 {
00060 public:
00061 
00062     eoStat(T _value, std::string _description)
00063         : eoValueParam<T>(_value, _description)
00064         {}
00065 
00066     virtual std::string className(void) const
00067         { return "eoStat"; }
00068 };
00069 
00070 
00071 
00075 template <class EOT>
00076 class eoSortedStatBase : public eoUF<const std::vector<const EOT*>&, void>
00077 {
00078 public:
00079   virtual void lastCall(const std::vector<const EOT*>&) {}
00080   virtual std::string className(void) const { return "eoSortedStatBase"; }
00081 };
00082 
00088 template <class EOT, class ParamType>
00089 class eoSortedStat : public eoSortedStatBase<EOT>, public eoValueParam<ParamType>
00090 {
00091 public :
00092   eoSortedStat(ParamType _value, std::string _desc) : eoValueParam<ParamType>(_value, _desc) {}
00093   virtual std::string className(void) const { return "eoSortedStat"; }
00094 };
00095 
00105 #ifdef _MSC_VER
00106 template <class EOT> class eoAverageStat : public eoStat<EOT, EOT::Fitness>
00107 #else
00108 template <class EOT> class eoAverageStat : public eoStat<EOT, typename EOT::Fitness>
00109 #endif
00110 {
00111 public :
00112 
00113     using eoStat<EOT, typename EOT::Fitness>::value;
00114 
00115     typedef typename EOT::Fitness Fitness;
00116 
00117     eoAverageStat(std::string _description = "Average Fitness")
00118       : eoStat<EOT, Fitness>(Fitness(), _description) {}
00119 
00120     static Fitness sumFitness(double _sum, const EOT& _eot){
00121         _sum += _eot.fitness();
00122         return _sum;
00123     }
00124 
00125     eoAverageStat(double _value, std::string _desc) : eoStat<EOT, double>(_value, _desc) {}
00126 
00127     virtual void operator()(const eoPop<EOT>& _pop){
00128       doit(_pop, Fitness()); // specializations for scalar and std::vector
00129     }
00130 
00131   virtual std::string className(void) const { return "eoAverageStat"; }
00132 
00133 private :
00134 
00135     // Specialization for pareto fitness
00136     template <class T>
00137     void doit(const eoPop<EOT>& _pop, eoParetoFitness<T>)
00138     {
00139       value().clear();
00140       value().resize(_pop[0].fitness().size(), 0.0);
00141 
00142       for (unsigned o = 0; o < value().size(); ++o)
00143       {
00144         for (unsigned i = 0; i < _pop.size(); ++i)
00145         {
00146           value()[o] += _pop[i].fitness()[o];
00147         }
00148 
00149         value()[o] /= _pop.size();
00150       }
00151     }
00152 
00153     // Default behavior
00154     template <class T>
00155     void doit(const eoPop<EOT>& _pop, T)
00156     {
00157         Fitness v = std::accumulate(_pop.begin(), _pop.end(), Fitness(0.0), eoAverageStat::sumFitness);
00158 
00159         value() = v / _pop.size();
00160     }
00161 
00162 };
00163 
00167 template <class EOT>
00168 class eoSecondMomentStats : public eoStat<EOT, std::pair<double, double> >
00169 {
00170 public :
00171 
00172     using eoStat<EOT, std::pair<double, double> >::value;
00173 
00174     typedef typename EOT::Fitness fitness_type;
00175 
00176     typedef std::pair<double, double> SquarePair;
00177 
00178     eoSecondMomentStats(std::string _description = "Average & Stdev")
00179         : eoStat<EOT, SquarePair>(std::make_pair(0.0,0.0), _description)
00180         {}
00181 
00182     static SquarePair sumOfSquares(SquarePair _sq, const EOT& _eo)
00183     {
00184         double fitness = _eo.fitness();
00185 
00186         _sq.first += fitness;
00187         _sq.second += fitness * fitness;
00188         return _sq;
00189     }
00190 
00191     virtual void operator()(const eoPop<EOT>& _pop)
00192     {
00193         SquarePair result = std::accumulate(_pop.begin(), _pop.end(), std::make_pair(0.0, 0.0), eoSecondMomentStats::sumOfSquares);
00194 
00195         double n = _pop.size();
00196         value().first = result.first / n; // average
00197         value().second = sqrt( (result.second - n * value().first * value().first) / (n - 1.0)); // stdev
00198     }
00199 
00200   virtual std::string className(void) const { return "eoSecondMomentStats"; }
00201 };
00202 
00206 #ifdef _MSC_VER
00207 template <class EOT>
00208 class eoNthElementFitnessStat : public eoSortedStat<EOT, EOT::Fitness >
00209 #else
00210 template <class EOT>
00211 class eoNthElementFitnessStat : public eoSortedStat<EOT, typename EOT::Fitness >
00212 #endif
00213 {
00214 public :
00215     using eoSortedStat<EOT, typename EOT::Fitness >::value;
00216 
00217     typedef typename EOT::Fitness Fitness;
00218 
00219     eoNthElementFitnessStat(unsigned _whichElement, std::string _description = "nth element fitness")
00220       : eoSortedStat<EOT, Fitness>(Fitness(), _description), whichElement(_whichElement) {}
00221 
00222     virtual void operator()(const std::vector<const EOT*>& _pop)
00223     {
00224         if (whichElement > _pop.size())
00225             throw std::logic_error("fitness requested of element outside of pop");
00226 
00227         doit(_pop, Fitness());
00228     }
00229 
00230   virtual std::string className(void) const { return "eoNthElementFitnessStat"; }
00231 private :
00232 
00233     struct CmpFitness
00234     {
00235       CmpFitness(unsigned _whichElement, bool _maxim) : whichElement(_whichElement), maxim(_maxim) {}
00236 
00237       bool operator()(const EOT* a, const EOT* b)
00238       {
00239         if (maxim)
00240           return a->fitness()[whichElement] > b->fitness()[whichElement];
00241 
00242         return a->fitness()[whichElement] < b->fitness()[whichElement];
00243       }
00244 
00245       unsigned whichElement;
00246       bool maxim;
00247     };
00248 
00249     // Specialization for eoParetoFitness
00250     template <class T>
00251     void doit(const eoPop<EOT>& _pop, eoParetoFitness<T>)
00252     {
00253       typedef typename EOT::Fitness::fitness_traits traits;
00254 
00255       value().resize(traits::nObjectives());
00256 
00257       // copy of pointers, what the heck
00258       std::vector<const EOT*> tmp_pop = _pop;
00259 
00260       for (unsigned o = 0; o < value().size(); ++o)
00261       {
00262         typename std::vector<const EOT*>::iterator nth = tmp_pop.begin() + whichElement;
00263         std::nth_element(tmp_pop.begin(), nth, tmp_pop.end(), CmpFitness(o, traits::maximizing(o)));
00264         value()[o] = (*nth)->fitness()[o];
00265       }
00266     }
00267 
00268     // for everything else
00269     template <class T>
00270     void doit(const std::vector<const EOT*>& _pop, T)
00271     {
00272       value() = _pop[whichElement]->fitness();
00273     }
00274 
00275     unsigned whichElement;
00276 };
00277 
00278 /* Actually, you shouldn't need to sort the population to get the best fitness
00279    MS - 17/11/00
00280 
00281    But then again, if another stat needs sorted fitness anyway, getting the best
00282    out would be very fast.
00283    MK - 09/01/03
00284 
00285 template <class EOT>
00286 class eoBestFitnessStat : public eoStat<EOT, typename EOT::Fitness >
00287 {
00288 public :
00289     typedef typename EOT::Fitness Fitness;
00290 
00291     eoBestFitnessStat(std::string _description = "Best Fitness") :
00292       eoStat<EOT, Fitness>(Fitness(), _description) {}
00293 
00294     virtual void operator()(const eoPop<EOT>& _pop)
00295     {
00296         value() = _pop.nth_element_fitness(0);
00297     }
00298 
00299 };
00300 */
00301 
00311 #ifdef _MSC_VER
00312 template <class EOT>
00313 class eoBestFitnessStat : public eoStat<EOT, EOT::Fitness>
00314 #else
00315 template <class EOT>
00316 class eoBestFitnessStat : public eoStat<EOT, typename EOT::Fitness>
00317 #endif
00318 {
00319 public:
00320 
00321     using eoStat<EOT, typename EOT::Fitness>::value;
00322 
00323     typedef typename EOT::Fitness Fitness;
00324 
00325     eoBestFitnessStat(std::string _description = "Best ")
00326         : eoStat<EOT, Fitness>(Fitness(), _description)
00327         {}
00328 
00329     void operator()(const eoPop<EOT>& _pop) {
00330         doit(_pop, Fitness() ); // specializations for scalar and std::vector
00331     }
00332 
00333     virtual std::string className(void) const { return "eoBestFitnessStat"; }
00334 
00335 
00336 private :
00337 
00338     struct CmpFitness
00339     {
00340       CmpFitness(unsigned _which, bool _maxim) : which(_which), maxim(_maxim) {}
00341 
00342       bool operator()(const EOT& a, const EOT& b)
00343       {
00344         if (maxim)
00345           return a.fitness()[which] < b.fitness()[which];
00346 
00347         return a.fitness()[which] > b.fitness()[which];
00348       }
00349 
00350       unsigned which;
00351       bool maxim;
00352     };
00353 
00354     // Specialization for pareto fitness
00355     template <class T>
00356     void doit(const eoPop<EOT>& _pop, eoParetoFitness<T>)
00357     {
00358       typedef typename EOT::Fitness::fitness_traits traits;
00359       value().resize(traits::nObjectives());
00360 
00361       for (unsigned o = 0; o < traits::nObjectives(); ++o)
00362       {
00363         typename eoPop<EOT>::const_iterator it = std::max_element(_pop.begin(), _pop.end(), CmpFitness(o, traits::maximizing(o)));
00364         value()[o] = it->fitness()[o];
00365       }
00366     }
00367 
00368     // default
00369     template<class T>
00370     void doit(const eoPop<EOT>& _pop, T)
00371     { // find the largest elements
00372       value() = _pop.best_element().fitness();
00373     }
00374 
00375 };
00376 
00377 template <class EOT>
00378 class eoDistanceStat : public eoStat<EOT, double>
00379 {
00380 public:
00381 
00382     using eoDistanceStat< EOT >::value;
00383 
00384     eoDistanceStat(std::string _name = "distance")
00385         : eoStat<EOT, double>(0.0, _name)
00386         {}
00387 
00388     template <class T>
00389     double distance(T a, T b)
00390     {
00391         T res = a-b;
00392         return res < 0? -res : res;
00393     }
00394 
00395     double distance(bool a, bool b)
00396     {
00397         return (a==b)? 0 : 1;
00398     }
00399 
00400     void operator()(const eoPop<EOT>& _pop)
00401     {
00402         double& v = value();
00403         v = 0.0;
00404 
00405         for (unsigned i = 0; i < _pop.size(); ++i)
00406         {
00407             for (unsigned j = 0; j < _pop.size(); ++j)
00408             {
00409                 for (unsigned k = 0; k < _pop[i].size(); ++k)
00410                 {
00411                     v += distance(_pop[i][k], _pop[j][k]);
00412                 }
00413             }
00414         }
00415 
00416         double sz = _pop.size();
00417         v /= sz * sz * _pop[0].size();
00418     }
00419   virtual std::string className(void) const { return "eoDistanceStat"; }
00420 
00421 };
00422 
00423 
00424 
00425 /*
00426 template <class EOT>
00427 class eoStdevStat : public eoStat<EOT, double >
00428 {
00429 public :
00430     typedef typename eoSecondMomentStats<EOT>::SquarePair SquarePair;
00431 
00432     eoStdevStat(std::string _description = "Stdev") : eoStat<EOT, double>(0.0, _description) {}
00433 
00434     virtual void operator()(const eoPop<EOT>& _pop)
00435     {
00436         SquarePair result = std::accumulate(pop.begin(), pop.end(), std::make_pair(0.0, 0.0), eoSecondMomentStats::sumOfSquares);
00437 
00438         double n = pop.size();
00439         value() = sqrt( (result.second - (result.first / n)) / (n - 1.0)); // stdev
00440     }
00441 };
00442 */
00443 #endif

Generated on Thu Oct 19 05:06:38 2006 for EO by  doxygen 1.3.9.1