Changed the populator to be a) more efficient and b) more useable

It is no longer derived from eoPop, it now gets a destination population.
This saves a lot of copying. The semantics has changed a little as well. It is
now an _infinite_ iterator. operator++ will *not* dispense new individuals, but
will merely stay at the end. To get a new indy, use operator*() as before.

eoEasyEA now checks the checkpoint *after* making a generation and clears the offspring
eoGeneralBreeder is changed to reflect the changes in eoPopulator
eoSequentialSelect now uses setup() rather than init()
This commit is contained in:
maartenkeijzer 2001-03-10 14:02:23 +00:00
commit ead2ac2c62
4 changed files with 88 additions and 57 deletions

View file

@ -114,11 +114,13 @@ template<class EOT> class eoEasyEA: public eoAlgo<EOT>
{ {
eoPop<EOT> offspring; eoPop<EOT> offspring;
while ( continuator( _pop ) ) do
{ {
try try
{ {
unsigned pSize = _pop.size(); unsigned pSize = _pop.size();
offspring.clear(); // new offspring
breed(_pop, offspring); breed(_pop, offspring);
apply<EOT>(eval, offspring); apply<EOT>(eval, offspring);
@ -137,7 +139,7 @@ template<class EOT> class eoEasyEA: public eoAlgo<EOT>
s.append( " in eoEasyEA"); s.append( " in eoEasyEA");
throw runtime_error( s ); throw runtime_error( s );
} }
} // while } while ( continuator( _pop ) );
} }
private: private:

View file

@ -69,17 +69,15 @@ class eoGeneralBreeder: public eoBreed<EOT>
{ {
unsigned target = howMany(_parents.size()); unsigned target = howMany(_parents.size());
eoSelectivePopulator<EOT> it(_parents, select); _offspring.clear();
eoSelectivePopulator<EOT> it(_parents, _offspring, select);
select.setup(_parents); while (_offspring.size() < target)
{
op(it);
++it;
}
while (it.size() < target)
{
op(it);
++it;
}
swap(_offspring, it);
_offspring.resize(target); // you might have generated a few more _offspring.resize(target); // you might have generated a few more
} }

View file

@ -36,11 +36,15 @@
See eoGenOp and eoOpContainer See eoGenOp and eoOpContainer
*/ */
template <class EOT> template <class EOT>
class eoPopulator : public eoPop<EOT> class eoPopulator
{ {
public : public :
eoPopulator(const eoPop<EOT>& _src) : current(begin()), src(_src) {} eoPopulator(const eoPop<EOT>& _src, eoPop<EOT>& _dest) : dest(_dest), current(dest.end()), src(_src)
{
dest.reserve(src.size()); // we don't know this, but wth.
current = dest.end();
}
struct OutOfIndividuals {}; struct OutOfIndividuals {};
@ -50,24 +54,20 @@ public :
*/ */
EOT& operator*(void) EOT& operator*(void)
{ {
if (current == end()) if (current == dest.end())
operator++(); get_next(); // get a new individual
return *current; return *current;
} }
/** only prefix increment defined /** only prefix increment defined
* if needed, adds a new individual using the embedded selector Does not add a new element when at the end, use operator* for that
* and set the current pointer to the newly inserted individual If not on the end, increment the pointer to the next individual
* otherwise simply increment the current pointer
*/ */
eoPopulator& operator++() eoPopulator& operator++()
{ {
if (current == end()) if (current == dest.end())
{ // get new individual from derived class select() { // keep the pointer there
push_back(select());
current = end();
--current;
return *this; return *this;
} }
// else // else
@ -80,40 +80,66 @@ public :
*/ */
void insert(const EOT& _eo) void insert(const EOT& _eo)
{ /* not really efficient, but its nice to have */ { /* not really efficient, but its nice to have */
current = eoPop<EOT>::insert(current, _eo); current = dest.insert(current, _eo);
} }
/** just to make memory mangement more efficient /** just to make memory mangement more efficient
*/ */
void reserve(int how_many) void reserve(int how_many)
{ {
size_t sz = current - begin(); size_t sz = current - dest.begin();
eoPop<EOT>::reserve(size() + how_many); if (dest.capacity() < dest.size() + how_many)
current = begin() + sz; {
dest.reserve(dest.size() + how_many);
}
current = dest.begin() + sz;
} }
/** can be useful for operators with embedded selectors /** can be useful for operators with embedded selectors
* e.g. your barin and my beauty -type * e.g. your brain and my beauty -type
*/ */
const eoPop<EOT>& source(void) { return src; } const eoPop<EOT>& source(void) { return src; }
/** Get the offspring population.
Can be useful when you want to do some online niching kind of thing
*/
eoPop<EOT>& offspring(void) { return dest; }
typedef unsigned position_type; typedef unsigned position_type;
/** this is a direct access container: tell position */ /** this is a direct access container: tell position */
position_type tellp() { return current - begin(); } position_type tellp() { return current - dest.begin(); }
/** this is a direct access container: go to position */ /** this is a direct access container: go to position */
void seekp(position_type pos) { current = begin() + pos; } void seekp(position_type pos) { current = dest.begin() + pos; }
/** no more individuals */ /** no more individuals */
bool exhausted(void) { return current == end(); } bool exhausted(void) { return current == dest.end(); }
virtual const EOT& select() = 0;
protected :
/** the pure virtual selection method - will be instanciated in /** the pure virtual selection method - will be instanciated in
* eoSeqPopulator and eoPropPopulator * eoSeqPopulator and eoPropPopulator
*/ */
virtual const EOT& select() = 0;
protected :
eoPop<EOT>& dest;
eoPop<EOT>::iterator current; eoPop<EOT>::iterator current;
const eoPop<EOT>& src; const eoPop<EOT>& src;
private :
void get_next()
{
if (current == dest.end())
{ // get new individual from derived class select()
dest.push_back(select());
current = dest.end();
--current;
return;
}
// else
++current;
return;
}
}; };
@ -125,22 +151,22 @@ class eoSeqPopulator : public eoPopulator<EOT>
{ {
public : public :
eoSeqPopulator(const eoPop<EOT>& _pop) : eoSeqPopulator(const eoPop<EOT>& _pop, eoPop<EOT>& _dest) :
eoPopulator<EOT>(_pop), src_it(_pop.begin()) {} eoPopulator<EOT>(_pop, _dest), current(0) {}
const EOT& select(void) const EOT& select(void)
{ {
if (src_it == src.end()) if (current >= src.size())
{ {
throw OutOfIndividuals(); throw OutOfIndividuals();
} }
const EOT& res = *src_it++; const EOT& res = src[current++];
return res; return res;
} }
private : private :
vector<EOT>::const_iterator src_it; unsigned current;
}; };
@ -151,8 +177,11 @@ template <class EOT>
class eoSelectivePopulator : public eoPopulator<EOT> class eoSelectivePopulator : public eoPopulator<EOT>
{ {
public : public :
eoSelectivePopulator(const eoPop<EOT>& _pop, eoSelectOne<EOT>& _sel) eoSelectivePopulator(const eoPop<EOT>& _pop, eoPop<EOT>& _dest, eoSelectOne<EOT>& _sel)
: eoPopulator<EOT>(_pop), sel(_sel) {} : eoPopulator<EOT>(_pop, _dest), sel(_sel)
{
sel.setup(_pop);
}
const EOT& select() const EOT& select()
{ {

View file

@ -87,10 +87,11 @@ template <class EOT> class eoSequentialSelect: public eoSelectOne<EOT>
eoSequentialSelect(bool _ordered = true): eoSequentialSelect(bool _ordered = true):
ordered(_ordered), current(MAXINT) {} ordered(_ordered), current(MAXINT) {}
void init(const eoPop<EOT>& _pop) void setup(const eoPop<EOT>& _pop)
{ {
eoPters.resize(_pop.size());
if (ordered) // probably we could have a marker to avoid re-sorting if (ordered) // probably we could have a marker to avoid re-sorting
_pop.sort(eoPters); _pop.sort(eoPters);
else else
_pop.shuffle(eoPters); _pop.shuffle(eoPters);
current=0; current=0;
@ -99,7 +100,8 @@ template <class EOT> class eoSequentialSelect: public eoSelectOne<EOT>
virtual const EOT& operator()(const eoPop<EOT>& _pop) virtual const EOT& operator()(const eoPop<EOT>& _pop)
{ {
if (current >= _pop.size()) if (current >= _pop.size())
init(_pop); setup(_pop);
unsigned eoN = current; unsigned eoN = current;
current++; current++;
return *eoPters[eoN] ; return *eoPters[eoN] ;