Changed a few things in the eoPerf2Worth classes, EO.h and eoSelectOne.h are functionally unchanged
This commit is contained in:
parent
9bbac485f9
commit
665e20b0f8
10 changed files with 331 additions and 80 deletions
|
|
@ -115,6 +115,7 @@
|
||||||
|
|
||||||
// Perf2Worth
|
// Perf2Worth
|
||||||
#include <eoParetoRanking.h>
|
#include <eoParetoRanking.h>
|
||||||
|
#include <eoNDSorting.h>
|
||||||
|
|
||||||
// Algorithms
|
// Algorithms
|
||||||
#include <eoEasyEA.h>
|
#include <eoEasyEA.h>
|
||||||
|
|
|
||||||
|
|
@ -93,12 +93,12 @@ class eoDominanceMap : public eoUF<const eoPop<EoType>&, void>, public std::vect
|
||||||
|
|
||||||
for (unsigned j = 0; j < i; ++j)
|
for (unsigned j = 0; j < i; ++j)
|
||||||
{
|
{
|
||||||
if (_pop[i].fitness() > _pop[j].fitness())
|
if (_pop[i].fitness().dominates(_pop[j].fitness()))
|
||||||
{
|
{
|
||||||
operator[](i)[j] = true;
|
operator[](i)[j] = true;
|
||||||
operator[](j)[i] = false;
|
operator[](j)[i] = false;
|
||||||
}
|
}
|
||||||
else if (_pop[j].fitness() > _pop[i].fitness())
|
else if (_pop[j].fitness().dominates(_pop[i].fitness()))
|
||||||
{
|
{
|
||||||
operator[](i)[j] = false;
|
operator[](i)[j] = false;
|
||||||
operator[](j)[i] = true;
|
operator[](j)[i] = true;
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
* to be used within an eoSelectFromWorth object
|
* to be used within an eoSelectFromWorth object
|
||||||
*/
|
*/
|
||||||
template <class EOT>
|
template <class EOT>
|
||||||
class eoLinearFitScaling : public eoPerf2Worth<EOT>
|
class eoLinearFitScaling : public eoPerf2Worth<EOT> // false: do not cache fitness
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/* Ctor:
|
/* Ctor:
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <eoPerf2Worth.h>
|
#include <eoPerf2Worth.h>
|
||||||
#include <eoDominanceMap.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Non dominated sorting, it *is a* vector of doubles, the integer part is the rank (to which front it belongs),
|
Non dominated sorting, it *is a* vector of doubles, the integer part is the rank (to which front it belongs),
|
||||||
|
|
@ -37,63 +36,88 @@
|
||||||
the bits.
|
the bits.
|
||||||
*/
|
*/
|
||||||
template <class EOT>
|
template <class EOT>
|
||||||
class eoNDSorting : public eoPerf2Worth<EOT, double>
|
class eoNDSorting : public eoPerf2WorthCached<EOT, double>
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
eoNDSorting(eoDominanceMap<EOT>& _dominanceMap) :
|
|
||||||
eoPerf2Worth<EOT, double>(), dominanceMap(_dominanceMap) {}
|
|
||||||
|
|
||||||
/** Pure virtual function that calculates the 'distance' for each element to the current front
|
/** Pure virtual function that calculates the 'distance' for each element to the current front
|
||||||
Implement to create your own nondominated sorting algorithm. The size of the returned vector
|
Implement to create your own nondominated sorting algorithm. The size of the returned vector
|
||||||
should be equal to the size of the current_front.
|
should be equal to the size of the current_front.
|
||||||
*/
|
*/
|
||||||
virtual vector<double> niche_penalty(const vector<unsigned>& current_front, const eoPop<EOT>& _pop) = 0;
|
virtual vector<double> niche_penalty(const vector<unsigned>& current_front, const eoPop<EOT>& _pop) = 0;
|
||||||
|
|
||||||
/// Do the work
|
/** implements fast nondominated sorting
|
||||||
void operator()(const eoPop<EOT>& _pop)
|
*/
|
||||||
|
void calculate_worths(const eoPop<EOT>& _pop)
|
||||||
{
|
{
|
||||||
dominanceMap(_pop);
|
|
||||||
|
|
||||||
vector<bool> excluded(_pop.size(), false);
|
|
||||||
|
|
||||||
value().resize(_pop.size());
|
value().resize(_pop.size());
|
||||||
|
|
||||||
bool finished = false;
|
typedef typename EOT::Fitness::fitness_traits traits;
|
||||||
|
|
||||||
int dominance_level = 0;
|
if (traits::nObjectives() == 1)
|
||||||
|
{ // no need to do difficult sorting,
|
||||||
|
|
||||||
while(!finished)
|
for (unsigned i = 0; i < _pop.size(); ++i)
|
||||||
{
|
{
|
||||||
vector<double> ranks = dominanceMap.sum_dominators();
|
value()[i] = _pop[i].fitness()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!traits::maximizing(0))
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < value().size(); ++i)
|
||||||
|
{
|
||||||
|
value()[i] = exp(-value()[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<vector<unsigned> > S(_pop.size()); // which individuals does guy i dominate
|
||||||
|
vector<unsigned> n(_pop.size(), 0); // how many individuals dominate guy i
|
||||||
|
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < _pop.size(); ++i)
|
||||||
|
{
|
||||||
|
for (unsigned j = 0; j < _pop.size(); ++j)
|
||||||
|
{
|
||||||
|
if (_pop[i].fitness().dominates(_pop[j].fitness()))
|
||||||
|
{ // i dominates j
|
||||||
|
S[i].push_back(j); // add j to i's domination list
|
||||||
|
|
||||||
|
//n[j]++; // as i dominates j
|
||||||
|
}
|
||||||
|
else if (_pop[j].fitness().dominates(_pop[i].fitness()))
|
||||||
|
{ // j dominates i, increment count for i, add i to the domination list of j
|
||||||
|
n[i]++;
|
||||||
|
|
||||||
|
//S[j].push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vector<unsigned> current_front;
|
vector<unsigned> current_front;
|
||||||
current_front.reserve(_pop.size());
|
current_front.reserve(_pop.size());
|
||||||
|
|
||||||
finished = true;
|
// get the first front out
|
||||||
|
|
||||||
for (unsigned i = 0; i < _pop.size(); ++i)
|
for (unsigned i = 0; i < _pop.size(); ++i)
|
||||||
{
|
{
|
||||||
if (excluded[i])
|
if (n[i] == 0)
|
||||||
{
|
{
|
||||||
continue; // next please
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ranks[i] < 1e-6)
|
|
||||||
{// it's part of the current front
|
|
||||||
excluded[i] = true;
|
|
||||||
current_front.push_back(i);
|
current_front.push_back(i);
|
||||||
dominanceMap.remove(i); // remove from consideration
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
finished = false; // we need another go
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<unsigned> next_front;
|
||||||
|
next_front.reserve(_pop.size());
|
||||||
|
|
||||||
|
unsigned front_index = 0; // which front are we processing
|
||||||
|
while (!current_front.empty())
|
||||||
|
{
|
||||||
// Now we have the indices to the current front in current_front, do the niching
|
// Now we have the indices to the current front in current_front, do the niching
|
||||||
vector<double> niche_count = niche_penalty(current_front, _pop);
|
vector<double> niche_count = niche_penalty(current_front, _pop);
|
||||||
|
|
||||||
|
// Check whether the derived class was nice
|
||||||
if (niche_count.size() != current_front.size())
|
if (niche_count.size() != current_front.size())
|
||||||
{
|
{
|
||||||
throw logic_error("eoNDSorting: niche and front should have the same size");
|
throw logic_error("eoNDSorting: niche and front should have the same size");
|
||||||
|
|
@ -103,10 +127,28 @@ class eoNDSorting : public eoPerf2Worth<EOT, double>
|
||||||
|
|
||||||
for (unsigned i = 0; i < current_front.size(); ++i)
|
for (unsigned i = 0; i < current_front.size(); ++i)
|
||||||
{
|
{
|
||||||
value()[current_front[i]] = dominance_level + niche_count[i] / (max_niche + 1);
|
value()[current_front[i]] = front_index + niche_count[i] / (max_niche + 1.); // divide by max_niche + 1 to ensure that this front does not overlap with the next
|
||||||
}
|
}
|
||||||
|
|
||||||
dominance_level++; // go to the next front
|
// Calculate which individuals are in the next front;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < current_front.size(); ++i)
|
||||||
|
{
|
||||||
|
for (unsigned j = 0; j < S[current_front[i]].size(); ++j)
|
||||||
|
{
|
||||||
|
unsigned dominated_individual = S[current_front[i]][j];
|
||||||
|
n[dominated_individual]--; // As we remove individual i -- being part of the current front -- it no longer dominates j
|
||||||
|
|
||||||
|
if (n[dominated_individual] == 0) // it should be in the current front
|
||||||
|
{
|
||||||
|
next_front.push_back(dominated_individual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
front_index++; // go to the next front
|
||||||
|
swap(current_front, next_front); // make the next front current
|
||||||
|
next_front.clear(); // clear it for the next iteration
|
||||||
}
|
}
|
||||||
|
|
||||||
// now all that's left to do is to transform lower rank into higher worth
|
// now all that's left to do is to transform lower rank into higher worth
|
||||||
|
|
@ -115,15 +157,10 @@ class eoNDSorting : public eoPerf2Worth<EOT, double>
|
||||||
for (unsigned i = 0; i < value().size(); ++i)
|
for (unsigned i = 0; i < value().size(); ++i)
|
||||||
{
|
{
|
||||||
value()[i] = max_fitness - value()[i];
|
value()[i] = max_fitness - value()[i];
|
||||||
|
assert(n[i] == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const eoDominanceMap<EOT>& map() const;
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
eoDominanceMap<EOT>& dominanceMap;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -133,7 +170,7 @@ template <class EOT>
|
||||||
class eoNDSorting_I : public eoNDSorting<EOT>
|
class eoNDSorting_I : public eoNDSorting<EOT>
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
eoNDSorting_I(eoDominanceMap<EOT>& _map, double _nicheSize) : eoNDSorting<EOT>(_map), nicheSize(_nicheSize) {}
|
eoNDSorting_I(double _nicheSize) : eoNDSorting<EOT>(), nicheSize(_nicheSize) {}
|
||||||
|
|
||||||
vector<double> niche_penalty(const vector<unsigned>& current_front, const eoPop<EOT>& _pop)
|
vector<double> niche_penalty(const vector<unsigned>& current_front, const eoPop<EOT>& _pop)
|
||||||
{
|
{
|
||||||
|
|
@ -182,7 +219,6 @@ template <class EOT>
|
||||||
class eoNDSorting_II : public eoNDSorting<EOT>
|
class eoNDSorting_II : public eoNDSorting<EOT>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
eoNDSorting_II(eoDominanceMap<EOT>& _map) : eoNDSorting<EOT>(_map) {}
|
|
||||||
|
|
||||||
typedef std::pair<double, unsigned> double_index_pair;
|
typedef std::pair<double, unsigned> double_index_pair;
|
||||||
|
|
||||||
|
|
@ -222,9 +258,9 @@ class eoNDSorting_II : public eoNDSorting<EOT>
|
||||||
|
|
||||||
double max_dist = *max_element(nc.begin(), nc.end());
|
double max_dist = *max_element(nc.begin(), nc.end());
|
||||||
|
|
||||||
// set boundary penalty at 0 (so it will get chosen over all the others
|
// set boundary at max_dist + 1 (so it will get chosen over all the others
|
||||||
nc[performance[0].second] = 0;
|
nc[performance[0].second] = max_dist + 1;
|
||||||
nc[performance.back().second] = 0;
|
nc[performance.back().second] = max_dist + 1;
|
||||||
|
|
||||||
for (unsigned i = 0; i < nc.size(); ++i)
|
for (unsigned i = 0; i < nc.size(); ++i)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -56,12 +56,15 @@ class eoParetoFitness : public std::vector<double>
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
|
typedef FitnessTraits fitness_traits;
|
||||||
|
|
||||||
eoParetoFitness(void) : std::vector<double>(FitnessTraits::nObjectives(),0.0) {}
|
eoParetoFitness(void) : std::vector<double>(FitnessTraits::nObjectives(),0.0) {}
|
||||||
|
|
||||||
/// Partial order based on Pareto-dominance
|
/// Partial order based on Pareto-dominance
|
||||||
bool operator<(const eoParetoFitness<FitnessTraits>& _other) const
|
//bool operator<(const eoParetoFitness<FitnessTraits>& _other) const
|
||||||
|
bool dominates(const eoParetoFitness<FitnessTraits>& _other) const
|
||||||
{
|
{
|
||||||
bool smaller = false;
|
bool dom = false;
|
||||||
|
|
||||||
double tol = FitnessTraits::tol();
|
double tol = FitnessTraits::tol();
|
||||||
const vector<double>& performance = *this;
|
const vector<double>& performance = *this;
|
||||||
|
|
@ -75,17 +78,41 @@ public :
|
||||||
|
|
||||||
if (fabs(aval - bval) > tol)
|
if (fabs(aval - bval) > tol)
|
||||||
{
|
{
|
||||||
if (aval > bval)
|
if (aval < bval)
|
||||||
{
|
{
|
||||||
return false; // cannot dominate
|
return false; // cannot dominate
|
||||||
}
|
}
|
||||||
// else aval < bval
|
// else aval < bval
|
||||||
smaller = true; // goto next objective
|
dom = true; // for the moment: goto next objective
|
||||||
}
|
}
|
||||||
//else they're equal in this objective, goto next
|
//else they're equal in this objective, goto next
|
||||||
}
|
}
|
||||||
|
|
||||||
return smaller;
|
return dom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// compare *not* on dominance, but on the first, then the second, etc
|
||||||
|
bool operator<(const eoParetoFitness<FitnessTraits>& _other) const
|
||||||
|
{
|
||||||
|
double tol = FitnessTraits::tol();
|
||||||
|
const vector<double>& performance = *this;
|
||||||
|
const vector<double>& otherperformance = _other;
|
||||||
|
for (unsigned i = 0; i < FitnessTraits::nObjectives(); ++i)
|
||||||
|
{
|
||||||
|
bool maxim = FitnessTraits::maximizing(i);
|
||||||
|
double aval = maxim? performance[i] : -performance[i];
|
||||||
|
double bval = maxim? otherperformance[i] : -otherperformance[i];
|
||||||
|
|
||||||
|
if (fabs(aval-bval) > tol)
|
||||||
|
{
|
||||||
|
if (aval < bval)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator>(const eoParetoFitness<FitnessTraits>& _other) const
|
bool operator>(const eoParetoFitness<FitnessTraits>& _other) const
|
||||||
|
|
|
||||||
|
|
@ -37,17 +37,27 @@
|
||||||
on a single spot on the front.
|
on a single spot on the front.
|
||||||
*/
|
*/
|
||||||
template <class EOT>
|
template <class EOT>
|
||||||
class eoParetoRanking : public eoPerf2Worth<EOT, double>
|
class eoParetoRanking : public eoPerf2WorthCached<EOT, double>
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
eoParetoRanking(eoDominanceMap<EOT>& _dominanceMap) :
|
eoParetoRanking(eoDominanceMap<EOT>& _dominanceMap) :
|
||||||
eoPerf2Worth<EOT, double>(), dominanceMap(_dominanceMap) {}
|
eoPerf2WorthCached<EOT, double>(), dominanceMap(_dominanceMap) {}
|
||||||
|
|
||||||
void operator()(const eoPop<EOT>& _pop)
|
void calculate_worths(const eoPop<EOT>& _pop)
|
||||||
{
|
{
|
||||||
dominanceMap(_pop);
|
dominanceMap(_pop);
|
||||||
value() = dominanceMap.sum_dominants();
|
value() = dominanceMap.sum_dominators(); // get rank: 0 means part of current front
|
||||||
|
|
||||||
|
// calculate maximum
|
||||||
|
double maxim = *max_element(value().begin(), value().end());
|
||||||
|
|
||||||
|
// higher is better, so invert the value
|
||||||
|
for (unsigned i = 0; i < value().size(); ++i)
|
||||||
|
{
|
||||||
|
value()[i] = maxim - value()[i];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private :
|
private :
|
||||||
|
|
|
||||||
|
|
@ -27,22 +27,198 @@
|
||||||
#ifndef eoPerf2Worth_h
|
#ifndef eoPerf2Worth_h
|
||||||
#define eoPerf2Worth_h
|
#define eoPerf2Worth_h
|
||||||
|
|
||||||
#include <utils/eoStat.h>
|
#include <utils/eoParam.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
/** Base class to transform raw fitnesses into fitness for selection
|
/** Base class to transform raw fitnesses into fitness for selection
|
||||||
|
|
||||||
It is an eoStat so
|
|
||||||
- it is updated inside a checkpoint (i.e. at start of every generation)
|
|
||||||
- it can be monitored or whatever else you wish through its value()
|
|
||||||
|
|
||||||
@see eoSelectFromWorth
|
@see eoSelectFromWorth
|
||||||
*/
|
*/
|
||||||
template <class EOT, class WorthT = typename EOT::Fitness>
|
template <class EOT, class WorthT = double>
|
||||||
class eoPerf2Worth : public eoStat<EOT, vector<WorthT> >
|
class eoPerf2Worth : public eoUF<const eoPop<EOT>&, void>, public eoValueParam<vector<WorthT> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
eoPerf2Worth(std::string _description = "Worths"):eoStat<EOT, vector<WorthT> >(vector<WorthT>(0),
|
eoPerf2Worth(std::string _description = "Worths"):eoValueParam<vector<WorthT> >(vector<WorthT>(0),
|
||||||
_description) {}
|
_description) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sort population according to worth, will keep the worths and fitness_cache in sync with the population.
|
||||||
|
*/
|
||||||
|
virtual void sort_pop(eoPop<EOT>& _pop)
|
||||||
|
{ // start with a vector of indices
|
||||||
|
vector<unsigned> indices(_pop.size());
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < _pop.size();++i)
|
||||||
|
{ // could use generate, but who cares
|
||||||
|
indices[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
sort(indices.begin(), indices.end(), compare_worth(value()));
|
||||||
|
|
||||||
|
eoPop<EOT> tmp_pop;
|
||||||
|
tmp_pop.resize(_pop.size());
|
||||||
|
vector<WorthT> tmp_worths(value().size());
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < _pop.size(); ++i)
|
||||||
|
{
|
||||||
|
tmp_pop[i] = _pop[indices[i]];
|
||||||
|
tmp_worths[i] = value()[indices[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
swap(_pop, tmp_pop);
|
||||||
|
swap(value(), tmp_worths);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** helper class used to sort indices into populations/worths
|
||||||
|
*/
|
||||||
|
class compare_worth
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
compare_worth(const vector<WorthT>& _worths) : worths(_worths) {}
|
||||||
|
|
||||||
|
bool operator()(unsigned a, unsigned b) const
|
||||||
|
{
|
||||||
|
return worths[b] < worths[a]; // sort in descending (!) order
|
||||||
|
}
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
const vector<WorthT>& worths;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void resize(eoPop<EOT>& _pop, unsigned sz)
|
||||||
|
{
|
||||||
|
_pop.resize(sz);
|
||||||
|
value().resize(sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Perf2Worth with fitness cache
|
||||||
|
*/
|
||||||
|
template <class EOT, class WorthT = typename EOT::Fitness>
|
||||||
|
class eoPerf2WorthCached : public eoPerf2Worth<EOT, WorthT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
eoPerf2WorthCached(std::string _description = "Worths") : eoPerf2Worth<EOT, WorthT>(_description) {}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Implementation of the operator(), updating a cache of fitnesses. Calls the virtual function
|
||||||
|
calculate_worths when one of the fitnesses has changed. It is not virtual, but derived classes
|
||||||
|
can remove the fitness caching trough the third template element
|
||||||
|
*/
|
||||||
|
void operator()(const eoPop<EOT>& _pop)
|
||||||
|
{
|
||||||
|
if (fitness_cache.size() == _pop.size())
|
||||||
|
{
|
||||||
|
bool in_sync = true;
|
||||||
|
for (unsigned i = 0; i < _pop.size(); ++i)
|
||||||
|
{
|
||||||
|
if (fitness_cache[i] != _pop[i].fitness())
|
||||||
|
{
|
||||||
|
in_sync = false;
|
||||||
|
fitness_cache[i] = _pop[i].fitness();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_sync)
|
||||||
|
{ // worths are up to date
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // just cache the fitness
|
||||||
|
{
|
||||||
|
fitness_cache.resize(_pop.size());
|
||||||
|
for (unsigned i = 0; i < _pop.size(); ++i)
|
||||||
|
{
|
||||||
|
fitness_cache[i] = _pop[i].fitness();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// call derived implementation of perf2worth mapping
|
||||||
|
calculate_worths(_pop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The actual virtual function the derived classes should implement*/
|
||||||
|
virtual void calculate_worths(const eoPop<EOT>& _pop) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sort population according to worth, will keep the worths and fitness_cache in sync with the population.
|
||||||
|
*/
|
||||||
|
virtual void sort_pop(eoPop<EOT>& _pop)
|
||||||
|
{ // start with a vector of indices
|
||||||
|
vector<unsigned> indices(_pop.size());
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < _pop.size();++i)
|
||||||
|
{ // could use generate, but who cares
|
||||||
|
indices[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
sort(indices.begin(), indices.end(), eoPerf2Worth<EOT,WorthT>::compare_worth(value()));
|
||||||
|
|
||||||
|
eoPop<EOT> tmp_pop;
|
||||||
|
tmp_pop.resize(_pop.size());
|
||||||
|
vector<WorthT> tmp_worths(value().size());
|
||||||
|
vector<typename EOT::Fitness> tmp_cache(_pop.size());
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < _pop.size(); ++i)
|
||||||
|
{
|
||||||
|
tmp_pop[i] = _pop[indices[i]];
|
||||||
|
tmp_worths[i] = value()[indices[i]];
|
||||||
|
|
||||||
|
tmp_cache[i] = fitness_cache[indices[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
swap(_pop, tmp_pop);
|
||||||
|
swap(value(), tmp_worths);
|
||||||
|
swap(fitness_cache, tmp_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** helper class used to sort indices into populations/worths
|
||||||
|
*/
|
||||||
|
class compare_worth
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
compare_worth(const vector<WorthT>& _worths) : worths(_worths) {}
|
||||||
|
|
||||||
|
bool operator()(unsigned a, unsigned b) const
|
||||||
|
{
|
||||||
|
return worths[b] < worths[a]; // sort in descending (!) order
|
||||||
|
}
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
const vector<WorthT>& worths;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void resize(eoPop<EOT>& _pop, unsigned sz)
|
||||||
|
{
|
||||||
|
_pop.resize(sz);
|
||||||
|
value().resize(sz);
|
||||||
|
fitness_cache.resize(sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
private :
|
||||||
|
vector <typename EOT::Fitness> fitness_cache;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
A dummy perf2worth, just in case you need it
|
||||||
|
*/
|
||||||
|
template <class EOT>
|
||||||
|
class eoNoPerf2Worth : public eoPerf2Worth<EOT, typename EOT::Fitness>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// default behaviour, just copy fitnesses
|
||||||
|
void operator()(const eoPop<EOT>& _pop)
|
||||||
|
{
|
||||||
|
value.resize(_pop.size());
|
||||||
|
for (unsigned i = 0; i < _pop.size(); ++i)
|
||||||
|
value()[i]=_pop[i];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
* in between, the progression depends on exponent (linear if 1).
|
* in between, the progression depends on exponent (linear if 1).
|
||||||
*/
|
*/
|
||||||
template <class EOT>
|
template <class EOT>
|
||||||
class eoRanking : public eoPerf2Worth<EOT>
|
class eoRanking : public eoPerf2Worth<EOT> // false: do not cache fitness
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/* Ctor:
|
/* Ctor:
|
||||||
|
|
|
||||||
|
|
@ -37,13 +37,14 @@
|
||||||
|
|
||||||
@see eoSelectMany, eoSelectRandom, eoDetTournament, eoStochTournament, eoProportional
|
@see eoSelectMany, eoSelectRandom, eoDetTournament, eoStochTournament, eoProportional
|
||||||
*/
|
*/
|
||||||
template<class EOT>
|
template<class EOT, class WorthT = typename EOT::Fitness>
|
||||||
class eoSelectOne : public eoUF<const eoPop<EOT>&, const EOT&>
|
class eoSelectOne : public eoUF<const eoPop<EOT>&, const EOT&>
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
|
||||||
/// virtual function to setup some population stats (for instance eoProportional can benefit greatly from this)
|
/// virtual function to setup some population stats (for instance eoProportional can benefit greatly from this)
|
||||||
virtual void setup(const eoPop<EOT>&) {}
|
virtual void setup(const eoPop<EOT>& _pop)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Reference in a new issue