The BIG change of general operator interface

I also changed
  - the eoQuadratic into eoQuad (as dicussed with Maarten)
  - the eoBin into eoBit, with more appropriate names for the "binary"
    operators (that can be unary!) as no one protested when I posted on
    eodev list
This commit is contained in:
evomarc 2001-02-09 05:09:26 +00:00
commit 415b419671
60 changed files with 2034 additions and 940 deletions

View file

@ -0,0 +1,56 @@
/* -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoInserter.h
Abstract population insertion operator, which is used by the eoGeneralOps
to insert the results in the (intermediate) population. This file also
contains the definitions of a derived classes that implements a back inserter,
probably the only efficient inserter for populations of type vector.
(c) Maarten Keijzer (mkeijzer@mad.scientist.com) and 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
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 eoBackInserter_h
#define eoBackInserter_h
#include <eoInserter.h>
/**
\ingroup inserters
* eoBackInserter: Interface class that enables an operator to insert
new individuals at the back of the new population.
*/
template <class EOT>
class eoBackInserter : public eoPopInserter<EOT>
{
public :
eoBackInserter(void) : eoPopInserter<EOT>() {}
eoInserter<EOT>& operator()(const EOT& _eot)
{
pop().push_back(_eot);
return *this;
}
string className(void) const { return "eoBackInserter"; }
};
#endif

View file

@ -0,0 +1,70 @@
/* -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoDetTournamentInserter.h
Concrete steady state inserter. It is initialized with a population and
inserts individuals in the population based on an inverse deterministic
tournament
(c) Maarten Keijzer (mkeijzer@mad.scientist.com) and 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
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 eoDetTournamentInserter_h
#define eoDetTournamentInserter_h
#include <eoSteadyStateInserter.h>
#include <utils/selectors.h>
/**
* eoDetTournamentInserter: Uses an inverse deterministic tournament to figure
* out who gets overridden by the new individual. It resets the fitness of the
* individual.
*/
template <class EOT>
class eoDetTournamentInserter : public eoSteadyStateInserter<EOT>
{
public :
eoDetTournamentInserter(eoEvalFunc<EOT>& _eval, unsigned _t_size):
eoSteadyStateInserter<EOT>(_eval),
t_size(_t_size)
{
if (t_size < 2)
{ // warning, error?
t_size = 2;
}
}
eoInserter<EOT>& operator()(const EOT& _eot)
{
EOT& eo = inverse_deterministic_tournament<EOT>(pop(), t_size);
eo = _eot; // overwrite loser of tournament
eval(eo); // Evaluate after insert
return *this;
}
string className(void) const { return "eoDetTournamentInserter"; }
private :
unsigned t_size;
};
#endif

View file

@ -0,0 +1,62 @@
//-----------------------------------------------------------------------------
// eoBreeder.h
//-----------------------------------------------------------------------------
#ifndef eoGopBreeder_h
#define eoGopBreeder_h
//-----------------------------------------------------------------------------
/*****************************************************************************
* eoBreeder: transforms a population using genetic operators. *
* For every operator there is a rated to be applyed. *
*****************************************************************************/
#include <eoFunctor.h>
#include <eoPop.h>
#include <eoGOpSelector.h>
#include <eoIndiSelector.h>
#include <eoBackInserter.h>
/**
Base class for breeders using generalized operators, I'm not sure if we
will maintain the generalized operators in their current form, so
it might change.
*/
template<class EOT>
class eoGOpBreeder: public eoUF<eoPop<EOT>&, void>
{
public:
/// Default constructor.
eoGOpBreeder( eoGOpSelector<EOT>& _opSel,
eoSelectOneIndiSelector<EOT>& _selector)
: opSel( _opSel ), selector(_selector)
{}
/**
* Enlarges the population.
* @param pop The population to be transformed.
*/
void operator()(eoPop<EOT>& _pop)
{
unsigned size = _pop.size();
for (unsigned i = 0; i < size; i++)
{ // and the one liner
opSel.selectOp()(selector.bind(_pop,size).bias(i), inserter.bind(_pop));
}
}
/// The class name.
string className() const { return "eoGOpBreeder"; }
private:
eoGOpSelector<EOT>& opSel;
eoSelectOneIndiSelector<EOT>& selector;
// the inserter can be local as there's no point in changing it from the outside
eoBackInserter<EOT> inserter;
};
#endif eoBreeder_h

View file

@ -0,0 +1,181 @@
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoGOpSelector.h
Base class for generalized (n-inputs, n-outputs) operator selectors.
Includes code and variables that contain operators and rates.
Also included eoProportionalGOpSelector and eoSequentialGOpSelector, that offer
a few concrete implementations.
(c) Maarten Keijzer, GeNeura Team 1998, 1999, 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 eoGOpSelector_h
#define eoGOpSelector_h
//-----------------------------------------------------------------------------
#include <list>
#include "eoOpSelector.h"
#include "eoWrappedOps.h" // for eoCombinedOp
#include <utils/eoRNG.h>
using namespace std;
/** Base class for alternative selectors, which use the generalized operator
interface. eoGOpBreeders expects this class */
template<class EOT>
class eoGOpSelector: public eoOpSelector<EOT>, public vector<eoGeneralOp<EOT>*>
{
public:
typedef eoOpSelector<EOT>::ID ID;
/// Dtor
virtual ~eoGOpSelector() {
for ( list< eoGeneralOp<EOT>* >::iterator i= ownOpList.begin();
i != ownOpList.end(); i++ ) {
delete *i;
}
}
/*
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
@param _id The id number. Should be a valid id, or an exception
will be thrown
@return a reference of the operator corresponding to that id.
*/
virtual eoOp<EOT>& getOp( ID _id )
{
return *operator[](_id);
}
///
virtual void deleteOp( ID _id );
// implemented below
///
virtual eoOp<EOT>* Op()
{
return &selectOp();
}
/// Select an operator from the operators present here
virtual eoGeneralOp<EOT>& selectOp() = 0;
///
virtual string className() const { return "eoGOpSelector"; };
///
void printOn(ostream& _os) const {}
// _os << className().c_str() << endl;
// for ( unsigned i=0; i!= rates.size(); i++ ) {
// _os << *(operator[](i)) << "\t" << rates[i] << endl;
// }
//}
const vector<float>& getRates(void) const { return rates; }
private :
vector<float> rates;
list< eoGeneralOp<EOT>* > ownOpList;
};
/* Implementation of longish functions defined above */
template <class EOT>
inline eoOpSelector<EOT>::ID eoGOpSelector<EOT>::addOp( eoOp<EOT>& _op,
float _arg )
{
eoGeneralOp<EOT>* op;
if (_op.getType() == eoOp<EOT>::general)
{
op = static_cast<eoGeneralOp<EOT>*>(&_op);
}
else
{
// if it's not a general op, it's a "old" op; create a wrapped op from it
// and keep it on a list to delete them afterwards
// will use auto_ptr when they're readily available
switch(_op.getType())
{
case eoOp<EOT>::unary :
op= new eoWrappedMonOp<EOT>(static_cast<eoMonOp<EOT>&>(_op));
break;
case eoOp<EOT>::binary :
op = new eoWrappedBinOp<EOT>(static_cast<eoBinOp<EOT>&>(_op));
break;
case eoOp<EOT>::quadratic :
op = new eoWrappedQuadraticOp<EOT>(static_cast<eoQuadraticOp<EOT>&>(_op));
break;
case eoOp<EOT>::general : break; // cannot happen, but gcc issued a warning
}
ownOpList.push_back( op );
}
// Now 'op' is a general operator, either because '_op' was one or
// because we wrapped it in an appropriate wrapper in the code above.
typename eoGOpSelector<EOT>::iterator result = find(begin(), end(), (eoGeneralOp<EOT>*) 0); // search for nullpointer
if (result == end())
{
push_back(op);
rates.push_back(_arg);
return size();
}
// else
*result = op;
ID id = result - begin();
rates[id] = _arg;
return id;
}
template <class EOT>
inline void eoGOpSelector<EOT>::deleteOp( ID _id )
{
eoGeneralOp<EOT>* op = operator[](_id);
operator[](_id) = 0;
rates[_id] = 0.0;
// check oplist and clear it there too.
list< eoGeneralOp<EOT>* >::iterator it = find(ownOpList.begin(), ownOpList.end(), op);
if(it != ownOpList.end())
{
ownOpList.erase(it);
}
}
#endif eoGOpSelector_h

View file

@ -0,0 +1,160 @@
/* -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoIndiSelector.h
Abstract selection operator, which is used by the eoGeneralOps
to obtain individuals from a source population. It also gives a
direct descended eoPopIndiSelector that can be used to
initialize objects with an eoPop<EOT>. For most uses use eoPopIndividualSelector
rather than eoIndividualSelector to derive from.
(c) Maarten Keijzer (mkeijzer@mad.scientist.com) and 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
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 eoIndiSelector_h
#define eoIndiSelector_h
#include <eoFunctor.h>
/**
* eoIndividualSelector: This class defines the interface. This
* interface is used by the eoGeneralOp to get new individuals
* from a pop, a subpop or a remote pop
* for convenience when implementing an nary operator a size() and operator[]
* need to be implemented.
*/
template <class EOT>
class eoIndiSelector : public eoF<const EOT&>
{
public :
eoIndiSelector() {}
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;
/**
return the specified individual, the size_t argument should be between 0 and eoIndiSelector::size()
*/
virtual const EOT& operator[](size_t i) const = 0;
};
#include <eoSelectOne.h>
/**
* eoSelectOneAdaptor: Adaptor class for dispensing individuals.
It produces the eoIndiSelector interface and an eoSelectOne implementation
This class can then be used for general operators
various useful things can be done with this class:
you can specify how many of the population can ever be dispensed to the
operators, but you can also specify a preference to the first guy being
dispensed. This is useful if you want to perform the operator on a specific
individual.
@see eoSelectOne, eoIndiSelector
*/
template <class EOT>
class eoSelectOneIndiSelector : public eoIndiSelector<EOT>
{
public :
eoSelectOneIndiSelector(eoSelectOne<EOT>& _select) : pop(0), last(0), firstChoice(-1), secondChoice(-1), select(_select) {}
struct eoUnitializedException{};
/** Initialization function, binds the population to the selector, can also
be used to specify an optional end
*/
eoSelectOneIndiSelector& bind(const eoPop<EOT>& _pop, int _end = -1)
{
pop = &_pop;
last = _end;
if (last < 0 || last > (int) pop->size())
{
last = pop->size();
}
select.setup(*pop);
return *this;
}
/** Bias function to bias the selection function to select specific individuals
first before applying a selection algorithm defined in derived classes
*/
eoSelectOneIndiSelector& bias(int _first, int _second = -1)
{
firstChoice = _first;
secondChoice = _second;
return *this;
}
size_t size(void) const { valid(); return last; }
const EOT& operator[](size_t _i) const { valid(); return pop->operator[](_i); }
eoPop<EOT>::const_iterator begin(void) const { valid(); return pop->begin(); }
eoPop<EOT>::const_iterator end(void) const { valid(); return pop->end(); }
/// 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 >= last)
{
// see if we have a second choice
if (secondChoice < 0 || secondChoice >= last)
{
return select(*pop); // let the embedded selector figure out what to do
}
const EOT& result = pop->operator[](secondChoice);
secondChoice = -1;
return result;
}
const EOT& result = pop->operator[](firstChoice);
firstChoice = -1;
return result;
}
private :
void valid(void) const
{
if (pop == 0)
throw eoUnitializedException();
}
const eoPop<EOT>* pop; // need a pointer as this the pop argument can be re-instated
int last;
int firstChoice;
int secondChoice;
eoSelectOne<EOT>& select;
};
#endif

View file

@ -0,0 +1,193 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoInplaceTransform.h
// (c) GeNeura Team, 1998
/*
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 eoInplaceTransform_h
#define eoInplaceTransform_h
//-----------------------------------------------------------------------------
#include <vector> // vector
#include <utils/eoRNG.h>
#include <eoOp.h> // eoOp, eoMonOp, eoBinOp
#include <eoPop.h> // eoPop
#include <eoOpSelector.h> // eoOpSelector
#include <eoFunctor.h>
#include <eoIndiSelector.h>
#include <eoBackInserter.h>
/*****************************************************************************
* eoInplaceTransform1: transforms a population using genetic operators. *
* It does it in an SGA like manner
*****************************************************************************/
template<class Chrom> class eoInplaceTransform1 : public eoTransform<Chrom>
{
public:
/// Default constructor.
eoInplaceTransform1( eoOpSelector<Chrom>& _opSel): opSel( _opSel ), select(defaultSelect) {}
eoInplaceTransform1( eoOpSelector<Chrom>& _opSel, eoSelectOne<Chrom>& _select)
: opSel(_opSel), select(_select) {}
/**
* Transforms a population.
* @param pop The population to be transformed.
*/
void operator()(eoPop<Chrom>& pop)
{
// copy the guys in a newpop
// because otherwise eoSelectRandom might select freshly created individuals
eoPop<Chrom> newpop;
newpop.reserve(pop.size());
// Set up general op helper classes
eoSelectOneIndiSelector<Chrom> inplace(select);
eoBackInserter<Chrom> inserter;
// set up selection routine
select.setup(pop);
for (unsigned i = 0; i < pop.size(); i++)
{
eoOp<Chrom>* op = opSel.Op();
switch (op->getType())
{
case eoOp<Chrom>::unary:
{
eoMonOp<Chrom>* monop = static_cast<eoMonOp<Chrom>* >(op);
newpop.push_back(pop[i]);
(*monop)( newpop.back() );
break;
}
case eoOp<Chrom>::binary:
{
eoBinOp<Chrom>* binop = static_cast<eoBinOp<Chrom>* >(op);
newpop.push_back(pop[i]);
(*binop)(newpop[i], select(pop));
break;
}
case eoOp<Chrom>::quadratic:
{
eoQuadraticOp<Chrom>* Qop = static_cast<eoQuadraticOp<Chrom>* >(op);
newpop.push_back(pop[i]);
Chrom& indy1 = newpop.back();
if (++i == pop.size())
newpop.push_back(select(pop));
else
newpop.push_back(pop[i]);
(*Qop)(indy1, newpop.back() );
break;
}
case eoOp<Chrom>::general :
{
eoGeneralOp<Chrom>* Gop = static_cast<eoGeneralOp<Chrom>* >(op);
inplace.bind(pop);
inplace.bias(i,i + 1);
inserter.bind(newpop);
unsigned orgsize = newpop.size();
(*Gop)(inplace, inserter);
unsigned diff = newpop.size() - orgsize;
i = i + (diff-1);
break;
}
}
pop.swap(newpop); // overwrite existing pop
}
};
private:
eoOpSelector<Chrom>& opSel;
eoRandomSelect<Chrom> defaultSelect;
eoSelectOne<Chrom>& select;
};
#include <eoGOpSelector.h>
/*****************************************************************************
* eoInplaceTransform2: transforms a population using general genetic operators. *
* It does it in an SGA like manner
*****************************************************************************/
template<class Chrom> class eoInplaceTransform2 : public eoTransform<Chrom>
{
public:
/// Default constructor.
eoInplaceTransform2( eoGOpSelector<Chrom>& _opSel): opSel( _opSel ), select(defaultSelect) {}
eoInplaceTransform2( eoGOpSelector<Chrom>& _opSel, eoSelectOne<Chrom>& _select)
: opSel(_opSel), select(_select) {}
/**
* Transforms a population.
* @param pop The population to be transformed.
*/
void operator()(eoPop<Chrom>& pop)
{
// copy the guys in a newpop
// because otherwise eoSelectRandom might select freshly created individuals
eoPop<Chrom> newpop;
newpop.reserve(pop.size());
// Set up general op helper classes
eoSelectOneIndiSelector<Chrom> inplace(select);
eoBackInserter<Chrom> inserter;
// set up selection routine
select.setup(pop);
for (unsigned i = 0; i < pop.size(); i++)
{
eoGeneralOp<Chrom>& Gop = opSel.selectOp();
inplace.bind(pop);
inplace.bias(i,i + 1);
inserter.bind(newpop);
unsigned orgsize = newpop.size();
Gop(inplace, inserter);
// see how many have been inserted and add that to i (minus one ofcourse)
unsigned diff = newpop.size() - orgsize;
i = i + (diff-1);
}
pop.swap(newpop); // overwrite existing pop
}
private:
eoGOpSelector<Chrom>& opSel;
eoRandomSelect<Chrom> defaultSelect;
eoSelectOne<Chrom>& select;
};
//-----------------------------------------------------------------------------
#endif eoBreeder_h

View file

@ -0,0 +1,93 @@
/* -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoInserter.h
Abstract population insertion operator, which is used by the eoGeneralOps
to insert the results in the (intermediate) population. It also contains
a direct descended eoPopInserter that defines a convenient inbetween class
for working with eoPop<EOT>. The user will most likely derive from eoPopInserter
rather than eoInserter.
(c) Maarten Keijzer (mak@dhi.dk) and 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
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 eoInserter_h
#define eoInserter_h
#include <eoFunctor.h>
#include <eoPop.h>
/**
* eoInserter: Interface class that enables an operator to insert
new individuals into the (intermediate) population for example.
*/
template <class EOT>
class eoInserter : public eoUF<const EOT&, eoInserter<EOT>&>
{
public :
virtual ~eoInserter() {}
struct eoInserterException{};
};
/**
* eoPopInserter: In-between class that defines an initialization
* of the eoIndividualInserter.
*/
template <class EOT>
class eoPopInserter : public eoInserter<EOT>
{
public :
eoPopInserter(void) : eoInserter<EOT>(), thePop(0) {}
/// Binds the population to this class. This is an initialization routine used by breeders
eoInserter<EOT>& bind(eoPop<EOT>& _pop)
{
thePop = &_pop;
return *this;
}
protected :
eoPop<EOT>& pop(void) const { valid(); return *thePop; }
private :
void valid(void) const
{
if (thePop == 0)
throw eoInserterException();
}
// Need a pointer as the inserter should be able to bind to different populations.
// This is caused by the 'one template parameter only' convention in EO.
eoPop<EOT>* thePop;
// If eoGOpBreeder could be templatized over the inserter and the selector,
// the pop could be a ref as this class could be created every time it is applied
// and subsequently would get the population through the constructor
};
#endif

View file

@ -0,0 +1,87 @@
// eoOpFactory.h
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoMonOpFactory.h
// (c) GeNeura Team, 1998
/*
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 _EOOPFACTORY_H
#define _EOOPFACTORY_H
#include <eoFactory.h>
#include <eoDup.h>
#include <eoKill.h>
#include <eoTranspose.h>
#include <eoXOver2.h>
//-----------------------------------------------------------------------------
/** EO Factory. An instance of the factory class to create monary operators.
@see eoSelect*/
template< class EOT>
class eoOpFactory: public eoFactory< eoOp<EOT> > {
public:
/// @name ctors and dtors
//{@
/// constructor
eoOpFactory( ) {}
/// destructor
virtual ~eoOpFactory() {}
//@}
/** Another factory method: creates an object from an istream, reading from
it whatever is needed to create the object. Usually, the format for the istream will be\\
objectType parameter1 parameter2 ... parametern\\
If there are problems, an exception is raised; it should be caught at the
upper level, because it might be something for that level
@param _is an stream from where a single line will be read
@throw runtime_exception if the object type is not known
*/
virtual eoOp<EOT>* make(istream& _is) {
eoOp<EOT> * opPtr = NULL;
string objectTypeStr;
_is >> objectTypeStr;
if ( objectTypeStr == "eoDup") {
opPtr = new eoDup<EOT>();
}
if ( objectTypeStr == "eoKill" ) {
opPtr = new eoKill<EOT>( );
}
if ( objectTypeStr == "eoTranspose" ) {
opPtr = new eoTranspose<EOT>( );
}
if ( objectTypeStr == "eoXOver2" ) {
opPtr = new eoXOver2<EOT>( );
}
if ( !opPtr ) {
throw objectTypeStr;
}
return opPtr;
};
};
#endif _EOOPFACTORY_H

View file

@ -0,0 +1,94 @@
/* -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoOpSelector.h
Base class for operator selectors, which return 1 operator according
to some criterium
(c) GeNeura Team 1998, 1999, 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 EOOPSELECTOR_H
#define EOOPSELECTOR_H
//-----------------------------------------------------------------------------
#include <stdexcept> // runtime_error
#include <eoObject.h>
#include <eoPrintable.h>
#include <eoOp.h>
//-----------------------------------------------------------------------------
/** An operator selector is an object that contains a set of EO operators,
and selects one based on whatever criteria. It will be used in the breeder objects.\\
This class is basically a generic interface for operator selection
*/
template<class EOT>
class eoOpSelector: public eoObject, public eoPrintable
{
public:
// Need virtual destructor for derived classes
virtual ~eoOpSelector() {}
/// type of IDs assigned to each operators, used to handle them
typedef unsigned ID;
/** add an operator to the operator set
@param _op a genetic operator, that will be applied in some way
@param _arg the operator rate, usually, or any other argument to the operator
@return an ID that will be used to identify the operator
*/
virtual ID addOp( eoOp<EOT>& _op, float _arg ) = 0;
/** Gets a non-const reference to an operator, so that it can be changed,
modified or whatever
@param _id a previously assigned ID
@throw runtime_exception if the ID does not exist*/
virtual eoOp<EOT>& getOp( ID _id ) = 0;
/** Remove an operator from the operator set
@param _id a previously assigned ID
@throw runtime_exception if the ID does not exist
*/
virtual void deleteOp( ID _id ) = 0;
/// Returns a genetic operator according to the established criteria
virtual eoOp<EOT>* Op() = 0;
/// Methods inherited from eoObject
//@{
/** Return the class id.
@return the class name as a string
*/
virtual string className() const { return "eoOpSelector"; };
/**
* Read object and print objects are left for subclasses to define.
*/
//@}
};
//-----------------------------------------------------------------------------
#endif EO_H

View file

@ -0,0 +1,51 @@
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoProportionalGOpSel.h
Proportional operator selector, selects operators proportionally to its rate
(c) Maarten Keijzer, GeNeura Team 1998, 1999, 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 eoProportionalGOpSel_h
#define eoProportionalGOpSel_h
//-----------------------------------------------------------------------------
#include <eoGOpSelector.h> // eoOpSelector
template <class EOT>
class eoProportionalGOpSel : public eoGOpSelector<EOT>
{
public :
eoProportionalGOpSel() : eoGOpSelector<EOT>() {}
/** Returns the operator proportionally selected */
virtual eoGeneralOp<EOT>& selectOp()
{
unsigned what = rng.roulette_wheel(getRates());
return *operator[](what);
}
///
virtual string className() const { return "eoGOpSelector"; };
};
#endif eoProportionalGOpSel_h

View file

@ -0,0 +1,158 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoProportionalOpSel.h
// (c) GeNeura Team 1998
/*
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 EOPROPORTIONALOPSEL_H
#define EOPROPORTIONALOPSEL_H
//-----------------------------------------------------------------------------
#include <stdexcept> // runtime_error
#include <functional> // greater
#include <map>
// Includes from EO
#include <utils/eoRNG.h>
#include <eoOpSelector.h>
#include <eoOp.h>
//-----------------------------------------------------------------------------
/** This class selects operators according to probability. All operator percentages
should add up to one; if not, an exception will be raised.\\
Operators are represented as pairs (proportion,operator)
*/
template<class EOT>
class eoProportionalOpSel: public eoOpSelector<EOT>,
public multimap<float,eoOp<EOT>*,greater<float> >
{
public:
typedef multimap<float, eoOp<EOT>*,greater<float> > MMF;
/// default ctor
eoProportionalOpSel()
: eoOpSelector<EOT>(), MMF(), opID(1) {};
/// virtual dtor
virtual ~eoProportionalOpSel() {};
/** Gets a non-const reference to an operator, so that it can be changed,
modified or whatever
@param _id a previously assigned ID
@throw runtime_error if the ID does not exist*/
virtual eoOp<EOT>& getOp( ID _id ) {
MMF::iterator i=begin();
ID j = 1;
while ( (i++!=end()) && (j++ != _id) );
if ( i == end() )
throw runtime_error( "No such id in eoProportionalOpSel::op\n" );
return *(i->second);
//return i->second;
}
/** add an operator to the operator set
@param _op a genetic operator, that will be applied in some way
@param _arg an argument to the operator, usually operator rate
@return an ID that will be used to identify the operator
*/
virtual ID addOp( eoOp<EOT>& _op, float _arg ) {
insert( MMF::value_type( _arg,& _op ) );
return opID++;
}
/** Remove an operator from the operator set
@param _id a previously assigned ID
@throw runtime_error if the ID does not exist
*/
virtual void deleteOp( ID _id ) {
unsigned j;
MMF::iterator i;
for ( i=begin(), j=1; i!=end(); i++,j++ ) {
if( j == _id )
erase( i );
return;
}
if ( i == end() )
throw runtime_error( "No such id in eoProportionalOpSel::op\n" );
};
/// Returns a genetic operator according to the established criteria
virtual eoOp<EOT>* Op() {
// Check that all add up to one
float acc = 0;
MMF::iterator i;
unsigned j;
for ( i=begin(), j=1; i!=end(); i++,j++ ) {
acc +=i->first;
}
if ( acc != 1.0 )
throw runtime_error( "Operator rates added up different from 1.0" );
// If here, operators ordered by rate and no problem
float aRnd = rng.uniform();
i=begin();
acc = 0;
do {
acc += i->first;
} while ( (acc <= aRnd ) && (i++!=end() ) );
if ( i == end() )
throw runtime_error( "Operator not found in eoProportionalOpSelector" );
return i->second;
//return i->second;
}
/// Methods inherited from eoObject
//@{
/** Return the class id.
@return the class name as a string
*/
virtual string className() const { return "eoProportionalOpSel"; };
/** Print itself: inherited from eoObject implementation. Declared virtual so that
it can be reimplemented anywhere. Instance from base classes are processed in
base classes, so you don´t have to worry about, for instance, fitness.
@param _s the ostream in which things are written*/
virtual void printOn( ostream& _s ) const{
_s << className().c_str() << endl;
for ( MMF::const_iterator i=begin(); i!=end(); i++ ) {
_s << i->first << "\t" << *(i->second )<< endl;
}
}
//@}
private:
ID opID;
};
//-----------------------------------------------------------------------------
#endif EO_H

View file

@ -0,0 +1,55 @@
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoSequentialGOpSel.h
Sequential Generalized Operator Selector.
(c) Maarten Keijzer (mkeijzer@mad.scientist.com), GeNeura Team 1998, 1999, 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 eoSequentialGOpSel_h
#define eoSequentialGOpSel_h
//-----------------------------------------------------------------------------
#include <eoGOpSelector.h>
/** eoSequentialGOpSel: return a sequence of
operations to be applied one after the other. The order of the
operators is significant. If for instance you first add a
quadratic operator and then a mutation operator,
@see eoGeneralOp, eoCombinedOp
*/
template <class EOT>
class eoSequentialGOpSel : public eoGOpSelector<EOT>
{
public :
virtual eoGeneralOp<EOT>& selectOp()
{
return combined.bind(*this, getRates());
}
private :
eoCombinedOp<EOT> combined;
};
#endif

View file

@ -0,0 +1,84 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoSteadyStateEA.h
// (c) 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 _eoSteadyStateEA_h
#define _eoSteadyStateEA_h
//-----------------------------------------------------------------------------
#include <eoAlgo.h>
#include <eoSteadyStateTransform.h>
/** EOSteadyStateEA:
An easy-to-use evolutionary algorithm, just supply
a general operator selector, a selector for choosing the ones
to reproduce and an eoSteadyStateInserter that takes care of evaluating
and inserter the guy/girl in the steady state population.
*/
template<class EOT> class eoSteadyStateEA: public eoAlgo<EOT>
{
public:
/// Constructor.
eoSteadyStateEA(
eoGOpSelector<EOT>& _opSelector,
eoSelectOne<EOT>& _selector,
eoSteadyStateInserter<EOT>& _inserter,
eoContinue<EOT>& _continuator,
unsigned _steps = 0 )
: step(_opSelector, _selector, _inserter, _steps),
continuator( _continuator)
{};
/// Constructor from an already created generation
eoSteadyStateEA(eoSteadyStateTransform<EOT>& _gen,
eoContinue<EOT>& _continuator):
step(_gen),
continuator( _continuator){};
/// Apply one generation of evolution to the population.
virtual void operator()(eoPop<EOT>& pop) {
do {
try
{
step(pop);
}
catch (exception& e)
{
string s = e.what();
s.append( " in eoSteadyStateEA ");
throw runtime_error( s );
}
} while ( continuator( pop ) );
}
private:
eoSteadyStateTransform<EOT> step;
eoContinue<EOT>& continuator;
};
//-----------------------------------------------------------------------------
#endif eoEasyEA_h

View file

@ -0,0 +1,53 @@
/* -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoSteadyStateInserter.h
Still abstract population insertion operator that is initialized with
and eoEvalFunc object to be able to evaluate individuals before inserting
them.
(c) Maarten Keijzer (mak@dhi.dk) and 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
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 eoSteadyStateInserter_h
#define eoSteadyStateInserter_h
#include <eoEvalFunc.h>
#include <eoInserter.h>
/**
* eoSteadyStateInserter: Interface class that enables an operator to update
* a population with a new individual... it contains an eoEvalFunc derived object to
* make sure that every individual is evaluated before it is inserted
*/
template <class EOT>
class eoSteadyStateInserter : public eoPopInserter<EOT>
{
public :
eoSteadyStateInserter(eoEvalFunc<EOT>& _eval):
eoPopInserter<EOT>(),
eval(_eval) {}
protected :
eoEvalFunc<EOT>& eval;
};
#endif

View file

@ -0,0 +1,88 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoSteadyStateTransform.h
// (c) Maarten Keijzer 2000, GeNeura Team, 1998
/*
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 eoSteadyStateTransform_h
#define eoSteadyStateTransform_h
//-----------------------------------------------------------------------------
#include <eoAlgo.h> // eoPop
#include <eoEvalFunc.h>
#include <eoGOpSelector.h>
#include <eoIndiSelector.h>
#include <eoSteadyStateInserter.h>
//-----------------------------------------------------------------------------
/** eoSteadyStateTransform
* Single step of a steady state evolutionary algorithm.
* Proceeds by updating one individual at a time, by first selecting parents,
* creating one or more children and subsequently overwrite (a) bad individual(s)
*/
template<class EOT> class eoSteadyStateTransform: public eoTransform<EOT>
{
public:
/// Constructor.
eoSteadyStateTransform(
eoGOpSelector<EOT>& _opSelector,
eoSelectOne<EOT>& _selector,
eoSteadyStateInserter<EOT>& _inserter,
unsigned _steps = 0) :
opSelector(_opSelector),
selector(_selector),
inserter(_inserter) ,
steps(_steps) {};
/// Apply one generation of evolution to the population.
virtual void operator()(eoPop<EOT>& pop)
{
unsigned nSteps = steps;
if (nSteps == 0)
{
nSteps = pop.size(); // make a 'generation equivalent'
}
for (unsigned i = 0; i < nSteps; ++i)
{
selector.bind(pop);
inserter.bind(pop);
opSelector.selectOp()(selector, inserter);
}
}
private:
eoGOpSelector<EOT>& opSelector;
eoSelectOneIndiSelector<EOT> selector;
eoSteadyStateInserter<EOT>& inserter;
unsigned steps;
};
//-----------------------------------------------------------------------------
#endif eoGeneration_h

View file

@ -0,0 +1,75 @@
/* -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoStochTournamentInserter.h
Concrete steady state inserter. It is initialized with a population and
inserts individuals in the population based on an inverse stochastic
tournament
(c) Maarten Keijzer (mkeijzer@mad.scientist.com) and 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
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 eoStochTournamentInserter_h
#define eoStochTournamentInserter_h
#include <eoSteadyStateInserter.h>
#include <utils/selectors.h>
/**
\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.
*/
template <class EOT>
class eoStochTournamentInserter : public eoSteadyStateInserter<EOT>
{
public :
eoStochTournamentInserter(eoEvalFunc<EOT>& _eval, double _t_rate):
eoSteadyStateInserter<EOT>(_eval), t_rate(_t_rate)
{
if (t_rate < 0.5)
{ // warning, error?
t_rate = 0.55;
}
if (t_rate >= 1.0)
{
t_rate = 0.99; // 1.0 would mean deterministic tournament
}
}
eoInserter<EOT>& operator()(const EOT& _eot)
{
EOT& eo = inverse_stochastic_tournament<EOT>(pop(), t_rate);
eo = _eot; // overwrite loser of tournament
eo.invalidate();
return *this;
}
string className(void) const { return "eoStochTournamentInserter"; }
private :
double t_rate;
};
#endif

View file

@ -0,0 +1,200 @@
/* -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
eoWrappedOps.h
Derived from the General genetic operator, which can be used to wrap any unary or binary
operator. File also contains the eoCombinedOp, needed by the eoSequentialGOpSelector
(c) Maarten Keijzer (mak@dhi.dk) and 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
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 eoWrappedOps_h
#define eoWrappedOps_h
//-----------------------------------------------------------------------------
#include <eoOp.h> // eoOp, eoMonOp, eoBinOp
#include <utils/eoRNG.h>
using namespace std;
/// Wraps monary operators
template <class EOT>
class eoWrappedMonOp : public eoGeneralOp<EOT>
{
public :
///
eoWrappedMonOp(eoMonOp<EOT>& _op) : eoGeneralOp<EOT>(), op(_op) {};
///
virtual ~eoWrappedMonOp() {}
/// Instantiates the abstract method
void operator()( eoIndiSelector<EOT>& _in,
eoInserter<EOT>& _out)
{
EOT result = _in();
op( result );
_out(result);
}
private :
eoMonOp<EOT>& op;
};
/// Wraps binary operators
template <class EOT>
class eoWrappedBinOp : public eoGeneralOp<EOT>
{
public :
///
eoWrappedBinOp(eoBinOp<EOT>& _op) : eoGeneralOp<EOT>(), op(_op) {}
///
virtual ~eoWrappedBinOp() {}
/// Instantiates the abstract method. EOT should have copy ctor.
void operator()(eoIndiSelector<EOT>& _in,
eoInserter<EOT>& _out)
{
EOT out1 = _in();
const EOT& out2 = _in();
op(out1, out2);
_out(out1);
}
private :
eoBinOp<EOT>& op;
};
/// Wraps Quadratic operators
template <class EOT>
class eoWrappedQuadraticOp : public eoGeneralOp<EOT>
{
public :
///
eoWrappedQuadraticOp(eoQuadraticOp<EOT>& _op) : eoGeneralOp<EOT>(), op(_op) {}
///
virtual ~eoWrappedQuadraticOp() {}
/// Instantiates the abstract method. EOT should have copy ctor.
void operator()(eoIndiSelector<EOT>& _in,
eoInserter<EOT>& _out)
{
EOT out1 = _in();
EOT out2 = _in();
op(out1, out2);
_out(out1)(out2);
}
private :
eoQuadraticOp<EOT>& op;
};
#include <eoBackInserter.h>
template <class EOT>
class eoCombinedOp : public eoGeneralOp<EOT>
{
public :
eoCombinedOp& bind(const std::vector<eoGeneralOp<EOT>*>& _ops, const std::vector<float>& _rates)
{
ops = &_ops;
rates = &_rates;
return *this;
}
class eoDelayedSelector : public eoIndiSelector<EOT>
{
public :
eoDelayedSelector(eoIndiSelector<EOT>& _select, const eoPop<EOT>& _pop) : select(_select), pop(_pop), it(pop.begin()) {}
unsigned size() const { return select.size();}
const EOT& operator[](size_t i) const { return select[i]; }
/// will first dispense all previously selected individuals before returning new ones
const EOT& operator()(void)
{
if (it == pop.end())
{
return select();
}
// else
return *it++;
}
eoPop<EOT>::const_iterator get_it(void) const { return it; }
private :
eoIndiSelector<EOT>& select;
const eoPop<EOT>& pop;
eoPop<EOT>::const_iterator it;
};
/** Applies all ops in the combined op
It first applies the
*/
void operator()( eoIndiSelector<EOT>& _in,
eoInserter<EOT>& _out )
{
eoPop<EOT> intermediate;
eoPop<EOT> next;
unsigned i;
for (i = 0; i < ops->size(); ++i)
{
eoDelayedSelector delay(_in, intermediate);
inserter.bind(next);
unsigned counter = 0;
// apply operators until we have as many outputs as inputs
do
{
if (rng.flip(rates->operator[](i))) // should this flip be here?
(*ops->operator[](i))(delay, inserter);
counter++;
if (counter > 1000)
{
throw logic_error("eoCombinedOp: no termination after 1000 tries, did you forget to insert individuals in your eoGeneralOp?");
}
}
while (next.size() < intermediate.size());
intermediate.swap(next);
next.resize(0);
}
// after last swap, results can be found in intermediate
for (i = 0; i < intermediate.size(); ++i)
_out(intermediate[i]);
}
private :
const std::vector<eoGeneralOp<EOT>*>* ops;
const std::vector<float>* rates;
eoBackInserter<EOT> inserter;
};
#endif