Changed the general operator interface to be consistent with the rest
of EO, updated some documentation.
This commit is contained in:
parent
64a5d2de58
commit
ed45375451
17 changed files with 230 additions and 52 deletions
|
|
@ -29,9 +29,10 @@
|
|||
#ifndef eoBackInserter_h
|
||||
#define eoBackInserter_h
|
||||
|
||||
#include "eoInserter.h"
|
||||
#include <eoInserter.h>
|
||||
|
||||
/**
|
||||
\ingroup inserters
|
||||
* eoBackInserter: Interface class that enables an operator to insert
|
||||
new individuals at the back of the new population.
|
||||
*/
|
||||
|
|
@ -42,9 +43,10 @@ class eoBackInserter : public eoPopInserter<EOT>
|
|||
|
||||
eoBackInserter(void) : eoPopInserter<EOT>() {}
|
||||
|
||||
void insert(const EOT& _eot)
|
||||
eoInserter<EOT>& operator()(const EOT& _eot)
|
||||
{
|
||||
pop().push_back(_eot);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string className(void) const { return "eoBackInserter"; }
|
||||
|
|
|
|||
|
|
@ -26,11 +26,12 @@
|
|||
#define eoDetTournamentIndiSelector_h
|
||||
|
||||
#include "eoIndiSelector.h"
|
||||
#include "selectors.h"
|
||||
#include "utils/selectors.h"
|
||||
|
||||
|
||||
/**
|
||||
* eoDetTournamentIndiSelector: selects children through a deterministic_tournament
|
||||
\ingroup selectors
|
||||
* eoDetTournamentIndiSelector: selects children through a deterministic_tournament
|
||||
*/
|
||||
template <class EOT>
|
||||
class eoDetTournamentIndiSelector : public eoPopIndiSelector<EOT>
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@
|
|||
#define eoDetTournamentInserter_h
|
||||
|
||||
|
||||
#include "eoSteadyStateInserter.h"
|
||||
#include "selectors.h"
|
||||
#include <eoSteadyStateInserter.h>
|
||||
#include <utils/selectors.h>
|
||||
|
||||
/**
|
||||
* eoDetTournamentInserter: Uses an inverse deterministic tournament to figure
|
||||
|
|
@ -50,13 +50,14 @@ class eoDetTournamentInserter : public eoSteadyStateInserter<EOT>
|
|||
}
|
||||
}
|
||||
|
||||
void insert(const EOT& _eot)
|
||||
eoInserter<EOT>& operator()(const EOT& _eot)
|
||||
{
|
||||
EOT& eo = inverse_deterministic_tournament<EOT>(pop(), t_size);
|
||||
eo = _eot; // overwrite loser of tournament
|
||||
|
||||
eo.invalidate(); // This line should probably be removed when all genetic operators do this themselves
|
||||
eval(eo); // Evaluate after insert
|
||||
return *this;
|
||||
}
|
||||
|
||||
string className(void) const { return "eoDetTournamentInserter"; }
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@
|
|||
#define EOFITNESS_H
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
\deprecated This class will dissapear in time, use eoScalarFitness instead
|
||||
*/
|
||||
class eoFitness: public eoPersistent
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class eoGOpBreeder: public eoMonPopOp<EOT>
|
|||
|
||||
for (unsigned i = 0; i < size; i++)
|
||||
{ // and the one liner
|
||||
opSel.selectOp()(selector(_pop,size, i), inserter(_pop));
|
||||
opSel.selectOp()(selector.bind(_pop,size, i), inserter.bind(_pop));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,8 +55,13 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/// Add any kind of operator to the operator mix, with an argument
|
||||
virtual ID addOp( eoOp<EOT>& _op, float _arg );
|
||||
/*
|
||||
Add any kind of operator to the operator mix,
|
||||
@param _op operator, one of eoMonOp, eoBinOp, eoQuadraticOp or eoGeneralOp
|
||||
@param _rate the rate at which it should be applied, it should be a probability
|
||||
|
||||
*/
|
||||
virtual ID addOp( eoOp<EOT>& _op, float _rate );
|
||||
// implementation can be found below
|
||||
|
||||
/** Retrieve the operator using its integer handle
|
||||
|
|
@ -79,7 +84,7 @@ public:
|
|||
return &selectOp();
|
||||
}
|
||||
|
||||
///
|
||||
/// Select an operator from the operators present here
|
||||
virtual eoGeneralOp<EOT>& selectOp() = 0;
|
||||
|
||||
///
|
||||
|
|
|
|||
|
|
@ -42,19 +42,29 @@ public :
|
|||
|
||||
virtual ~eoIndiSelector(void) {}
|
||||
|
||||
/**
|
||||
return the number of individuals that can be selected by an nary operator (through operator[] below)
|
||||
*/
|
||||
virtual size_t size(void) const = 0;
|
||||
virtual const EOT& operator[](size_t) const = 0;
|
||||
|
||||
virtual const EOT& select(void) = 0;
|
||||
/**
|
||||
return the specified individual, the size_t argument should be between 0 and eoIndiSelector::size()
|
||||
*/
|
||||
virtual const EOT& operator[](size_t i) const = 0;
|
||||
|
||||
/**
|
||||
Select an individual, maybe from an underlying population (see eoPopIndiSelector)
|
||||
*/
|
||||
virtual const EOT& operator()(void) = 0;
|
||||
|
||||
/// default implementation just calls operator() a couple of times
|
||||
/// this can be overridden in favour of a more efficient implementation
|
||||
virtual vector<const EOT*> select(size_t _how_many)
|
||||
{ // default implementation just calls select a couple of times
|
||||
// this can be overridden in favour of a more efficient implementation
|
||||
vector<const EOT*> result(_how_many);
|
||||
{ vector<const EOT*> result(_how_many);
|
||||
|
||||
for (unsigned i = 0; i < _how_many; ++i)
|
||||
{
|
||||
result[i] = &select();
|
||||
result[i] = &operator()();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -79,9 +89,10 @@ class eoPopIndiSelector : public eoIndiSelector<EOT>
|
|||
|
||||
struct eoUnitializedException{};
|
||||
|
||||
/** Initialization function
|
||||
/** Initialization function, binds the population to the selector, can also
|
||||
be used to specify an optional end and the first individual to return in operator()
|
||||
*/
|
||||
eoPopIndiSelector& operator()(const eoPop<EOT>& _pop, int _end = -1, int _myGuy = -1)
|
||||
eoPopIndiSelector& bind(const eoPop<EOT>& _pop, int _end = -1, int _myGuy = -1)
|
||||
{
|
||||
pop = &_pop;
|
||||
last = _end;
|
||||
|
|
@ -102,8 +113,8 @@ class eoPopIndiSelector : public eoIndiSelector<EOT>
|
|||
eoPop<EOT>::const_iterator end(void) const { valid(); return pop->end(); }
|
||||
|
||||
|
||||
/// select does the work. Note that it is not virtual. It calls do_select that needs to be implemented by the derived classes
|
||||
const EOT& select(void)
|
||||
/// operator() does the work. Note that it is not virtual. It calls do_select that needs to be implemented by the derived classes
|
||||
const EOT& operator()(void)
|
||||
{
|
||||
valid();
|
||||
if (firstChoice < 0 || firstChoice >= (int) size())
|
||||
|
|
@ -116,6 +127,10 @@ class eoPopIndiSelector : public eoIndiSelector<EOT>
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
do_select, abstract member re-implemented by derived classes
|
||||
This function will get called by operator() when it ran out of choices
|
||||
*/
|
||||
virtual const EOT& do_select(void) = 0;
|
||||
|
||||
private :
|
||||
|
|
|
|||
|
|
@ -36,14 +36,17 @@
|
|||
new individuals into the (intermediate) population.
|
||||
*/
|
||||
template <class EOT>
|
||||
class eoInserter : public eoObject
|
||||
class eoInserter
|
||||
{
|
||||
public :
|
||||
virtual ~eoInserter() {}
|
||||
|
||||
struct eoInserterException{};
|
||||
|
||||
virtual void insert(const EOT&) = 0; // can throw an eoInserterException
|
||||
/**
|
||||
insert argument somewhere (quite likely a population)
|
||||
*/
|
||||
virtual eoInserter<EOT>& operator()(const EOT&) = 0; // can throw an eoInserterException
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -58,7 +61,7 @@ class eoPopInserter : public eoInserter<EOT>
|
|||
eoPopInserter(void) : eoInserter<EOT>(), thePop(0) {}
|
||||
|
||||
/// Binds the population to this class. This is an initialization routine used by breeders
|
||||
eoInserter<EOT>& operator()(eoPop<EOT>& _pop)
|
||||
eoInserter<EOT>& bind(eoPop<EOT>& _pop)
|
||||
{
|
||||
thePop = &_pop;
|
||||
return *this;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@
|
|||
#include <eoObject.h>
|
||||
#include <eoPrintable.h>
|
||||
|
||||
/**
|
||||
\defgroup operators
|
||||
Genetic Operators are used for various purposes
|
||||
*/
|
||||
|
||||
/** @name Genetic operators
|
||||
|
||||
What is a genetic algorithm without genetic operators? There is a genetic operator hierarchy, with eoOp as father and eoMonOp (monary or unary operator) and eoBinOp and eoQuadraticOp (binary operators) as siblings). Nobody should subclass eoOp, you should subclass eoGeneralOp, eoBinOp, eoQuadraticOp or eoMonOp, those are the ones actually used here. \\#eoOp#s are only printable objects, so if you want to build them from a file, it has to be done in another class, namely factories. Each hierarchy of #eoOp#s should have its own factory, which know how to build them from a description in a file.
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "eoIndiSelector.h"
|
||||
|
||||
/**
|
||||
\ingroup selectors
|
||||
* eoRandomSelector: just selects a random child
|
||||
*/
|
||||
template <class EOT>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class eoScalarFitness
|
|||
|
||||
operator ScalarType(void) const { return value; }
|
||||
|
||||
// Comparison, using less by default
|
||||
/// Comparison, using less by default
|
||||
bool operator<(const eoScalarFitness& other) const
|
||||
{ return Compare()(value, other.value); }
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@
|
|||
#define eoSteadyStateInserter_h
|
||||
|
||||
|
||||
#include "eoEvalFunc.h"
|
||||
#include <eoEvalFunc.h>
|
||||
#include <eoInserter.h>
|
||||
|
||||
/**
|
||||
* eoSteadyStateInserter: Interface class that enables an operator to update
|
||||
|
|
|
|||
|
|
@ -29,11 +29,12 @@
|
|||
#define eoStochTournamentInserter_h
|
||||
|
||||
|
||||
#include "eoSteadyStateInserter.h"
|
||||
#include "selectors.h"
|
||||
#include <eoSteadyStateInserter.h>
|
||||
#include <utils/selectors.h>
|
||||
|
||||
/**
|
||||
* eoDetTournamentInserter: Uses an inverse stochastic tournament to figure
|
||||
\ingroup inserters
|
||||
* eoStochTournamentInserter: Uses an inverse stochastic tournament to figure
|
||||
* out who gets overridden by the new individual. It resets the fitness of the
|
||||
* individual.
|
||||
*/
|
||||
|
|
@ -55,13 +56,14 @@ class eoStochTournamentInserter : public eoSteadyStateInserter<EOT>
|
|||
}
|
||||
}
|
||||
|
||||
void insert(const EOT& _eot)
|
||||
eoInserter<EOT>& operator()(const EOT& _eot)
|
||||
{
|
||||
EOT& eo = inverse_stochastic_tournament<EOT>(pop(), t_rate);
|
||||
eo = _eot; // overwrite loser of tournament
|
||||
|
||||
eo.invalidate();
|
||||
eval(eo); // Evaluate after insert
|
||||
return *this;
|
||||
}
|
||||
|
||||
string className(void) const { return "eoStochTournamentInserter"; }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
// eoTerm.h
|
||||
// (c) GeNeura Team, 1999
|
||||
// (c) GeNeura Team, 1999, 2000
|
||||
/*
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
|
@ -25,11 +25,17 @@
|
|||
#ifndef _EOTERM_H
|
||||
#define _EOTERM_H
|
||||
|
||||
#include <eoPop.h>
|
||||
//#include <eoPop.h>
|
||||
|
||||
// forward definition for fast(er) compilation
|
||||
template <class EOT> class eoPop;
|
||||
|
||||
|
||||
/** Termination condition for the genetic algorithm
|
||||
* Takes the population as input, returns true for continue,
|
||||
* false for termination
|
||||
* false for termination (although this begs the question why this
|
||||
* terminator is not called a continuator)
|
||||
*
|
||||
*/
|
||||
template< class EOT>
|
||||
class eoTerm : public eoObject {
|
||||
|
|
@ -44,10 +50,77 @@ public:
|
|||
of the object, for instance, updating local data.
|
||||
*/
|
||||
virtual bool operator() ( const eoPop< EOT >& _pop ) = 0 ;
|
||||
|
||||
/// Class name.
|
||||
virtual string className() const { return "eoTerm"; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
/** eoParamTerm, a terminator that compares two statistics and decides whether the
|
||||
* algorithm should stop or not.
|
||||
*/
|
||||
|
||||
#include <utils/eoParam.h>
|
||||
|
||||
template<class EOT, class Pred>
|
||||
class eoBinaryTerm : public eoTerm<EOT>
|
||||
{
|
||||
public :
|
||||
|
||||
typedef typename Pred::first_argument_type first_argument_type;
|
||||
typedef typename Pred::second_argument_type second_argument_type;
|
||||
|
||||
/// Ctors/dtors
|
||||
eoBinaryTerm(first_argument_type& _param1, second_argument_type& _param2) : param1(_param1), param2(_param2), compare() {}
|
||||
|
||||
virtual ~eoBinaryTerm() {};
|
||||
|
||||
/**
|
||||
*/
|
||||
virtual bool operator() ( const eoPop< EOT >& _pop )
|
||||
{
|
||||
return compare(param1, param2);
|
||||
}
|
||||
|
||||
/// Class name.
|
||||
virtual string className() const { return "eoStatTerm"; }
|
||||
|
||||
private :
|
||||
|
||||
first_argument_type& param1;
|
||||
second_argument_type& param2;
|
||||
Pred compare;
|
||||
};
|
||||
|
||||
#include <utility>
|
||||
/** Combined termination condition for the genetic algorithm
|
||||
*
|
||||
* The eoCombinedTerm will perform a logical and on all the terminators
|
||||
* contained in it. This means that the terminator will say stop (return false)
|
||||
* when one of the contained terminators says so
|
||||
*
|
||||
*
|
||||
* So now you can say:
|
||||
|
||||
eoTerm1<EOT> term1;
|
||||
eoTerm2<EOT> term2;
|
||||
eoCombinedTerm<EOT> term3(term1, term2);
|
||||
|
||||
|
||||
template <class EOT>
|
||||
class eoCombinedTerm : public eoTerm<EOT>, public std::pair<eoTerm<EOT>&, eoTerm<EOT>& >
|
||||
{
|
||||
public :
|
||||
|
||||
eoCombinedTerm(const eoTerm<EOT>& _first, const eoTerm<EOT>& _second) : std::pair(_first, _second) {}
|
||||
|
||||
~eoCombinedTerm() {}
|
||||
|
||||
bool operator()(const eoPop<EOT>& _pop)
|
||||
{
|
||||
if (first(_pop))
|
||||
return second(_pop);
|
||||
|
||||
return false; // quit evolution
|
||||
}
|
||||
};
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,29 @@ class eoUniform: public eoRnd<T>
|
|||
double diff;
|
||||
};
|
||||
|
||||
template<>
|
||||
class eoUniform<bool>: public eoRnd<bool>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Default constructor.
|
||||
* @param _min The minimum value in the interval.
|
||||
* @param _max The maximum value in the interval.
|
||||
*/
|
||||
eoUniform(bool _min = false, bool _max = true)
|
||||
: eoRnd<bool>() {}
|
||||
|
||||
/** Returns an uniform random number over the interval [min, max)
|
||||
Uses global rng object */
|
||||
virtual bool operator()() {
|
||||
return rng.flip(0.5);
|
||||
}
|
||||
|
||||
private:
|
||||
T min;
|
||||
double diff;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@ public :
|
|||
/// Instantiates the abstract method
|
||||
void operator()( eoIndiSelector<EOT>& _in,
|
||||
eoInserter<EOT>& _out) const {
|
||||
EOT result = _in.select();
|
||||
EOT result = _in();
|
||||
op( result );
|
||||
_out.insert(result);
|
||||
_out(result);
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -78,10 +78,10 @@ public :
|
|||
/// Instantiates the abstract method. EOT should have copy ctor.
|
||||
void operator()(eoIndiSelector<EOT>& _in,
|
||||
eoInserter<EOT>& _out) const {
|
||||
EOT out1 = _in.select();
|
||||
const EOT& out2 = _in.select();
|
||||
EOT out1 = _in();
|
||||
const EOT& out2 = _in();
|
||||
op(out1, out2);
|
||||
_out.insert(out1);
|
||||
_out(out1);
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -105,11 +105,10 @@ public :
|
|||
/// Instantiates the abstract method. EOT should have copy ctor.
|
||||
void operator()(eoIndiSelector<EOT>& _in,
|
||||
eoInserter<EOT>& _out) const {
|
||||
EOT out1 = _in.select();
|
||||
EOT out2 = _in.select();
|
||||
EOT out1 = _in();
|
||||
EOT out2 = _in();
|
||||
op(out1, out2);
|
||||
_out.insert(out1);
|
||||
_out.insert(out2);
|
||||
_out(out1)(out2);
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -154,11 +153,11 @@ public :
|
|||
size_t size() const { return in.size(); }
|
||||
const EOT& operator[](size_t _n) const { return in[_n]; }
|
||||
|
||||
const EOT& select(void)
|
||||
const EOT& operator()(void)
|
||||
{
|
||||
if (results.empty())
|
||||
{
|
||||
return in.select();
|
||||
return in();
|
||||
}
|
||||
// else we use the previously inserted individual,
|
||||
// an iterator to it is stored in 'results', but the memory
|
||||
|
|
@ -169,10 +168,11 @@ public :
|
|||
return *it;
|
||||
}
|
||||
|
||||
void insert(const EOT& _eot)
|
||||
eoInserter<EOT>& operator()(const EOT& _eot)
|
||||
{
|
||||
intermediate.push_front(_eot);
|
||||
results.push_front(intermediate.begin());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void fill(eoInserter<EOT>& _out)
|
||||
|
|
@ -181,7 +181,7 @@ public :
|
|||
|
||||
for (Iterator it = results.begin(); it != results.end(); ++it)
|
||||
{
|
||||
_out.insert(**it);
|
||||
_out(**it);
|
||||
}
|
||||
|
||||
results.clear();
|
||||
|
|
|
|||
|
|
@ -32,8 +32,17 @@
|
|||
#include <eoPop.h>
|
||||
#include <ga/eoBitOp.h>
|
||||
#include <eoProportionalGOpSel.h>
|
||||
//#include <eoAltBreeder.h>
|
||||
#include <eoSequentialGOpSelector.h>
|
||||
#include <eoRandomIndiSelector.h>
|
||||
|
||||
#include <eoDetTournamentIndiSelector.h>
|
||||
#include <eoDetTournamentInserter.h>
|
||||
#include <eoStochTournamentInserter.h>
|
||||
|
||||
#include <eoGOpBreeder.h>
|
||||
|
||||
#include <utils/eoRNG.h>
|
||||
#include <utils/eoState.h>
|
||||
|
||||
// Fitness evaluation
|
||||
#include "binary_value.h"
|
||||
|
|
@ -46,6 +55,8 @@ typedef eoBin<float> Chrom;
|
|||
|
||||
main()
|
||||
{
|
||||
rng.reseed(42); // reproducible random seed
|
||||
|
||||
const unsigned POP_SIZE = 8, CHROM_SIZE = 4;
|
||||
unsigned i;
|
||||
|
||||
|
|
@ -68,16 +79,49 @@ main()
|
|||
eoBinBitFlip<Chrom> bitflip;
|
||||
eoBinCrossover<Chrom> xover;
|
||||
|
||||
eoEvalFuncPtr<Chrom> eval(binary_value);
|
||||
|
||||
//Create the proportional operator selector and add the
|
||||
// two operators creatd above to it.
|
||||
|
||||
eoProportionalGOpSel<Chrom > propSel;
|
||||
eoSequentialGOpSel<Chrom> seqSel;
|
||||
|
||||
propSel.addOp(bitflip, 0.5);
|
||||
propSel.addOp(xover, 0.5);
|
||||
for ( i = 0; i < POP_SIZE; i ++ ) {
|
||||
eoGeneralOp<Chrom>& foo = propSel.selectOp();
|
||||
}
|
||||
|
||||
// seqSel selects operator in sequence, creating a combined operator
|
||||
// add a bitflip, an xover and another bitflip
|
||||
seqSel.addOp(bitflip, 0.25);
|
||||
seqSel.addOp(xover, 0.5);
|
||||
seqSel.addOp(bitflip, 0.25);
|
||||
|
||||
|
||||
eoRandomIndiSelector<Chrom> selector1;
|
||||
eoDetTournamentIndiSelector<Chrom> selector2(2);
|
||||
|
||||
eoBackInserter<Chrom> inserter1;
|
||||
eoDetTournamentInserter<Chrom> inserter2(eval, 2);
|
||||
eoStochTournamentInserter<Chrom> inserter3(eval, 0.9f);
|
||||
|
||||
eoGOpBreeder<Chrom> breeder1(propSel, selector1);
|
||||
eoGOpBreeder<Chrom> breeder2(seqSel, selector1);
|
||||
eoGOpBreeder<Chrom> breeder3(propSel, selector2);
|
||||
eoGOpBreeder<Chrom> breeder4(seqSel, selector2);
|
||||
|
||||
// test the breeders
|
||||
|
||||
breeder1(pop);
|
||||
breeder2(pop);
|
||||
breeder3(pop);
|
||||
breeder4(pop);
|
||||
|
||||
eoState state;
|
||||
|
||||
state.registerObject(pop);
|
||||
|
||||
state.save(std::cout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Reference in a new issue