EO: added overloaded printing of fitness (for vectors and pairs)
Various bugs and ommissions in eoPerf2Worth and eoSelectFromWorth
This commit is contained in:
parent
492899bfb2
commit
4222e64829
4 changed files with 144 additions and 46 deletions
104
eo/src/EO.h
104
eo/src/EO.h
|
|
@ -31,56 +31,104 @@
|
||||||
#include <eoObject.h> // eoObject
|
#include <eoObject.h> // eoObject
|
||||||
#include <eoPersistent.h> // eoPersistent
|
#include <eoPersistent.h> // eoPersistent
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
ostream& print_fitness(ostream& _os, const std::vector<T>& vec)
|
||||||
|
{
|
||||||
|
_os << vec.size() << ' ';
|
||||||
|
std::copy(vec.begin(), vec.end(), ostream_iterator<T>(_os));
|
||||||
|
return _os;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
ostream& print_fitness(ostream& _os, const std::pair<T, U>& pair)
|
||||||
|
{
|
||||||
|
return _os << pair.first << ' ' << pair.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
ostream& print_fitness(ostream& _os, const T& t)
|
||||||
|
{ // general, try operator<<
|
||||||
|
return _os << t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
istream& read_fitness(istream& _is, vector<T>& vec)
|
||||||
|
{
|
||||||
|
unsigned sz;
|
||||||
|
_is >> sz;
|
||||||
|
vec.resize(sz);
|
||||||
|
for (unsigned i = 0; i < vec.size(); ++i)
|
||||||
|
{
|
||||||
|
_is >> vec[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _is;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
istream& read_fitness(istream& _is, pair<T, U>& pair)
|
||||||
|
{
|
||||||
|
_is >> pair.first;
|
||||||
|
_is >> pair.second;
|
||||||
|
return _is;
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
istream& read_fitness(istream& _is, T& t)
|
||||||
|
{
|
||||||
|
_is >> t;
|
||||||
|
return _is;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** EO is a base class for evolvable objects, that is, the subjects of
|
/** EO is a base class for evolvable objects, that is, the subjects of
|
||||||
evolution. EOs have only got a fitness, which at the same time needs to be
|
evolution. EOs have only got a fitness, which at the same time needs to be
|
||||||
only an object with the operation less than (<) defined. Fitness says how
|
only an object with the operation less than (<) defined. Fitness says how
|
||||||
good is the object; evolution or change of these objects is left to the
|
good is the object; evolution or change of these objects is left to the
|
||||||
genetic operators. A fitness less than another means a worse fitness, in
|
genetic operators. A fitness less than another means a worse fitness, in
|
||||||
whatever the context; thus, fitness is always maximized; although it can
|
whatever the context; thus, fitness is always maximized; although it can
|
||||||
be minimized with a proper definition of the < operator. The fitness
|
be minimized with a proper definition of the < operator. The fitness
|
||||||
object must have, besides an void ctor, a copy ctor.
|
object must have, besides an void ctor, a copy ctor.
|
||||||
*/
|
*/
|
||||||
template<class F> class EO: public eoObject, public eoPersistent
|
template<class F> class EO: public eoObject, public eoPersistent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef F Fitness;
|
typedef F Fitness;
|
||||||
|
|
||||||
/** Default constructor.
|
/** Default constructor.
|
||||||
Fitness must have a ctor which takes 0 as a value; we can not use void
|
Fitness must have a ctor which takes 0 as a value; we can not use void
|
||||||
ctors here since default types like float have no void initializer.
|
ctors here since default types like float have no void initializer.
|
||||||
VC++ allows it, but gcc does not
|
VC++ allows it, but gcc does not
|
||||||
*/
|
*/
|
||||||
EO(): repFitness(Fitness()), invalidFitness(true) {}
|
EO(): repFitness(Fitness()), invalidFitness(true) {}
|
||||||
|
|
||||||
/// Virtual dtor
|
/// Virtual dtor
|
||||||
virtual ~EO() {};
|
virtual ~EO() {};
|
||||||
|
|
||||||
/// Return fitness value.
|
/// Return fitness value.
|
||||||
Fitness fitness() const {
|
Fitness fitness() const {
|
||||||
if (invalid())
|
if (invalid())
|
||||||
throw runtime_error("invalid fitness");
|
throw runtime_error("invalid fitness");
|
||||||
return repFitness;
|
return repFitness;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set fitness as invalid.
|
// Set fitness as invalid.
|
||||||
void invalidate() { invalidFitness = true; }
|
void invalidate() { invalidFitness = true; }
|
||||||
|
|
||||||
/** Set fitness. At the same time, validates it.
|
/** Set fitness. At the same time, validates it.
|
||||||
* @param _fitness New fitness value.
|
* @param _fitness New fitness value.
|
||||||
*/
|
*/
|
||||||
void fitness(const Fitness& _fitness)
|
void fitness(const Fitness& _fitness)
|
||||||
{
|
{
|
||||||
repFitness = _fitness;
|
repFitness = _fitness;
|
||||||
invalidFitness = false;
|
invalidFitness = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return true If fitness value is invalid, false otherwise.
|
/** Return true If fitness value is invalid, false otherwise.
|
||||||
* @return true If fitness is invalid.
|
* @return true If fitness is invalid.
|
||||||
*/
|
*/
|
||||||
bool invalid() const { return invalidFitness; }
|
bool invalid() const { return invalidFitness; }
|
||||||
|
|
||||||
/** Returns true if
|
/** Returns true if
|
||||||
@return true if the fitness is higher
|
@return true if the fitness is higher
|
||||||
*/
|
*/
|
||||||
bool operator<(const EO& _eo2) const { return fitness() < _eo2.fitness(); }
|
bool operator<(const EO& _eo2) const { return fitness() < _eo2.fitness(); }
|
||||||
|
|
@ -88,28 +136,28 @@ public:
|
||||||
|
|
||||||
/// Methods inherited from eoObject
|
/// Methods inherited from eoObject
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
/** Return the class id.
|
/** Return the class id.
|
||||||
* @return the class name as a string
|
* @return the class name as a string
|
||||||
*/
|
*/
|
||||||
virtual string className() const { return "EO"; }
|
virtual string className() const { return "EO"; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read object.\\
|
* Read object.\\
|
||||||
* Calls base class, just in case that one had something to do.
|
* Calls base class, just in case that one had something to do.
|
||||||
* The read and print methods should be compatible and have the same format.
|
* The read and print methods should be compatible and have the same format.
|
||||||
* In principle, format is "plain": they just print a number
|
* In principle, format is "plain": they just print a number
|
||||||
* @param _is a istream.
|
* @param _is a istream.
|
||||||
* @throw runtime_exception If a valid object can't be read.
|
* @throw runtime_exception If a valid object can't be read.
|
||||||
*/
|
*/
|
||||||
virtual void readFrom(istream& _is) {
|
virtual void readFrom(istream& _is) {
|
||||||
_is >> repFitness;
|
read_fitness(_is, repFitness);
|
||||||
if (_is)
|
if (_is)
|
||||||
invalidFitness = false;
|
invalidFitness = false;
|
||||||
else
|
else
|
||||||
throw runtime_error("EO(istream&): can't read valid eo from istream");
|
throw runtime_error("EO(istream&): can't read valid eo from istream");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write object. Called printOn since it prints the object _on_ a stream.
|
* Write object. Called printOn since it prints the object _on_ a stream.
|
||||||
* @param _os A ostream.
|
* @param _os A ostream.
|
||||||
|
|
@ -118,11 +166,11 @@ public:
|
||||||
if (invalid())
|
if (invalid())
|
||||||
_os << "INVALID ";
|
_os << "INVALID ";
|
||||||
else
|
else
|
||||||
_os << repFitness << ' '; // trailing space to make reading in that much easier
|
print_fitness(_os, repFitness) << ' '; // trailing space to make reading in that much easier
|
||||||
}
|
}
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Fitness repFitness; // value of fitness for this chromosome
|
Fitness repFitness; // value of fitness for this chromosome
|
||||||
bool invalidFitness; // true if the value of fitness is invalid
|
bool invalidFitness; // true if the value of fitness is invalid
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@
|
||||||
#include <eoSteadyFitContinue.h>
|
#include <eoSteadyFitContinue.h>
|
||||||
#include <eoFitContinue.h>
|
#include <eoFitContinue.h>
|
||||||
|
|
||||||
// Selection
|
// Selection
|
||||||
// the eoSelectOne's
|
// the eoSelectOne's
|
||||||
#include <eoRandomSelect.h> // also contains the eoSequentialSelect
|
#include <eoRandomSelect.h> // also contains the eoSequentialSelect
|
||||||
#include <eoDetTournamentSelect.h>
|
#include <eoDetTournamentSelect.h>
|
||||||
|
|
@ -113,6 +113,9 @@
|
||||||
// a simple transformer
|
// a simple transformer
|
||||||
#include <eoSGATransform.h>
|
#include <eoSGATransform.h>
|
||||||
|
|
||||||
|
// Perf2Worth
|
||||||
|
#include <eoParetoRanking.h>
|
||||||
|
|
||||||
// Algorithms
|
// Algorithms
|
||||||
#include <eoEasyEA.h>
|
#include <eoEasyEA.h>
|
||||||
#include <eoSGA.h>
|
#include <eoSGA.h>
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ template <class EOT, class WorthT = typename EOT::Fitness>
|
||||||
class eoPerf2Worth : public eoStat<EOT, vector<WorthT> >
|
class eoPerf2Worth : public eoStat<EOT, vector<WorthT> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
eoPerf2Worth():eoStat<EOT, vector<WorthT> >(vector<WorthT>(0),
|
eoPerf2Worth(std::string _description = "Worths"):eoStat<EOT, vector<WorthT> >(vector<WorthT>(0),
|
||||||
"Worths") {}
|
_description) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -57,13 +57,35 @@ public:
|
||||||
perf2Worth(_perf2Worth) {}
|
perf2Worth(_perf2Worth) {}
|
||||||
|
|
||||||
/* setup the worthes */
|
/* setup the worthes */
|
||||||
virtual void setup(const eoPop<EOT>& _pop)
|
virtual void setup(const eoPop<EOT>& _pop)
|
||||||
{
|
{
|
||||||
perf2Worth(_pop);
|
perf2Worth(_pop);
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
fitness.resize(_pop.size());
|
||||||
|
for (unsigned i = 0; i < _pop.size(); ++i)
|
||||||
|
{
|
||||||
|
fitness[i] = _pop[i].fitness();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
eoPerf2Worth<EOT, WorthType> & perf2Worth;
|
eoPerf2Worth<EOT, WorthType> & perf2Worth;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
vector<typename EOT::Fitness> fitness; // for debugging purposes, to check that the perf2worth and pop are in sync
|
||||||
|
|
||||||
|
void check_sync(unsigned index, const EOT& _eo)
|
||||||
|
{
|
||||||
|
if (fitness[index] != _eo.fitness())
|
||||||
|
{
|
||||||
|
throw runtime_error("eoSelectFromWorth: fitnesses are not in sync");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -82,16 +104,24 @@ public:
|
||||||
unsigned _tSize) :
|
unsigned _tSize) :
|
||||||
eoSelectFromWorth<EOT, WorthT>(_perf2Worth), tSize(_tSize) {}
|
eoSelectFromWorth<EOT, WorthT>(_perf2Worth), tSize(_tSize) {}
|
||||||
|
|
||||||
/* Perform deterministic tournament on worthes
|
/* Perform deterministic tournament on worthes
|
||||||
by calling the appropriate fn
|
by calling the appropriate fn
|
||||||
see selectors.h
|
see selectors.h
|
||||||
*/
|
*/
|
||||||
virtual const EOT& operator()(const eoPop<EOT>& _pop)
|
virtual const EOT& operator()(const eoPop<EOT>& _pop)
|
||||||
{
|
{
|
||||||
worthIterator it = deterministic_tournament(
|
worthIterator it = deterministic_tournament(
|
||||||
perf2Worth.value().begin(),
|
perf2Worth.value().begin(),
|
||||||
perf2Worth.value().end(), tSize);
|
perf2Worth.value().end(), tSize);
|
||||||
return _pop[it-perf2Worth.value().begin()];
|
|
||||||
|
unsigned index = it - perf2Worth.value().begin();
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// check whether the stuff is still in sync
|
||||||
|
check_sync(index, _pop[index]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return _pop[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -99,7 +129,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
/** An instance of eoSelectPerf2Worth that does selection from the Worthes
|
/** An instance of eoSelectPerf2Worth that does selection from the Worthes
|
||||||
* using a ... determinisitic tournament, yes!
|
* using a ... stochastic tournament, yes!
|
||||||
*/
|
*/
|
||||||
template <class EOT, class WorthT = double>
|
template <class EOT, class WorthT = double>
|
||||||
class eoStochTournamentWorthSelect : public eoSelectFromWorth<EOT, WorthT>
|
class eoStochTournamentWorthSelect : public eoSelectFromWorth<EOT, WorthT>
|
||||||
|
|
@ -113,15 +143,23 @@ public:
|
||||||
double _tRate) :
|
double _tRate) :
|
||||||
eoSelectFromWorth<EOT, WorthT>(_perf2Worth), tRate(_tRate) {}
|
eoSelectFromWorth<EOT, WorthT>(_perf2Worth), tRate(_tRate) {}
|
||||||
|
|
||||||
/* Perform stochastic tournament on worthes
|
/* Perform stochastic tournament on worthes
|
||||||
by calling the appropriate fn in selectors.h
|
by calling the appropriate fn in selectors.h
|
||||||
*/
|
*/
|
||||||
virtual const EOT& operator()(const eoPop<EOT>& _pop)
|
virtual const EOT& operator()(const eoPop<EOT>& _pop)
|
||||||
{
|
{
|
||||||
worthIterator it = deterministic_tournament(
|
worthIterator it = stochastic_tournament(
|
||||||
perf2Worth.value().begin(),
|
perf2Worth.value().begin(),
|
||||||
perf2Worth.value().end(), tRate);
|
perf2Worth.value().end(), tRate);
|
||||||
return _pop[it-perf2Worth.value().begin()];
|
|
||||||
|
unsigned index = it - perf2Worth.value().begin();
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// check whether the stuff is still in sync
|
||||||
|
check_sync(index, _pop[index]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return _pop[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -145,25 +183,34 @@ public:
|
||||||
/* We have to override the default behavior to compute the total
|
/* We have to override the default behavior to compute the total
|
||||||
* only once!
|
* only once!
|
||||||
*/
|
*/
|
||||||
virtual void setup(const eoPop<EOT>& _pop)
|
virtual void setup(const eoPop<EOT>& _pop)
|
||||||
{
|
{
|
||||||
perf2Worth(_pop);
|
eoSelectFromWorth<EOT, WorthT>::setup(_pop);
|
||||||
total = 0.0;
|
total = 0.0;
|
||||||
for (worthIterator it = perf2Worth.value().begin();
|
for (worthIterator it = perf2Worth.value().begin();
|
||||||
it<perf2Worth.value().end(); ++it)
|
it<perf2Worth.value().end(); ++it)
|
||||||
total += (*it);
|
total += (*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform deterministic tournament on worthes
|
/* Perform deterministic tournament on worthes
|
||||||
by calling the appropriate fn
|
by calling the appropriate fn
|
||||||
see selectors.h
|
see selectors.h
|
||||||
*/
|
*/
|
||||||
virtual const EOT& operator()(const eoPop<EOT>& _pop)
|
virtual const EOT& operator()(const eoPop<EOT>& _pop)
|
||||||
{
|
{
|
||||||
worthIterator it = roulette_wheel(
|
worthIterator it = roulette_wheel(
|
||||||
perf2Worth.value().begin(),
|
perf2Worth.value().begin(),
|
||||||
perf2Worth.value().end(),
|
perf2Worth.value().end(),
|
||||||
total);
|
total);
|
||||||
|
|
||||||
|
unsigned index = it - perf2Worth.value().begin();
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// check whether the stuff is still in sync
|
||||||
|
check_sync(index, _pop[index]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return _pop[index];
|
||||||
return _pop[it-perf2Worth.value().begin()];
|
return _pop[it-perf2Worth.value().begin()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Reference in a new issue