This repository has been archived on 2026-03-28. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
eodev/eo/src/eoPerf2Worth.h
2010-11-05 15:59:35 +01:00

255 lines
6.6 KiB
C++

/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoPerf2Worth.h
(c) Maarten Keijzer, Marc Schoenauer, 2001
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
Marc.Schoenauer@polytechnique.fr
mkeijzer@dhi.dk
*/
//-----------------------------------------------------------------------------
#ifndef eoPerf2Worth_h
#define eoPerf2Worth_h
#include <utils/eoParam.h>
#include <eoPop.h>
#include <eoFunctor.h>
#include <algorithm>
#include <vector>
#include <string>
/** @brief Base class to transform raw fitnesses into fitness for selection
@see eoSelectFromWorth
@ingroup Selectors
@ingroup Utilities
*/
template <class EOT, class WorthT = double>
class eoPerf2Worth : public eoUF<const eoPop<EOT>&, void>, public eoValueParam<std::vector<WorthT> >
{
public:
using eoValueParam<std::vector<WorthT> >::value;
/** @brief default constructor */
eoPerf2Worth(std::string _description = "Worths")
: eoValueParam<std::vector<WorthT> >(std::vector<WorthT>(0), _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 std::vector of indices
std::vector<unsigned> indices(_pop.size());
unsigned i;
for (i = 0; i < _pop.size();++i)
{ // could use generate, but who cares
indices[i] = i;
}
std::sort(indices.begin(), indices.end(), compare_worth(value()));
eoPop<EOT> tmp_pop;
tmp_pop.resize(_pop.size());
std::vector<WorthT> tmp_worths(value().size());
for (i = 0; i < _pop.size(); ++i)
{
tmp_pop[i] = _pop[indices[i]];
tmp_worths[i] = value()[indices[i]];
}
std::swap(_pop, tmp_pop);
std::swap(value(), tmp_worths);
}
/** helper class used to sort indices into populations/worths */
class compare_worth
{
public:
compare_worth(const std::vector<WorthT>& _worths) : worths(_worths) {}
bool operator()(unsigned a, unsigned b) const {
return worths[b] < worths[a]; // sort in descending (!) order
}
private:
const std::vector<WorthT>& worths;
};
virtual void resize(eoPop<EOT>& _pop, unsigned sz) {
_pop.resize(sz);
value().resize(sz);
};
};
/**
Perf2Worth with fitness cache
@ingroup Selectors
@ingroup Utilities
*/
template <class EOT, class WorthT = typename EOT::Fitness>
class eoPerf2WorthCached : public eoPerf2Worth<EOT, WorthT>
{
public:
using eoPerf2Worth<EOT, WorthT>::value;
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)
{
unsigned i;
if (fitness_cache.size() == _pop.size())
{
bool in_sync = true;
for (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 (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 std::vector of indices
std::vector<unsigned> indices(_pop.size());
unsigned i;
for (i = 0; i < _pop.size();++i)
{ // could use generate, but who cares
indices[i] = i;
}
std::sort(indices.begin(), indices.end(), compare_worth(value()));
eoPop<EOT> tmp_pop;
tmp_pop.resize(_pop.size());
std::vector<WorthT> tmp_worths(value().size());
#ifdef _MSC_VER
std::vector<EOT::Fitness> tmp_cache(_pop.size());
#else
std::vector<typename EOT::Fitness> tmp_cache(_pop.size());
#endif
for (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]];
}
std::swap(_pop, tmp_pop);
std::swap(value(), tmp_worths);
std::swap(fitness_cache, tmp_cache);
}
/** helper class used to sort indices into populations/worths
*/
class compare_worth
{
public :
compare_worth(const std::vector<WorthT>& _worths) : worths(_worths) {}
bool operator()(unsigned a, unsigned b) const
{
return worths[b] < worths[a]; // sort in descending (!) order
}
private :
const std::vector<WorthT>& worths;
};
virtual void resize(eoPop<EOT>& _pop, unsigned sz)
{
_pop.resize(sz);
value().resize(sz);
fitness_cache.resize(sz);
}
private :
std::vector <typename EOT::Fitness> fitness_cache;
};
/** A dummy perf2worth, just in case you need it
@ingroup Selectors
@ingroup Utilities
*/
template <class EOT>
class eoNoPerf2Worth : public eoPerf2Worth<EOT, typename EOT::Fitness>
{
public:
using eoValueParam< EOT >::value;
// default behaviour, just copy fitnesses
void operator()(const eoPop<EOT>& _pop) {
unsigned i;
value().resize(_pop.size());
for (i = 0; i < _pop.size(); ++i)
value()[i]=_pop[i];
}
};
#endif