Well, what do you know, major commit.
Changed the signature of eoMon, eoBin and eoQuadOp to return a bool, without invalidating fitness. Added a set of invalidators to take over that job (see for instance eoSGA and eoSGATransform how this can transparantly used) Derived eoState from eoFunctorStore (for convenience, from a design perspective this may sound wrong) Added a wrap_op function that does the wrapping for you (see eoOpContainer how this made this functor exceedingly less hairy). Checked all the tests removed the eoGeneric*Op family (not needed anymore) and of course changed all the operators to reflect the change (and found a few that didn't invalidate the fitness, thus really pointing out the advantage of the current approach)
This commit is contained in:
parent
17d55ae92b
commit
3a9b5a0e7e
30 changed files with 651 additions and 564 deletions
|
|
@ -1,9 +1,9 @@
|
|||
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// eoGenOp.h
|
||||
// eoGenOp.h
|
||||
// (c) Maarten Keijzer and Marc Schoenauer, 2001
|
||||
/*
|
||||
/*
|
||||
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
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
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: mkeijzer@dhi.dk
|
||||
Contact: mak@dhi.dk
|
||||
Marc.Schoenauer@polytechnique.fr
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
#include <eoOp.h>
|
||||
#include <eoPopulator.h>
|
||||
|
||||
#include <eoFunctorStore.h>
|
||||
|
||||
/** @name General variation operators
|
||||
|
||||
|
|
@ -41,15 +41,22 @@ thanks to the friend class eoPopulator
|
|||
|
||||
|
||||
/** The base class for General Operators
|
||||
Subclass this operator is you want to define an operator that falls
|
||||
outside of the eoMonOp, eoBinOp, eoQuadOp classification. The argument
|
||||
the operator will receive is an eoPopulator, which is a wrapper around
|
||||
the original population, is an instantiation of the next population and
|
||||
has often a selection function embedded in it to select new individuals.
|
||||
|
||||
Note that the actual work is performed in the apply function.
|
||||
*/
|
||||
template <class EOT>
|
||||
class eoGenOp : public eoOp<EOT>, public eoUF<eoPopulator<EOT> &, void>
|
||||
{
|
||||
public :
|
||||
/// Ctor that honors its superclass
|
||||
eoGenOp(): eoOp<EOT>( eoOp<EOT>::general ) {}
|
||||
eoGenOp(): eoOp<EOT>( eoOp<EOT>::general ) {}
|
||||
|
||||
virtual unsigned max_production(void) = 0;
|
||||
virtual unsigned max_production(void) = 0;
|
||||
virtual string className() = 0;
|
||||
void operator()(eoPopulator<EOT>& _pop)
|
||||
{
|
||||
|
|
@ -57,6 +64,7 @@ class eoGenOp : public eoOp<EOT>, public eoUF<eoPopulator<EOT> &, void>
|
|||
apply(_pop);
|
||||
}
|
||||
|
||||
|
||||
protected :
|
||||
/** the function that will do the work
|
||||
*/
|
||||
|
|
@ -75,7 +83,8 @@ class eoMonGenOp : public eoGenOp<EOT>
|
|||
|
||||
void apply(eoPopulator<EOT>& _it)
|
||||
{
|
||||
op(*_it); // look how simple
|
||||
if (op(*_it))
|
||||
(*_it).invalidate(); // look how simple
|
||||
|
||||
}
|
||||
string className() {return op.className();}
|
||||
|
|
@ -101,8 +110,9 @@ class eoBinGenOp : public eoGenOp<EOT>
|
|||
{
|
||||
EOT& a = *_pop;
|
||||
EOT& b = *++_pop;
|
||||
op(a, b);
|
||||
_pop.erase();
|
||||
if (op(a, b))
|
||||
a.invalidate();
|
||||
_pop.erase(); // erase the b from the next population
|
||||
}
|
||||
string className() {return op.className();}
|
||||
|
||||
|
|
@ -115,17 +125,18 @@ template <class EOT>
|
|||
class eoSelBinGenOp : public eoGenOp<EOT>
|
||||
{
|
||||
public:
|
||||
eoSelBinGenOp(eoBinOp<EOT>& _op, eoSelectOne<EOT>& _sel) :
|
||||
eoSelBinGenOp(eoBinOp<EOT>& _op, eoSelectOne<EOT>& _sel) :
|
||||
op(_op), sel(_sel) {}
|
||||
|
||||
|
||||
unsigned max_production(void) { return 1; }
|
||||
|
||||
|
||||
void apply(eoPopulator<EOT>& _pop)
|
||||
{ // _pop.source() gets the original population, an eoVecOp can make use of this as well
|
||||
op(*_pop, sel(_pop.source()));
|
||||
if (op(*_pop, sel(_pop.source())))
|
||||
(*_pop).invalidate();
|
||||
}
|
||||
string className() {return op.className();}
|
||||
|
||||
|
||||
private :
|
||||
eoBinOp<EOT>& op;
|
||||
eoSelectOne<EOT>& sel;
|
||||
|
|
@ -147,7 +158,11 @@ class eoQuadGenOp : public eoGenOp<EOT>
|
|||
EOT& a = *_pop;
|
||||
EOT& b = *++_pop;
|
||||
|
||||
op(a, b);
|
||||
if(op(a, b))
|
||||
{
|
||||
a.invalidate();
|
||||
b.invalidate();
|
||||
}
|
||||
}
|
||||
string className() {return op.className();}
|
||||
|
||||
|
|
@ -155,6 +170,41 @@ class eoQuadGenOp : public eoGenOp<EOT>
|
|||
eoQuadOp<EOT>& op;
|
||||
};
|
||||
|
||||
/**
|
||||
Factory function for automagically creating references to an
|
||||
eoGenOp object. Useful when you are too lazy to figure out
|
||||
which wrapper belongs to which operator. The memory allocated
|
||||
in the wrapper will be stored in a eoFunctorStore (eoState derives from this).
|
||||
Therefore the memory will only be freed when the eoFunctorStore is deleted.
|
||||
Make very sure that you are not using these wrappers after this happens.
|
||||
|
||||
You can use this function 'wrap_op' in the following way. Suppose you've
|
||||
created an eoQuadOp<EOT> called my_quad, and you want to feed it to an eoTransform
|
||||
derived class that expects an eoGenOp<EOT>. If you have an eoState lying around
|
||||
(which is generally a good idea) you can say:
|
||||
|
||||
eoDerivedTransform<EOT> trans(eoGenOp<EOT>::wrap_op(my_quad, state), ...);
|
||||
|
||||
And as long as your state is not destroyed (by going out of scope for example,
|
||||
your 'trans' functor will be usefull.
|
||||
|
||||
As a final note, you can also enter an eoGenOp as the argument. It will
|
||||
not allocate memory then. This to make it even easier to use the wrap_op function.
|
||||
For an example of how this is used, check the eoOpContainer class.
|
||||
|
||||
@see eoOpContainer
|
||||
*/
|
||||
template <class EOT>
|
||||
eoGenOp<EOT>& wrap_op(eoOp<EOT>& _op, eoFunctorStore& _store)
|
||||
{
|
||||
switch(_op.getType())
|
||||
{
|
||||
case eoOp<EOT>::unary : return _store.storeFunctor(new eoMonGenOp<EOT>(static_cast<eoMonOp<EOT>&>(_op)));
|
||||
case eoOp<EOT>::binary : return _store.storeFunctor(new eoBinGenOp<EOT>(static_cast<eoBinOp<EOT>&>(_op)));
|
||||
case eoOp<EOT>::quadratic : return _store.storeFunctor(new eoQuadGenOp<EOT>(static_cast<eoQuadOp<EOT>&>(_op)));
|
||||
case eoOp<EOT>::general : return static_cast<eoGenOp<EOT>&>(_op);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue