Updated eoStat.h to also "do the right thing" when confronted with pareto style fitness
This commit is contained in:
parent
11cdd38f24
commit
9bbac485f9
2 changed files with 134 additions and 15 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Reference in a new issue