Updated eoStat.h to also "do the right thing" when confronted with pareto style fitness

This commit is contained in:
maartenkeijzer 2001-03-20 14:34:07 +00:00
commit 9bbac485f9
2 changed files with 134 additions and 15 deletions

View file

@ -64,10 +64,14 @@ public :
virtual void operator()(const vector<const EOT*>& _popPters) virtual void operator()(const vector<const EOT*>& _popPters)
{ {
value().resize(_popPters.size()); value().resize(_popPters.size());
for (unsigned i=0; i<_popPters.size(); i++) for (unsigned i=0; i<_popPters.size(); i++)
{
value()[i] = _popPters[i]->fitness()[objective]; value()[i] = _popPters[i]->fitness()[objective];
}
} }
private: private:
unsigned int objective; // The objective we're storing unsigned int objective; // The objective we're storing
}; };
#endif #endif

View file

@ -30,6 +30,8 @@
#include <eoFunctor.h> #include <eoFunctor.h>
#include <utils/eoParam.h> #include <utils/eoParam.h>
#include <eoPop.h> #include <eoPop.h>
#include <numeric> // accumulate
#include <eoParetoFitness.h>
/** /**
Base class for all statistics that need to be calculated Base class for all statistics that need to be calculated
@ -76,16 +78,16 @@ public :
eoSortedStat(ParamType _value, std::string _desc) : eoValueParam<ParamType>(_value, _desc) {} eoSortedStat(ParamType _value, std::string _desc) : eoValueParam<ParamType>(_value, _desc) {}
}; };
#include <numeric>
/** /**
Average fitness of a population, fitness needs to be scalar. Average fitness of a population, fitness can be a double, eoMinimizingFitness, eoMaximizingFitness or eoParetoFitness.
In the case of pareto optimization it will calculate the average of each objective.
*/ */
template <class EOT> template <class EOT>
class eoAverageStat : public eoStat<EOT, double> class eoAverageStat : public eoStat<EOT, typename EOT::Fitness>
{ {
public : public :
eoAverageStat(std::string _description = "Average Fitness") : eoStat<EOT, double>(0.0, _description) {} typedef typename EOT::Fitness fitness_type;
eoAverageStat(std::string _description = "Average Fitness") : eoStat<EOT, typename EOT::Fitness>(fitness_type(), _description) {}
static double sumFitness(double _sum, const EOT& _eot) static double sumFitness(double _sum, const EOT& _eot)
{ {
@ -96,11 +98,36 @@ public :
eoAverageStat(double _value, std::string _desc) : eoStat<EOT, double>(_value, _desc) {} eoAverageStat(double _value, std::string _desc) : eoStat<EOT, double>(_value, _desc) {}
virtual void operator()(const eoPop<EOT>& _pop) virtual void operator()(const eoPop<EOT>& _pop)
{
doit(_pop, typename EOT::Fitness()); // specializations for scalar and vector
}
private :
template <class T>
void doit(const eoPop<EOT>& _pop, eoParetoFitness<T>)
{
value().clear();
value().resize(_pop[0].fitness().size(), 0.0);
for (unsigned o = 0; o < value().size(); ++o)
{
for (unsigned i = 0; i < _pop.size(); ++i)
{
value()[o] += _pop[i].fitness()[o];
}
value()[o] /= _pop.size();
}
}
template <class T>
void doit(const eoPop<EOT>& _pop, T)
{ {
double v = std::accumulate(_pop.begin(), _pop.end(), 0.0, eoAverageStat::sumFitness); double v = std::accumulate(_pop.begin(), _pop.end(), 0.0, eoAverageStat::sumFitness);
value() = v / _pop.size(); value() = v / _pop.size();
} }
}; };
/** /**
@ -148,10 +175,53 @@ public :
if (which > _pop.size()) if (which > _pop.size())
throw logic_error("fitness requested of element outside of pop"); throw logic_error("fitness requested of element outside of pop");
value() = _pop[which]->fitness(); doit(_pop, Fitness());
} }
private : private :
struct CmpFitness
{
CmpFitness(unsigned _which, bool _maxim) : which(_which), maxim(_maxim) {}
bool operator()(const EOT* a, const EOT* b)
{
if (maxim)
return a->fitness()[which] > b->fitness()[which];
return a->fitness()[which] < b->fitness()[which];
}
unsigned which;
bool maxim;
};
template <class T>
void doit(const eoPop<EOT>& _pop, eoParetoFitness<T>)
{
typedef typename EOT::Fitness::fitness_traits traits;
value().resize(traits::nObjectives());
// copy of pointers, what the heck
vector<const EOT*> tmp_pop = _pop;
for (unsigned o = 0; o < value().size(); ++o)
{
vector<const EOT*>::iterator nth = tmp_pop.begin() + which;
std::nth_element(tmp_pop.begin(), nth, tmp_pop.end(), CmpFitness(o, traits::maximizing(o)));
value()[o] = (*nth)->fitness()[o];
}
}
// for everything else
template <class T>
void doit(const vector<const EOT*>& _pop, T)
{
value() = _pop[which]->fitness();
}
unsigned which; unsigned which;
}; };
@ -179,12 +249,57 @@ public :
Best fitness in the population Best fitness in the population
*/ */
template <class EOT> template <class EOT>
class eoBestFitnessStat : public eoNthElementFitnessStat<EOT> class eoBestFitnessStat : public eoStat<EOT, typename EOT::Fitness>
{ {
public : public :
typedef typename EOT::Fitness Fitness; typedef typename EOT::Fitness Fitness;
eoBestFitnessStat(std::string _description = "Best ") : eoNthElementFitnessStat<EOT>(0, _description) {} eoBestFitnessStat(std::string _description = "Best ") : eoStat<EOT, typename EOT::Fitness>(typename EOT::Fitness(), _description) {}
void operator()(const eoPop<EOT>& _pop)
{
doit(_pop, typename EOT::Fitness());
}
private :
struct CmpFitness
{
CmpFitness(unsigned _which, bool _maxim) : which(_which), maxim(_maxim) {}
bool operator()(const EOT& a, const EOT& b)
{
if (maxim)
return a.fitness()[which] < b.fitness()[which];
return a.fitness()[which] > b.fitness()[which];
}
unsigned which;
bool maxim;
};
template <class T>
void doit(const eoPop<EOT>& _pop, eoParetoFitness<T>)
{
typedef typename EOT::Fitness::fitness_traits traits;
value().resize(traits::nObjectives());
for (unsigned o = 0; o < traits::nObjectives(); ++o)
{
eoPop<EOT>::const_iterator it = max_element(_pop.begin(), _pop.end(), CmpFitness(o, traits::maximizing(o)));
value()[o] = it->fitness()[o];
}
}
// default
template<class T>
void doit(const eoPop<EOT>& _pop, T)
{ // find the largest elements
value() = _pop.best_element().fitness();
}
}; };
template <class EOT> template <class EOT>