Changed the general operator interface to be consistent with the rest

of EO, updated some documentation.
This commit is contained in:
mac 2000-04-09 09:41:29 +00:00
commit ed45375451
17 changed files with 230 additions and 52 deletions

View file

@ -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"; }

View file

@ -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>

View file

@ -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"; }

View file

@ -25,7 +25,9 @@
#define EOFITNESS_H
//-----------------------------------------------------------------------------
/**
\deprecated This class will dissapear in time, use eoScalarFitness instead
*/
class eoFitness: public eoPersistent
{
public:

View file

@ -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));
}
}

View file

@ -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;
///

View file

@ -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 :

View file

@ -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;

View file

@ -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.

View file

@ -29,6 +29,7 @@
#include "eoIndiSelector.h"
/**
\ingroup selectors
* eoRandomSelector: just selects a random child
*/
template <class EOT>

View file

@ -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); }

View file

@ -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

View file

@ -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"; }

View file

@ -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

View file

@ -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

View file

@ -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();

View file

@ -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;
}