diff --git a/eo/src/EO.h b/eo/src/EO.h index 34e216fe..8158cb40 100644 --- a/eo/src/EO.h +++ b/eo/src/EO.h @@ -31,56 +31,104 @@ #include // eoObject #include // eoPersistent +template +ostream& print_fitness(ostream& _os, const std::vector& vec) +{ + _os << vec.size() << ' '; + std::copy(vec.begin(), vec.end(), ostream_iterator(_os)); + return _os; +} + +template +ostream& print_fitness(ostream& _os, const std::pair& pair) +{ + return _os << pair.first << ' ' << pair.second; +} + +template +ostream& print_fitness(ostream& _os, const T& t) +{ // general, try operator<< + return _os << t; +} + +template +istream& read_fitness(istream& _is, vector& vec) +{ + unsigned sz; + _is >> sz; + vec.resize(sz); + for (unsigned i = 0; i < vec.size(); ++i) + { + _is >> vec[i]; + } + + return _is; +} + +template +istream& read_fitness(istream& _is, pair& pair) +{ + _is >> pair.first; + _is >> pair.second; + return _is; +} +template +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 - 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 - genetic operators. A fitness less than another means a worse fitness, in - whatever the context; thus, fitness is always maximized; although it can - be minimized with a proper definition of the < operator. The fitness + 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 + genetic operators. A fitness less than another means a worse fitness, in + whatever the context; thus, fitness is always maximized; although it can + be minimized with a proper definition of the < operator. The fitness object must have, besides an void ctor, a copy ctor. */ template class EO: public eoObject, public eoPersistent { public: typedef F Fitness; - + /** Default constructor. - 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. + 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. VC++ allows it, but gcc does not */ EO(): repFitness(Fitness()), invalidFitness(true) {} - + /// Virtual dtor virtual ~EO() {}; - + /// Return fitness value. Fitness fitness() const { if (invalid()) throw runtime_error("invalid fitness"); return repFitness; } - + // Set fitness as invalid. void invalidate() { invalidFitness = true; } - + /** Set fitness. At the same time, validates it. * @param _fitness New fitness value. */ void fitness(const Fitness& _fitness) - { + { repFitness = _fitness; invalidFitness = false; } - + /** Return true If fitness value is invalid, false otherwise. * @return true If fitness is invalid. */ bool invalid() const { return invalidFitness; } - - /** Returns true if + + /** Returns true if @return true if the fitness is higher */ bool operator<(const EO& _eo2) const { return fitness() < _eo2.fitness(); } @@ -88,28 +136,28 @@ public: /// Methods inherited from eoObject //@{ - - /** Return the class id. + + /** Return the class id. * @return the class name as a string */ virtual string className() const { return "EO"; } - + /** * Read object.\\ - * 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. + * 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. * In principle, format is "plain": they just print a number * @param _is a istream. * @throw runtime_exception If a valid object can't be read. */ - virtual void readFrom(istream& _is) { - _is >> repFitness; + virtual void readFrom(istream& _is) { + read_fitness(_is, repFitness); if (_is) invalidFitness = false; else throw runtime_error("EO(istream&): can't read valid eo from istream"); } - + /** * Write object. Called printOn since it prints the object _on_ a stream. * @param _os A ostream. @@ -118,11 +166,11 @@ public: if (invalid()) _os << "INVALID "; 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: Fitness repFitness; // value of fitness for this chromosome bool invalidFitness; // true if the value of fitness is invalid diff --git a/eo/src/eo b/eo/src/eo index 54c4caf1..bc8ed068 100644 --- a/eo/src/eo +++ b/eo/src/eo @@ -81,7 +81,7 @@ #include #include -// Selection +// Selection // the eoSelectOne's #include // also contains the eoSequentialSelect #include @@ -113,6 +113,9 @@ // a simple transformer #include +// Perf2Worth +#include + // Algorithms #include #include diff --git a/eo/src/eoPerf2Worth.h b/eo/src/eoPerf2Worth.h index d27bcd1c..3ad20358 100644 --- a/eo/src/eoPerf2Worth.h +++ b/eo/src/eoPerf2Worth.h @@ -41,8 +41,8 @@ template class eoPerf2Worth : public eoStat > { public: - eoPerf2Worth():eoStat >(vector(0), - "Worths") {} + eoPerf2Worth(std::string _description = "Worths"):eoStat >(vector(0), + _description) {} }; #endif diff --git a/eo/src/eoSelectFromWorth.h b/eo/src/eoSelectFromWorth.h index 29520ceb..a115f8b4 100644 --- a/eo/src/eoSelectFromWorth.h +++ b/eo/src/eoSelectFromWorth.h @@ -57,13 +57,35 @@ public: perf2Worth(_perf2Worth) {} /* setup the worthes */ - virtual void setup(const eoPop& _pop) + virtual void setup(const eoPop& _pop) { perf2Worth(_pop); + +#ifndef NDEBUG + fitness.resize(_pop.size()); + for (unsigned i = 0; i < _pop.size(); ++i) + { + fitness[i] = _pop[i].fitness(); + } +#endif } protected: eoPerf2Worth & perf2Worth; + +#ifndef NDEBUG + vector 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) : eoSelectFromWorth(_perf2Worth), tSize(_tSize) {} - /* Perform deterministic tournament on worthes - by calling the appropriate fn + /* Perform deterministic tournament on worthes + by calling the appropriate fn see selectors.h */ - virtual const EOT& operator()(const eoPop& _pop) + virtual const EOT& operator()(const eoPop& _pop) { worthIterator it = deterministic_tournament( perf2Worth.value().begin(), 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: @@ -99,7 +129,7 @@ private: }; /** An instance of eoSelectPerf2Worth that does selection from the Worthes - * using a ... determinisitic tournament, yes! + * using a ... stochastic tournament, yes! */ template class eoStochTournamentWorthSelect : public eoSelectFromWorth @@ -113,15 +143,23 @@ public: double _tRate) : eoSelectFromWorth(_perf2Worth), tRate(_tRate) {} - /* Perform stochastic tournament on worthes + /* Perform stochastic tournament on worthes by calling the appropriate fn in selectors.h */ - virtual const EOT& operator()(const eoPop& _pop) + virtual const EOT& operator()(const eoPop& _pop) { - worthIterator it = deterministic_tournament( + worthIterator it = stochastic_tournament( perf2Worth.value().begin(), 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: @@ -145,25 +183,34 @@ public: /* We have to override the default behavior to compute the total * only once! */ - virtual void setup(const eoPop& _pop) + virtual void setup(const eoPop& _pop) { - perf2Worth(_pop); + eoSelectFromWorth::setup(_pop); total = 0.0; for (worthIterator it = perf2Worth.value().begin(); it& _pop) + virtual const EOT& operator()(const eoPop& _pop) { worthIterator it = roulette_wheel( perf2Worth.value().begin(), perf2Worth.value().end(), 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()]; }