THe big eoReplacement update:

The interface for eoReplacement is now eoPop<EOT>&, eoPop<EOT>&
(i.e. no const) and the result must be in the first argument in the end.

Hence it is possible to do SSGA and all intermediate replacmeent procedures

The classes derived from eoMergeReduce.h are now in a separate file
The SSGA-like replcaement procedures are in eoReduceMerge.h
A more general replacement can be found in eoSurviveAndDie.h
(it could be made a littel more general - still open for upgrades).

Also some accessors have been added to the eoPop (best and worse individuals)

And include file eo has been updated
This commit is contained in:
evomarc 2000-12-19 18:41:19 +00:00
commit 6acdcb6d9b
12 changed files with 902 additions and 96 deletions

View file

@ -4,7 +4,7 @@
##
###############################################################################
SUBDIRS = es ga gp utils other
SUBDIRS = es ga utils other
CPPFLAGS = -O2
lib_LIBRARIES = libeo.a

View file

@ -30,8 +30,20 @@
// some defines to make things easier to get at first sight
// tunigni the amount of output using a boolean argument:
// true should always mean more output
#define eo_verbose true
#define eo_no_verbose false
// to be used in selection / replacement procedures to indicate whether
// the argument (rate, a double) shoudl be treated as a rate (number=rate*popSize)
// or as an absolute integer (number=rate regardless of popsize).
// the default value shoudl ALWAYS be true (eo_as_a_rate).
//
// this construct is mandatory because in some cases you might not know the
// population size that will enter the replacement for instance - so you
// cannot simply have a pre-computed (double) rate of 1/popSize
#define eo_is_a_rate true
#define eo_is_an_integer false
//-----------------------------------------------------------------------------
#include <utils/eoData.h>
@ -86,13 +98,24 @@
#include <eoSteadyFitContinue.h>
#include <eoFitContinue.h>
// Selection and reproduction stuff
// Selection
#include <eoSelectOne.h>
#include <eoSelectRandom.h>
#include <eoDetTournament.h>
#include <eoProportional.h>
#include <eoStochTournament.h>
#include <eoSelectPerc.h>
#include <eoSelectNumber.h>
#include <eoSelectMany.h>
// Replacement
// #include <eoReplacement.h>
#include <eoMergeReduce.h>
#include <eoReduceMerge.h>
#include <eoSurviveAndDie.h>
// Variation
#include <eoProportionalCombinedOp.h>
#include <eoProportionalOpSel.h>
#include <eoProportionalGOpSel.h>

View file

@ -119,24 +119,23 @@ template<class EOT> class eoEasyEA: public eoAlgo<EOT>
{
try
{
unsigned pSize = _pop.size();
breed(_pop, offspring);
apply<EOT>(eval, offspring);
replace(_pop, offspring);
if (offspring.size() < _pop.size())
replace(_pop, offspring); // after replace, the new pop. is in _pop
if (pSize > _pop.size())
throw runtime_error("Population shrinking!");
else if (offspring.size() > _pop.size())
else if (pSize < _pop.size())
throw runtime_error("Population growing!");
_pop.swap(offspring);
}
catch (exception& e)
{
string s = e.what();
s.append( " in eoSelectTransformReduce ");
s.append( " in eoEasyEA");
throw runtime_error( s );
}
} // while

View file

@ -50,32 +50,55 @@ template<class Chrom> class eoMerge: public eoBF<const eoPop<Chrom>&, eoPop<Chro
/**
Straightforward elitism class, specify the number of individuals to copy
into new geneneration
into new geneneration or the rate w.r.t. pop size
*/
template <class EOT> class eoElitism : public eoMerge<EOT>
{
public :
eoElitism(unsigned _howmany) : howmany(_howmany) {}
void operator()(const eoPop<EOT>& _pop, eoPop<EOT>& offspring)
{
if (howmany == 0)
return;
if (howmany > _pop.size())
throw std::logic_error("Elite larger than population");
vector<const EOT*> result;
_pop.nth_element(howmany, result);
for (size_t i = 0; i < result.size(); ++i)
{
offspring.push_back(*result[i]);
}
}
private :
unsigned howmany;
public :
eoElitism(double _rate, bool _interpret_as_rate = true):
rate(0), howmany(0)
{
if (_interpret_as_rate)
{
if ( (_rate<0) || (_rate>1) )
throw std::logic_error("eoElitism: rate shoud be in [0,1]");
rate = _rate;
}
else
{
if (_rate<0)
throw std::logic_error("Negative number of offspring in eoElitism!");
howmany = (unsigned int)_rate;
if (howmany != _rate)
cout << "Warning: Number of guys to merge in eoElitism was rounded";
}
}
void operator()(const eoPop<EOT>& _pop, eoPop<EOT>& _offspring)
{
if ((howmany == 0) && (rate == 0.0))
return;
unsigned howmanyLocal;
if (howmany == 0) // rate is specified
howmanyLocal = (unsigned int) (rate * _pop.size());
else
howmanyLocal = howmany;
if (howmanyLocal > _pop.size())
throw std::logic_error("Elite larger than population");
vector<const EOT*> result;
_pop.nth_element(howmanyLocal, result);
for (size_t i = 0; i < result.size(); ++i)
{
_offspring.push_back(*result[i]);
}
}
private :
double rate;
unsigned howmany;
};
/**
@ -93,18 +116,17 @@ Very elitist class, copies entire population into next gen
template <class EOT> class eoPlus : public eoMerge<EOT>
{
public :
void operator()(const eoPop<EOT>& _pop, eoPop<EOT>& offspring)
void operator()(const eoPop<EOT>& _pop, eoPop<EOT>& _offspring)
{
offspring.reserve(offspring.size() + _pop.size());
_offspring.reserve(_offspring.size() + _pop.size());
for (size_t i = 0; i < _pop.size(); ++i)
{
offspring.push_back(_pop[i]);
_offspring.push_back(_pop[i]);
}
}
private :
unsigned howmany;
};
//-----------------------------------------------------------------------------

98
eo/src/eoMergeReduce.h Normal file
View file

@ -0,0 +1,98 @@
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoMergeReduce.h
(c) Maarten Keijzer, GeNeura Team, 2000
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
*/
//-----------------------------------------------------------------------------
#ifndef _eoMergeReduce_h
#define _eoMergeReduce_h
//-----------------------------------------------------------------------------
#include <eoPop.h>
#include <eoFunctor.h>
#include <eoMerge.h>
#include <eoReduce.h>
#include <eoReplacement.h>
#include <utils/eoHowMany.h>
//-----------------------------------------------------------------------------
/**
Replacement strategies that combine en eoMerge and an eoReduce.
@classes: eoMergeReduce, the base (pure abstract) class
eoPlusReplacement the ES plus strategy
eoCommaReplacement the ES comma strategy
*/
/**
eoMergeReduce: abstract replacement strategy that is just an application of
an embedded merge, followed by an embedded reduce
*/
template <class EOT>
class eoMergeReduce : public eoReplacement<EOT>
{
public:
eoMergeReduce(eoMerge<EOT>& _merge, eoReduce<EOT>& _reduce) :
merge(_merge), reduce(_reduce)
{}
void operator()(eoPop<EOT>& _parents, eoPop<EOT>& _offspring)
{
merge(_parents, _offspring); // parents untouched, result in offspring
reduce(_offspring, _parents.size());
_parents.swap(_offspring);
}
private :
eoMerge<EOT>& merge;
eoReduce<EOT>& reduce;
};
/**
ES type of replacement strategy: first add parents to population, then truncate
*/
template <class EOT>
class eoPlusReplacement : public eoMergeReduce<EOT>
{
public :
eoPlusReplacement() : eoMergeReduce<EOT>(plus, truncate) {}
private :
eoPlus<EOT> plus;
eoTruncate<EOT> truncate;
};
/**
ES type of replacement strategy: ignore parents, truncate offspring
*/
template <class EOT>
class eoCommaReplacement : public eoMergeReduce<EOT>
{
public :
eoCommaReplacement() : eoMergeReduce<EOT>(no_elite, truncate) {}
private :
eoNoElitism<EOT> no_elite;
eoTruncate<EOT> truncate;
};
#endif

View file

@ -123,6 +123,7 @@ class eoPop: public vector<EOT>, public eoObject, public eoPersistent
std::sort(begin(), end(), greater<EOT>());
}
// creates a vector<EOT*> pointing to the individuals in descending order
void sort(vector<const EOT*>& result) const
{
result.resize(size());
@ -132,9 +133,37 @@ class eoPop: public vector<EOT>, public eoObject, public eoPersistent
std::sort(result.begin(), result.end(), Cmp());
}
// returns an iterator to the best individual DOES NOT MOVE ANYBODY
eoPop<EOT>::iterator it_best_element()
{
typename eoPop<EOT>::const_iterator it = max_element(begin(), end());
return it;
}
// returns an iterator to the best individual DOES NOT MOVE ANYBODY
const EOT & best_element() const
{
typename eoPop<EOT>::const_iterator it = max_element(begin(), end());
return (*it);
}
// returns a const reference to the worse individual DOES NOT MOVE ANYBODY
const EOT & worse_element() const
{
typename eoPop<EOT>::const_iterator it = min_element(begin(), end());
return (*it);
}
// returns an iterator to the worse individual DOES NOT MOVE ANYBODY
eoPop<EOT>::iterator it_worse_element()
{
typename eoPop<EOT>::iterator it = min_element(begin(), end());
return it;
}
/**
slightly faster algorithm than sort to find all individuals that are better
than the nth individual
than the nth individual. INDIVIDUALS ARE MOVED AROUND in the pop.
*/
eoPop<EOT>::iterator nth_element(int nth)
{
@ -168,6 +197,7 @@ class eoPop: public vector<EOT>, public eoObject, public eoPersistent
std::nth_element(result.begin(), it, result.end(), Cmp());
}
// does STL swap with other pop
void swap(eoPop<EOT>& other)
{
std::swap(static_cast<vector<EOT>& >(*this), static_cast<vector<EOT>& >(other));

View file

@ -33,26 +33,199 @@
// EO includes
#include <eoPop.h> // eoPop
#include <eoFunctor.h> // eoReduce
#include <utils/selectors.h>
/**
* eoReduce: .reduce the new generation to the specified size
At the moment, limited to truncation - with 2 different methods,
one that sorts the whole population, and one that repeatidely kills
the worst. Ideally, we should be able to choose at run-time!!!
*/
template<class Chrom> class eoReduce: public eoBF<eoPop<Chrom>&, unsigned, void>
template<class EOT> class eoReduce: public eoBF<eoPop<EOT>&, unsigned, void>
{};
/** truncation method using sort */
template <class EOT> class eoTruncate : public eoReduce<EOT>
{
void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
{
if (_newgen.size() == _newsize)
return;
if (_newgen.size() < _newsize)
throw std::logic_error("eoTruncate: Cannot truncate to a larger size!\n");
_newgen.nth_element(_newsize);
_newgen.resize(_newsize);
}
};
/**
EP truncation method (some global stochastic tournament + sort)
Softer selective pressure than pure truncate
*/
template <class EOT> class eoEPReduce : public eoReduce<EOT>
{
public:
typedef typename EOT::Fitness Fitness;
eoEPReduce(unsigned _t_size):
t_size(_t_size)
{
if (t_size < 2)
{ // warning, error?
t_size = 2;
}
}
/// helper struct for comparing on pairs
typedef pair<float, eoPop<EOT>::iterator> EPpair;
struct Cmp {
bool operator()(const EPpair a, const EPpair b) const
{ return b.first < a.first; }
};
void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
{
unsigned int presentSize = _newgen.size();
if (presentSize == _newsize)
return;
if (presentSize < _newsize)
throw std::logic_error("eoTruncate: Cannot truncate to a larger size!\n");
vector<EPpair> scores(presentSize);
for (unsigned i=0; i<presentSize; i++)
{
scores[i].second = _newgen.begin()+i;
Fitness fit = _newgen[i].fitness();
for (unsigned itourn = 0; itourn < t_size; ++itourn)
{
const EOT & competitor = _newgen[rng.random(presentSize)];
if (fit > competitor.fitness())
scores[i].first += 1;
else if (fit == competitor.fitness())
scores[i].first += 0.5;
}
}
// now we have the scores
typename vector<EPpair>::iterator it = scores.begin() + _newsize;
std::nth_element(scores.begin(), it, scores.end(), Cmp());
it = scores.begin() + _newsize; // just in case ???
while (it < scores.end())
_newgen.erase(it->second);
}
private:
unsigned t_size;
};
/** a truncate class that does not sort, but repeatidely kills the worse.
To be used in SSGA-like replacements (e.g. see eoSSGAWorseReplacement)
*/
template <class EOT>
class eoLinearTruncate : public eoReduce<EOT>
{
void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
{
unsigned oldSize = _newgen.size();
if (oldSize == _newsize)
return;
if (oldSize < _newsize)
throw std::logic_error("eoLinearTruncate: Cannot truncate to a larger size!\n");
for (unsigned i=0; i<oldSize - _newsize; i++)
{
eoPop<EOT>::iterator it = _newgen.it_worse_element();
_newgen.erase(it);
}
}
};
/** a truncate class based on a repeated deterministic (reverse!) tournament
To be used in SSGA-like replacements (e.g. see eoSSGADetTournamentReplacement)
*/
template <class EOT>
class eoDetTournamentTruncate : public eoReduce<EOT>
{
public:
eoDetTournamentTruncate(unsigned _t_size):
t_size(_t_size)
{
if (t_size < 2)
{
cout << "Warning, Size for eoDetTournamentTruncate adjusted to 2\n";
t_size = 2;
}
}
void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
{
unsigned oldSize = _newgen.size();
if (_newsize == 0)
{
_newgen.resize(0);
return;
}
if (oldSize == _newsize)
return;
if (oldSize < _newsize)
throw std::logic_error("eoDetTournamentTruncate: Cannot truncate to a larger size!\n");
// Now OK to erase some losers
for (unsigned i=0; i<oldSize - _newsize; i++)
{
EOT & eo = inverse_deterministic_tournament<EOT>(_newgen, t_size);
_newgen.erase(&eo);
}
}
private:
unsigned t_size;
};
/** a truncate class based on a repeated deterministic (reverse!) tournament
To be used in SSGA-like replacements (e.g. see eoSSGAStochTournamentReplacement)
*/
template <class EOT>
class eoStochTournamentTruncate : public eoReduce<EOT>
{
public:
eoStochTournamentTruncate(double _t_rate):
t_rate(_t_rate)
{
if (t_rate <= 0.5)
{
cout << "Warning, Rate for eoStochTournamentTruncate adjusted to 0.51\n";
t_rate = 0.51;
}
if (t_rate > 1)
{
cout << "Warning, Rate for eoStochTournamentTruncate adjusted to 1\n";
t_rate = 1;
}
}
void operator()(eoPop<EOT>& _newgen, unsigned _newsize)
{
unsigned oldSize = _newgen.size();
if (_newsize == 0)
{
_newgen.resize(0);
return;
}
if (oldSize == _newsize)
return;
if (oldSize < _newsize)
throw std::logic_error("eoStochTournamentTruncate: Cannot truncate to a larger size!\n");
// Now OK to erase some losers
for (unsigned i=0; i<oldSize - _newsize; i++)
{
EOT & eo = inverse_stochastic_tournament<EOT>(_newgen, t_rate);
_newgen.erase(&eo);
}
}
private:
double t_rate;
};
//-----------------------------------------------------------------------------
#endif //eoInsertion_h

119
eo/src/eoReduceMerge.h Normal file
View file

@ -0,0 +1,119 @@
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoReduceMerge.h
(c) Maarten Keijzer, Marc Schoenauer, GeNeura Team, 2000
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 _eoReduceMerge_h
#define _eoReduceMerge_h
//-----------------------------------------------------------------------------
#include <eoPop.h>
#include <eoFunctor.h>
#include <eoMerge.h>
#include <eoReduce.h>
#include <eoReplacement.h>
#include <utils/eoHowMany.h>
//-----------------------------------------------------------------------------
/**
eoReduceMerge: Replacement strategies that start by reducing the parents,
then merge with the offspring
This is the way to do SSGA: the offspring gets inserted in the population
even if it is worse than anybody else.
@classes: eoReduceMerge, eoSSGAWorseReplacement,
eoSSGADetTournamentReplacement, eoSSGAStochTournamentReplacement
*/
template <class EOT>
class eoReduceMerge : public eoReplacement<EOT>
{
public:
eoReduceMerge(eoReduce<EOT>& _reduce, eoMerge<EOT>& _merge) :
reduce(_reduce), merge(_merge)
{}
void operator()(eoPop<EOT>& _parents, eoPop<EOT>& _offspring)
{
if (_parents.size() < _offspring.size())
throw std::logic_error("eoReduceMerge: More offspring than parents!\n");
reduce(_parents, _parents.size() - _offspring.size());
merge(_offspring, _parents);
}
private :
eoReduce<EOT>& reduce;
eoMerge<EOT>& merge;
};
/**
SSGA replace worst. Is an eoReduceMerge.
*/
template <class EOT>
class eoSSGAWorseReplacement : public eoReduceMerge<EOT>
{
public :
eoSSGAWorseReplacement() : eoReduceMerge<EOT>(truncate, plus) {}
private :
eoLinearTruncate<EOT> truncate;
eoPlus<EOT> plus;
};
/**
SSGA deterministic tournament replacement. Is an eoReduceMerge.
*/
template <class EOT>
class eoSSGADetTournamentReplacement : public eoReduceMerge<EOT>
{
public :
eoSSGADetTournamentReplacement(unsigned _t_size) :
eoReduceMerge<EOT>(truncate, plus), truncate(_t_size) {}
private :
eoDetTournamentTruncate<EOT> truncate;
eoPlus<EOT> plus;
};
/** SSGA stochastic tournament replacement. Is an eoReduceMerge.
It much cleaner to insert directly the offspring in the parent population,
but it is NOT equivalent in case of more than 1 offspring as already
replaced could be removed , which is not possible in the eoReduceMerge
So what the heck ! */
template <class EOT>
class eoSSGAStochTournamentReplacement : public eoReduceMerge<EOT>
{
public :
eoSSGAStochTournamentReplacement(double _t_rate) :
eoReduceMerge<EOT>(truncate, plus), truncate(_t_rate) {}
private :
eoStochTournamentTruncate<EOT> truncate;
eoPlus<EOT> plus;
};
#endif

View file

@ -2,7 +2,7 @@
-----------------------------------------------------------------------------
eoReplacement.h
(c) Maarten Keijzer, GeNeura Team, 2000
(c) Maarten Keijzer, Marc Schoenauer, GeNeura Team, 2000
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@ -18,7 +18,9 @@
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
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
Marc.Schoenauer@polytechnique.fr
mkeijzer@dhi.dk
*/
//-----------------------------------------------------------------------------
@ -31,81 +33,85 @@
#include <eoFunctor.h>
#include <eoMerge.h>
#include <eoReduce.h>
#include <utils/eoHowMany.h>
//-----------------------------------------------------------------------------
/**
eoReplacement: High level strategy for creating a new generation
from parents and offspring. This is a combination of eoMerge and eoReduce,
so there is an implementation called eoMergeReduce that can be found below
from parents and offspring.
@see eoMerge, eoReduce, eoMergeReduce
The eoMergeReduce, combination of eoMerge and eoReduce, can be found
in file eoMergeReduce.h
Removed the const before first argument: though it makes too many classes
with the same interface, it allows to minimize the number of actual copies
by choosing the right destination
I also removed the enforced "swap" in the eoEasyAlgo and hence the generational
replacement gets a class of its own that only does the swap (instead of the
eoNoReplacement that did nothing, relying on the algo to swap popualtions).
MS 12/12/2000
NOTE: the resulting population should always be in the first argument
(replace parents by offspring)! The second argument can contain any rubbish
@see eoMerge, eoReduce, eoMergeReduce, eoReduceMerge
@classes eoReplacement, base (pure abstract) class
eoGenerationalReplacement, as it says ...
eoWeakElitistReplacement a wrapper to add elitism
*/
/**
eoReplacement: the base class for all replacementp functors
*/
template<class EOT>
class eoReplacement : public eoBF<const eoPop<EOT>&, eoPop<EOT>&, void>
class eoReplacement : public eoBF<eoPop<EOT>&, eoPop<EOT>&, void>
{};
/**
no replacement
generational replacement == swap populations
*/
template <class EOT>
class eoNoReplacement : public eoReplacement<EOT>
class eoGenerationalReplacement : public eoReplacement<EOT>
{
public :
/// do nothing
void operator()(const eoPop<EOT>&, eoPop<EOT>&)
{}
/// swap
void operator()(eoPop<EOT>& _parents, eoPop<EOT>& _offspring)
{
_parents.swap(_offspring);
}
};
/**
eoMergeReduce: special replacement strategy that is just an application of an embedded merge,
followed by an embedded reduce
/**
eoWeakElitistReplacement: a wrapper for other replacement procedures.
Copies in the new pop the best individual from the old pop,
AFTER normal replacement, if the best of the new pop is worse than the best
of the old pop. Removes the worse individual from the new pop.
This could be changed by adding a selector there...
*/
template <class EOT>
class eoMergeReduce : public eoReplacement<EOT>
class eoWeakElitistReplacement : public eoReplacement<EOT>
{
public:
eoMergeReduce(eoMerge<EOT>& _merge, eoReduce<EOT>& _reduce) :
merge(_merge), reduce(_reduce)
{}
public :
typedef typename EOT::Fitness Fitness;
void operator()(const eoPop<EOT>& _parents, eoPop<EOT>& _offspring)
{
merge(_parents, _offspring);
reduce(_offspring, _parents.size());
}
// Ctor, takes an eoReplacement
eoWeakElitistReplacement(eoReplacement<EOT> & _replace) :
replace(_replace) {}
private :
eoMerge<EOT>& merge;
eoReduce<EOT>& reduce;
/// do replacement
void operator()(eoPop<EOT>& _pop, eoPop<EOT>& _offspring)
{
const EOT & oldChamp = _pop.best_element();
replace(_pop, _offspring); // "normal" replacement, parents are the new
if (_pop.best_element() < oldChamp) // need to do something
{
typename eoPop<EOT>::iterator itPoorGuy = _pop.it_worse_element();
(*itPoorGuy) = oldChamp;
}
}
private:
eoReplacement<EOT> & replace;
};
/**
ES type of replacement strategy: first add parents to population, then truncate
*/
template <class EOT>
class eoPlusReplacement : public eoMergeReduce<EOT>
{
public :
eoPlusReplacement() : eoMergeReduce<EOT>(plus, truncate) {}
private :
eoPlus<EOT> plus;
eoTruncate<EOT> truncate;
};
/**
ES type of replacement strategy: ignore parents, truncate offspring
*/
template <class EOT>
class eoCommaReplacement : public eoMergeReduce<EOT>
{
public :
eoCommaReplacement() : eoMergeReduce<EOT>(no_elite, truncate) {}
private :
eoNoElitism<EOT> no_elite;
eoTruncate<EOT> truncate;
};
#endif

76
eo/src/eoSelectMany.h Normal file
View file

@ -0,0 +1,76 @@
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoSelectMany.h
(c) Maarten Keijzer, Marc Schoenauer, GeNeura Team, 2000
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 _eoSelectMany_h
#define _eoSelectMany_h
//-----------------------------------------------------------------------------
#include <eoSelect.h>
#include <eoSelectOne.h>
#include <utils/eoHowMany.h>
#include <math.h>
//-----------------------------------------------------------------------------
/** eoSelectMany selects many individuals using eoSelectOne as it's
mechanism. Therefore eoSelectMany needs an eoSelectOne in its ctor
It will use an eoHowMnay to determine the number of guys to select,
and push them to the back of the destination population.
*/
template<class EOT>
class eoSelectMany : public eoSelect<EOT>
{
public:
/// init
eoSelectMany(eoSelectOne<EOT>& _select,
double _rate, bool _interpret_as_rate = true)
: select(_select), howMany(_rate, _interpret_as_rate) {}
/**
The implementation repeatidly selects an individual
@param _source the source population
@param _dest the resulting population (size of this population is the number of times eoSelectOne is called. It empties the destination and adds the selection into it)
*/
virtual void operator()(const eoPop<EOT>& _source, eoPop<EOT>& _dest)
{
unsigned target = howMany(_source.size());
_dest.resize(target);
select.setup(_source);
for (size_t i = 0; i < _dest.size(); ++i)
_dest[i] = select(_source);
}
private :
eoSelectOne<EOT>& select;
eoHowMany howMany;
};
#endif

72
eo/src/eoSelectNumber.h Normal file
View file

@ -0,0 +1,72 @@
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoSelectNumber.h
(c) Maarten Keijzer, Marc Schoenauer, GeNeura Team, 2000
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
*/
//-----------------------------------------------------------------------------
#ifndef _eoSelectNumber_h
#define _eoSelectNumber_h
//-----------------------------------------------------------------------------
#include <eoSelect.h>
#include <eoSelectOne.h>
#include <math.h>
//-----------------------------------------------------------------------------
/** eoSelectNumber selects many individuals using eoSelectOne as it's
mechanism. Therefore eoSelectNumber needs an eoSelectOne in its ctor
It will select a fixed number of individuals and pushes them to
the back of the destination population.
*/
template<class EOT>
class eoSelectNumber : public eoSelect<EOT>
{
public:
/// init
eoSelectNumber(eoSelectOne<EOT>& _select, unsigned _nb_to_select = 1)
: select(_select), nb_to_select(_nb_to_select) {}
/**
The implementation repeatidly selects an individual
@param _source the source population
@param _dest the resulting population (size of this population is the number of times eoSelectOne is called. It empties the destination and adds the selection into it)
*/
virtual void operator()(const eoPop<EOT>& _source, eoPop<EOT>& _dest)
{
size_t target = static_cast<size_t>(nb_to_select);
_dest.resize(target);
select.setup(_source);
for (size_t i = 0; i < _dest.size(); ++i)
_dest[i] = select(_source);
}
private :
eoSelectOne<EOT>& select;
unsigned nb_to_select;
};
#endif

188
eo/src/eoSurviveAndDie.h Normal file
View file

@ -0,0 +1,188 @@
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoSurviveAndDie.h
(c) Maarten Keijzer, Marc Schoenauer, GeNeura Team, 2000
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 _eoSurviveAndDie_h
#define _eoSurviveAndDie_h
//-----------------------------------------------------------------------------
#include <eoPop.h>
#include <eoFunctor.h>
#include <eoMerge.h>
#include <eoReduce.h>
#include <utils/eoHowMany.h>
//-----------------------------------------------------------------------------
/**
eoSurviveAndDie: takes a population (first argument),
kills the ones that are to die,
puts the ones that are to survive into the second argument
removes them from the first pop argument
@classes: eoSurviveAndDie, eoDeterministicSurviveAndDie,
eoDeterministicSaDReplacement
*/
/** eoSurviveAndDie
A pure abstract class, to store the howmany's
*/
template <class EOT>
class eoSurviveAndDie : public eoBF<eoPop<EOT> &, eoPop<EOT> &, void>
{
public:
eoSurviveAndDie(double _survive, double _die, bool _interpret_as_rate = true):
howmanySurvive(_survive, _interpret_as_rate),
howmanyDie(_die, _interpret_as_rate)
{}
protected:
eoHowMany howmanySurvive;
eoHowMany howmanyDie;
};
/**
an instance (theonly one as of today, Dec. 20, 2000) of an eoSurviveAndDie,
that does everything deterministically
used in eoDeterministicSaDReplacement
*/
template <class EOT>
class eoDeterministicSurviveAndDie : public eoSurviveAndDie<EOT>
{
public:
eoDeterministicSurviveAndDie(double _survive, double _die,
bool _interpret_as_rate = true):
eoSurviveAndDie<EOT>(_survive, _die, _interpret_as_rate)
{}
void operator()(eoPop<EOT> & _pop, eoPop<EOT> & _luckyGuys)
{
unsigned pSize = _pop.size();
unsigned nbSurvive = howmanySurvive(pSize);
// first, save the best into _luckyGuys
if (nbSurvive)
{
_pop.nth_element(nbSurvive);
// copy best
_luckyGuys.resize(nbSurvive);
copy(_pop.begin(), _pop.begin()+nbSurvive, _luckyGuys.begin());
// erase them from pop
_pop.erase(_pop.begin(), _pop.begin()+nbSurvive);
}
unsigned nbRemaining = _pop.size();
// carefull, we can have a rate of 1 if we want to kill all remaining
unsigned nbDie = min(howmanyDie(pSize), pSize-nbSurvive);
if (nbDie > nbRemaining)
throw std::logic_error("eoDeterministicSurviveAndDie: Too many to kill!\n");
if (!nbDie)
{
return;
}
// else
// kill the worse nbDie
_pop.nth_element(nbRemaining-nbDie);
_pop.resize(nbRemaining-nbDie);
}
};
/**
eoDeterministicSaDReplacement: replacement strategy that is just, in sequence
saves best and kill worse from parents
+ saves best and kill worse from offspring
+ merge remaining (neither save nor killed) parents and offspring
+ reduce that merged population
= returns reduced pop + best parents + best offspring
An obvious use is as strong elitist strategy,
i.e. preserving best parents, and reducing
(either offspring or parents+offspring)
*/
template <class EOT>
class eoDeterministicSaDReplacement : public eoReplacement<EOT>
{
public:
/** Constructor with reduce */
eoDeterministicSaDReplacement(eoReduce<EOT>& _reduceGlobal,
double _surviveParents, double _dieParents=0,
double _surviveOffspring=0, double _dieOffspring=0,
bool _interpret_as_rate = true ) :
reduceGlobal(_reduceGlobal),
sAdParents(_surviveParents, _dieParents, _interpret_as_rate),
sAdOffspring(_surviveOffspring, _dieOffspring, _interpret_as_rate)
{}
/** Constructor with default truncate used as reduce */
eoDeterministicSaDReplacement(
double _surviveParents, double _dieParents=0,
double _surviveOffspring=0, double _dieOffspring=0,
bool _interpret_as_rate = true ) :
reduceGlobal(truncate),
sAdParents(_surviveParents, _dieParents, _interpret_as_rate),
sAdOffspring(_surviveOffspring, _dieOffspring, _interpret_as_rate)
{}
void operator()(eoPop<EOT>& _parents, eoPop<EOT>& _offspring)
{
unsigned pSize = _parents.size(); // target number of individuals
eoPop<EOT> luckyParents; // to hold the absolute survivors
sAdParents(_parents, luckyParents);
eoPop<EOT> luckyOffspring; // to hold the absolute survivors
sAdOffspring(_offspring, luckyOffspring);
unsigned survivorSize = luckyOffspring.size() + luckyParents.size();
if (survivorSize > pSize)
throw std::logic_error("eoGeneralReplacement: More survivors than parents!\n");
plus(_parents, _offspring); // all that remain in _offspring
reduceGlobal(_offspring, pSize - survivorSize);
plus(luckyParents, _offspring);
plus(luckyOffspring, _offspring);
_parents.swap(_offspring);
}
private :
eoReduce<EOT>& reduceGlobal;
eoDeterministicSurviveAndDie<EOT> sAdParents;
eoDeterministicSurviveAndDie<EOT> sAdOffspring;
// plus helper (could be replaced by operator+= ???)
eoPlus<EOT> plus;
// the default reduce: deterministic truncation
eoTruncate<EOT> truncate;
};
#endif