//----------------------------------------------------------------------------- // eoBreeder.h //----------------------------------------------------------------------------- #ifndef eoBreeder_h #define eoBreeder_h //----------------------------------------------------------------------------- #include // vector #include #include // eoUniform #include // eoOp, eoMonOp, eoBinOp #include // eoPop #include // eoTransform #include // eoOpSelector #include #include "eoRng.h" using namespace std; /***************************************************************************** * eoBreeder: transforms a population using genetic operators. * * For every operator there is a rated to be applyed. * *****************************************************************************/ template class eoGeneralOp: public eoOp { public: eoGeneralOp() :eoOp( Nary ) {}; virtual ~eoGeneralOp () {}; virtual void operator()( vector _in, OutIt _out) const = 0; virtual int nInputs(void) const = 0; virtual int nOutputs(void) const = 0; // no support for 2 -> 2 xover virtual string className() const {return "eoGeneralOp";}; }; template class eoWrappedMonOp : public eoGeneralOp { public : eoWrappedMonOp(const eoMonOp& _op) : eoGeneralOp(), op(_op) {} virtual ~eoWrappedMonOp() {} void operator()( vector _in, OutIt _out) const { *_out = *_in[0]; op(*_out ); } int nInputs(void) const { return 1; } int nOutputs(void) const { return 1; } virtual string className() const {return "eoWrappedOp";}; private : const eoMonOp& op; }; template class eoWrappedBinOp : public eoGeneralOp { public : eoWrappedBinOp(const eoBinOp& _op) : eoGeneralOp(), op(_op) {} virtual ~eoWrappedBinOp() {} void operator()( vector _in, OutIt _out) const { *_out = *_in[0]; *(_out + 1) = *_in[1]; op(*_out, *(_out + 1)); } int nInputs(void) const { return 2; } int nOutputs(void) const { return 2; } // Yup, due to the bad design, can't choose between outputting 1 or 2 virtual string className() const {return "eoWrappedOp";}; private : const eoBinOp& op; }; template class eoCombinedOp : public eoGeneralOp { public : eoCombinedOp() : eoGeneralOp(), arity(0) {} virtual ~eoCombinedOp() {} int nInputs(void) const { return arity; } int nOutputs(void) const { return 1; } void addOp(eoGeneralOp* _op) { ops.push_back(_op); arity = arity < _op->nInputs()? _op->nInputs() : arity; } void clear(void) { ops.resize(0); } void operator()( vector _in, OutIt _out) const { for (int i = 0; i < ops.size(); ++i) { (*ops[i])(_in, _out); _in[0] = &*_out; } } private : vector* > ops; int arity; }; template class eoAltOpSelector: public eoOpSelector, public vector*> { public: virtual ID addOp( eoOp& _op, float _arg ) { eoGeneralOp* op = dynamic_cast*>(&_op); if (op == 0) { switch(_op.readArity()) { case unary : oplist.push_back(auto_ptr >(new eoWrappedMonOp(static_cast&>(_op)))); op = oplist.back().get(); break; case binary : oplist.push_back(auto_ptr >(new eoWrappedBinOp(static_cast&>(_op)))); op = oplist.back().get(); break; } } iterator result = find(begin(), end(), (eoGeneralOp*) 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; } virtual const eoOp& getOp( ID _id ) { return *operator[](_id); } virtual void deleteOp( ID _id ) { operator[](_id) = 0; // TODO, check oplist and clear it there too. rates[_id] = 0.0; } virtual eoOp* Op() { return &selectOp(); } virtual eoGeneralOp& selectOp() = 0; virtual string className() const { return "eoAltOpSelector"; }; void printOn(ostream& _os) const {} protected : vector rates; list > > oplist; }; template class eoProportionalOpSelector : public eoAltOpSelector { public : eoProportionalOpSelector() : eoAltOpSelector() {} virtual eoGeneralOp& selectOp() { int what = rng.roulette_wheel(rates); return *operator[](what); } }; template class eoSequentialOpSelector : public eoAltOpSelector { public : eoSequentialOpSelector() : eoAltOpSelector() {} virtual eoGeneralOp& selectOp() { for (int i = 0; i < size(); ++i) { if (operator[](i) == 0) continue; if (rng.flip(rates[i])) combined.addOp(operator[](i)); } return combined; } private : eoCombinedOp combined; }; template class eoRandomIndy // living in a void right now { public : eoRandomIndy() {} vector operator()(int _n, eoPop::iterator _begin, eoPop::iterator _end) { vector result(_n); for (int i = 0; i < result.size(); ++i) { result[i] = &*(_begin + rng.random(_end - _begin)); } return result; } }; template class eoAltBreeder: public eoTransform { public: typedef eoPop::reverse_iterator outIt; /// Default constructor. eoAltBreeder( eoAltOpSelector& _opSel): opSel( _opSel ) {} /// Destructor. virtual ~eoAltBreeder() {} /** * Enlarges the population. * @param pop The population to be transformed. */ void operator()(eoPop& pop) { int size = pop.size(); for (unsigned i = 0; i < size; i++) { eoGeneralOp& op = opSel.selectOp(); pop.resize(pop.size() + op.nOutputs()); vector indies = indySelector(op.nInputs(), pop.begin(), pop.begin() + size); op(indies, pop.rbegin()); } } /// The class name. string classname() const { return "eoAltBreeder"; } private: eoAltOpSelector& opSel; eoRandomIndy indySelector; }; #endif eoBreeder_h