diff --git a/eo/src/eoAlgoFoundry.h b/eo/src/eoAlgoFoundry.h index b9e4eb638..9c815e157 100644 --- a/eo/src/eoAlgoFoundry.h +++ b/eo/src/eoAlgoFoundry.h @@ -25,7 +25,88 @@ #include -/** +/** A vector of eoForge which hold an index. + * + * To be used in conjunction with a subclass of an eoAlgoFoundry, + * where it can store all the alternative operators + * and hold the link to the encoding. @see eoAlgoFoundryEA + * + * As with eoForgeVector, adding a managed operator + *is done through public member variable's `add` method, + * which takes the class name as template and its constructor's parameters + * as arguments. For example: + * @code + * eoOperatorFoundry< eoSelectOne > selectors; + * selectors.add< eoStochTournamentSelect >( 0.5 ); + * @endcode + * + * @warning If the managed constructor takes a reference YOU SHOULD ABSOLUTELY wrap it + * in a `std::ref` when using `add` or `setup`, or it will silently be passed as a copy, + * which would effectively disable any link between operators. + * + * @ingroup Core + * @ingroup Foundry + */ +template +class eoOperatorFoundry : public eoForgeVector< Itf > +{ + public: + eoOperatorFoundry(size_t encoding_index, bool always_reinstantiate = true ) : + eoForgeVector(always_reinstantiate), + _index(encoding_index) + { } + + size_t index() const { return _index; } + + protected: + size_t _index; +}; + + +/** Interface of a Foundry: a class that instantiate an eoAlgo on-the-fly, given a choice of its operators. + * + * The chosen operators are encoded in a vector of indices. + * + * The foundry subclass should first be set up with sets of operators of the same interface, + * held within an eoOperatorFoundry member. + * @code + * eoOperatorFoundry< eoSelectOne > selectors; + * @endcode + * + * In a second step, the operators to be used should be selected + * by indicating their index, just like if the foundry was a array: + * @code + * foundry = {0, 1, 2}; + * // ^ ^ ^ + * // | | | + * // | | + 3d operator + * // | + 2d operator + * // + 1st operator + * @endcode + * + * If you don't (want to) recall the order of the operators in the encoding, + * you can use the `index()` member of eoOperatorFoundry, for example: + * @code + * foundry.at(foundry.continuators.index()) = 2; // select the third continuator + * @endcode + * + * Now, you must implement the foundry just like any eoAlgo, by using the eoPop interface: + * @code + * foundry(pop); + * @encode + * It will instantiate the needed operators (only) and the algorithm itself on-the-fly, + * and then run it. + * + * @note: Thanks to the underlying eoOperatorFoundry, not all the added operators are instantiated. + * Every instantiation is deferred upon actual use. That way, you can still reconfigure them + * at any time with `eoForgeOperator::setup`, for example: + * @code + * foundry.selector.at(0).setup(0.5); // using constructor's arguments + * @endcode + * + * @warning If the managed constructor takes a reference YOU SHOULD ABSOLUTELY wrap it + * in a `std::ref` when using `add` or `setup`, or it will silently be passed as a copy, + * which would effectively disable any link between operators. * * @ingroup Core * @ingroup Foundry @@ -43,6 +124,8 @@ class eoAlgoFoundry : public eoAlgo { } /** Select indices of all the operators. + * + * i.e. Select an algorithm to instantiate. */ void select( std::vector encoding ) { @@ -62,6 +145,8 @@ class eoAlgoFoundry : public eoAlgo return _size; } + /** Return the underlying encoding vector. + */ std::vector encoding() const { return _encoding; diff --git a/eo/src/eoAlgoFoundryEA.h b/eo/src/eoAlgoFoundryEA.h index 4f07c2c55..264072d2d 100644 --- a/eo/src/eoAlgoFoundryEA.h +++ b/eo/src/eoAlgoFoundryEA.h @@ -57,20 +57,20 @@ * @note: by default, the firsts of the five operators are selected. * * If you don't (want to) recall the order of the operators in the encoding, - * you can use the `index_of` member, for example: + * you can use the `index()` member, for example: * @code - * foundry.at(foundry.index_of.continuators) = 2; // select the third continuator + * foundry.at(foundry.continuators.index()) = 2; // select the third continuator * @endcode * * Now, you can call the fourdry just like any eoAlgo, by passing it an eoPop: * @code * foundry(pop); * @encode - * It will instanciate the needed operators (only) and the algorithm itself on-the-fly, + * It will instantiate the needed operators (only) and the algorithm itself on-the-fly, * and then run it. * - * @note: Thanks to the underlying eoForgeVector, not all the added operators are instanciated. - * Every instanciation is deferred upon actual use. That way, you can still reconfigure them + * @note: Thanks to the underlying eoOperatorFoundry, not all the added operators are instantiated. + * Every instantiation is deferred upon actual use. That way, you can still reconfigure them * at any time with `eoForgeOperator::setup`, for example: * @code * foundry.selector.at(0).setup(0.5); // using constructor's arguments @@ -88,47 +88,34 @@ class eoAlgoFoundryEA : public eoAlgoFoundry */ eoAlgoFoundryEA( eoPopEvalFunc& eval, size_t max_gen ) : eoAlgoFoundry(5), - index_of(), - continuators(true), // Always re-instanciate continuators, because they hold a state. - crossovers(false), - mutations(false), - selectors(false), - replacements(false), + continuators(0, true), // Always re-instantiate continuators, because they hold a state. + crossovers(1, false), + mutations(2, false), + selectors(3, false), + replacements(4, false), _eval(eval), _max_gen(max_gen) { } public: - struct Indices - { - static const size_t continuators = 0; - static const size_t crossovers = 1; - static const size_t mutations = 2; - static const size_t selectors = 3; - static const size_t replacements = 4; - }; - - /** Helper for keeping track of the indices of the underlying encoding. */ - const Indices index_of; - /* Operators containers @{ */ - eoForgeVector< eoContinue > continuators; - eoForgeVector< eoQuadOp > crossovers; - eoForgeVector< eoMonOp > mutations; - eoForgeVector< eoSelectOne > selectors; - eoForgeVector< eoReplacement > replacements; + eoOperatorFoundry< eoContinue > continuators; + eoOperatorFoundry< eoQuadOp > crossovers; + eoOperatorFoundry< eoMonOp > mutations; + eoOperatorFoundry< eoSelectOne > selectors; + eoOperatorFoundry< eoReplacement > replacements; /* @} */ - /** Instanciate and call the pre-selected algorithm. + /** instantiate and call the pre-selected algorithm. */ void operator()(eoPop& pop) { - assert(continuators.size() > 0); assert(this->at(index_of.continuators) < continuators.size()); - assert( crossovers.size() > 0); assert(this->at(index_of.crossovers) < crossovers.size()); - assert( mutations.size() > 0); assert(this->at(index_of.mutations) < mutations.size()); - assert( selectors.size() > 0); assert(this->at(index_of.selectors) < selectors.size()); - assert(replacements.size() > 0); assert(this->at(index_of.replacements) < replacements.size()); + assert(continuators.size() > 0); assert(this->at(continuators.index()) < continuators.size()); + assert( crossovers.size() > 0); assert(this->at( crossovers.index()) < crossovers.size()); + assert( mutations.size() > 0); assert(this->at( mutations.index()) < mutations.size()); + assert( selectors.size() > 0); assert(this->at( selectors.index()) < selectors.size()); + assert(replacements.size() > 0); assert(this->at(replacements.index()) < replacements.size()); eoSequentialOp variator; variator.add(this->crossover(), 1.0); @@ -153,11 +140,11 @@ class eoAlgoFoundryEA : public eoAlgoFoundry std::string name() { std::ostringstream name; - name << this->at(index_of.continuators) << " (" << this->continuator().className() << ") + "; - name << this->at(index_of.crossovers) << " (" << this->crossover().className() << ") + "; - name << this->at(index_of.mutations) << " (" << this->mutation().className() << ") + "; - name << this->at(index_of.selectors) << " (" << this->selector().className() << ") + "; - name << this->at(index_of.replacements) << " (" << this->replacement().className() << ")"; + name << this->at(continuators.index()) << " (" << this->continuator().className() << ") + "; + name << this->at(crossovers.index()) << " (" << this->crossover().className() << ") + "; + name << this->at(mutations.index()) << " (" << this->mutation().className() << ") + "; + name << this->at(selectors.index()) << " (" << this->selector().className() << ") + "; + name << this->at(replacements.index()) << " (" << this->replacement().className() << ")"; return name.str(); } @@ -168,32 +155,32 @@ class eoAlgoFoundryEA : public eoAlgoFoundry public: eoContinue& continuator() { - assert(this->at(index_of.continuators) < continuators.size()); - return continuators.instanciate(this->at(index_of.continuators)); + assert(this->at(continuators.index()) < continuators.size()); + return continuators.instantiate(this->at(continuators.index())); } eoQuadOp& crossover() { - assert(this->at(index_of.crossovers) < crossovers.size()); - return crossovers.instanciate(this->at(index_of.crossovers)); + assert(this->at(crossovers.index()) < crossovers.size()); + return crossovers.instantiate(this->at(crossovers.index())); } eoMonOp& mutation() { - assert(this->at(index_of.mutations) < mutations.size()); - return mutations.instanciate(this->at(index_of.mutations)); + assert(this->at(mutations.index()) < mutations.size()); + return mutations.instantiate(this->at(mutations.index())); } eoSelectOne& selector() { - assert(this->at(index_of.selectors) < selectors.size()); - return selectors.instanciate(this->at(index_of.selectors)); + assert(this->at(selectors.index()) < selectors.size()); + return selectors.instantiate(this->at(selectors.index())); } eoReplacement& replacement() { - assert(this->at(index_of.replacements) < replacements.size()); - return replacements.instanciate(this->at(index_of.replacements)); + assert(this->at(replacements.index()) < replacements.size()); + return replacements.instantiate(this->at(replacements.index())); } }; diff --git a/eo/src/eoEvalFoundryEA.h b/eo/src/eoEvalFoundryEA.h index 89145d822..f3b33cba5 100644 --- a/eo/src/eoEvalFoundryEA.h +++ b/eo/src/eoEvalFoundryEA.h @@ -62,14 +62,22 @@ public: _subpb_eval(subpb_eval), _foundry(foundry), _penalization(penalization), - _pop_size(pop_size) + _pop_size(pop_size), + i_cont(foundry.continuators.index()), + i_cros(foundry.crossovers.index()), + i_muta(foundry.mutations.index()), + i_sele(foundry.selectors.index()), + i_repl(foundry.replacements.index()) { } - static const size_t i_cont = eoAlgoFoundryEA::Indices::continuators; - static const size_t i_cros = eoAlgoFoundryEA::Indices::crossovers ; - static const size_t i_muta = eoAlgoFoundryEA::Indices::mutations ; - static const size_t i_sele = eoAlgoFoundryEA::Indices::selectors ; - static const size_t i_repl = eoAlgoFoundryEA::Indices::replacements; +protected: + const size_t i_cont; + const size_t i_cros; + const size_t i_muta; + const size_t i_sele; + const size_t i_repl; + +public: /** Decode the high-level problem encoding as an array of indices. * diff --git a/eo/src/eoForge.h b/eo/src/eoForge.h index f00d11e09..f4834e900 100644 --- a/eo/src/eoForge.h +++ b/eo/src/eoForge.h @@ -60,9 +60,9 @@ * Tools for automatic algorithms assembling, selection and search. */ -/** Interface for a "Forge": a class that can defer instanciation of EO's operator. +/** Interface for a "Forge": a class that can defer instantiation of EO's operator. * - * This interface only declares an `instanciate` method, + * This interface only declares an `instantiate` method, * in order to be able to make containers of factories (@see eoForgeOperator). * * @ingroup Core @@ -72,15 +72,15 @@ template class eoForgeInterface { public: - virtual Itf& instanciate(bool no_cache = true) = 0; + virtual Itf& instantiate(bool no_cache = true) = 0; virtual ~eoForgeInterface() {} }; -/** This "Forge" can defer the instanciation of an EO's operator. +/** This "Forge" can defer the instantiation of an EO's operator. * * It allows to decouple the constructor's parameters setup from its actual call. * You can declare a parametrized operator at a given time, - * then actually instanciate it (with the given interface) at another time. + * then actually instantiate it (with the given interface) at another time. * * This allows for creating containers of pre-parametrized operators (@see eoForgeVector). * @@ -91,13 +91,13 @@ class eoForgeInterface * * @code eoForgeOperator,eoRankMuSelect> forge(mu); - // ^ desired ^ to-be-instanciated ^ operator's + // ^ desired ^ to-be-instantiated ^ operator's // interface operator parameters - // Actual instanciation: - eoSelect& select = forge.instanciate(); + // Actual instantiation: + eoSelect& select = forge.instantiate(); * @endcode * - * @warning You may want to enable instanciation cache to grab some performances. + * @warning You may want to enable instantiation cache to grab some performances. * The default is set to disable the cache, because its use with operators * which hold a state will lead to unwanted behaviour. * @@ -111,10 +111,10 @@ class eoForgeOperator : public eoForgeInterface template eoForgeOperator(Args2... args) : _args(std::forward(args)...), - _instanciated(nullptr) + _instantiated(nullptr) { } - /** Instanciate the managed operator class. + /** instantiate the managed operator class. * * That is call its constructor with the set up arguments. * @@ -122,20 +122,20 @@ class eoForgeOperator : public eoForgeInterface * * @param no_cache If false, will enable caching previous instances. */ - Itf& instanciate(bool no_cache = true) + Itf& instantiate(bool no_cache = true) { - if(no_cache or not _instanciated) { - if(_instanciated) { - delete _instanciated; + if(no_cache or not _instantiated) { + if(_instantiated) { + delete _instantiated; } - _instanciated = op_constructor(_args); + _instantiated = op_constructor(_args); } - return *_instanciated; + return *_instantiated; } virtual ~eoForgeOperator() { - delete _instanciated; + delete _instantiated; } protected: @@ -152,7 +152,7 @@ class eoForgeOperator : public eoForgeInterface /** @} */ protected: - Itf* _instanciated; + Itf* _instantiated; }; /** Partial specialization for constructors without any argument. @@ -162,30 +162,30 @@ class eoForgeOperator : public eoForgeInterface { public: eoForgeOperator() : - _instanciated(nullptr) + _instantiated(nullptr) { } - Itf& instanciate( bool no_cache = true ) + Itf& instantiate( bool no_cache = true ) { - if(no_cache or not _instanciated) { - if(_instanciated) { - delete _instanciated; + if(no_cache or not _instantiated) { + if(_instantiated) { + delete _instantiated; } - _instanciated = new Op; + _instantiated = new Op; } - return *_instanciated; + return *_instantiated; } virtual ~eoForgeOperator() { - delete _instanciated; + delete _instantiated; } protected: - Itf* _instanciated; + Itf* _instantiated; }; -/** A vector holding an operator with deferred instanciation at a given index. +/** A vector holding an operator with deferred instantiation at a given index. * * @note You can actually store several instances of the same class, * with different parametrization (or not). @@ -195,19 +195,19 @@ class eoForgeOperator : public eoForgeInterface * This is is a source of bug which your compiler will to detect and that would * disable any link between operators. * - * @warning You may want to enable instanciation cache to grab some performances. + * @warning You may want to enable instantiation cache to grab some performances. * The default is set to disable the cache, because its use with operators * which hold a state will lead to unwanted behaviour. * * @code eoForgeVector> factories(false); - // Capture constructor's parameters and defer instanciation. + // Capture constructor's parameters and defer instantiation. factories.add>(1); factories.setup>(0, 5); // Edit - // Actually instanciate. - eoSelect& op = factories.instanciate(0); + // Actually instantiate. + eoSelect& op = factories.instantiate(0); // Call. op(); @@ -219,11 +219,11 @@ template class eoForgeVector : public std::vector*> { public: - /** Default constructor do not cache instanciations. + /** Default constructor do not cache instantiations. * * @warning * You most probably want to disable caching for operators that hold a state. - * If you enable the cache, the last used instanciation will be used, + * If you enable the cache, the last used instantiation will be used, * at its last state. * For example, continuators should most probably not be cached, * as they very often hold a state in the form of a counter. @@ -231,10 +231,10 @@ class eoForgeVector : public std::vector*> * and thus always ask for a stop. * Reusing an instance in this state will de facto disable further searches. * - * @param always_reinstanciate If false, will enable cache for the forges in this container. + * @param always_reinstantiate If false, will enable cache for the forges in this container. */ - eoForgeVector( bool always_reinstanciate = true ) : - _no_cache(always_reinstanciate) + eoForgeVector( bool always_reinstantiate = true ) : + _no_cache(always_reinstantiate) { } /** Add an operator to the list. @@ -294,11 +294,11 @@ class eoForgeVector : public std::vector*> this->at(index) = pfo; } - /** Instanciate the operator managed at the given index. + /** instantiate the operator managed at the given index. */ - Itf& instanciate(size_t index) + Itf& instantiate(size_t index) { - return this->at(index)->instanciate(_no_cache); + return this->at(index)->instantiate(_no_cache); } virtual ~eoForgeVector() diff --git a/eo/src/es/eoReal.h b/eo/src/es/eoReal.h index dc6d51126..440234f60 100644 --- a/eo/src/es/eoReal.h +++ b/eo/src/es/eoReal.h @@ -39,6 +39,7 @@ template class eoReal: public eoVector { public: + using FitnessType = FitT; /** * (Default) Constructor. diff --git a/eo/test/t-algo-forged.cpp b/eo/test/t-algo-forged.cpp index 7b31b6e69..b2f6b4d46 100644 --- a/eo/test/t-algo-forged.cpp +++ b/eo/test/t-algo-forged.cpp @@ -77,11 +77,11 @@ int main(int /*argc*/, char** /*argv*/) pop.append(pop_size, init); eval(pop,pop); - foundry.at(foundry.index_of.continuators) = i_cont; - foundry.at(foundry.index_of.crossovers) = i_cross; - foundry.at(foundry.index_of.mutations) = i_mut; - foundry.at(foundry.index_of.selectors) = i_sel; - foundry.at(foundry.index_of.replacements) = i_rep; + foundry.at(foundry.continuators.index()) = i_cont; + foundry.at(foundry.crossovers.index()) = i_cross; + foundry.at(foundry.mutations.index()) = i_mut; + foundry.at(foundry.selectors.index()) = i_sel; + foundry.at(foundry.replacements.index()) = i_rep; // Or, if you know the order. foundry.select({i_cont, i_cross, i_mut, i_sel, i_rep}); diff --git a/eo/test/t-forge-algo.cpp b/eo/test/t-forge-algo.cpp index f654723c8..e4f713cff 100644 --- a/eo/test/t-forge-algo.cpp +++ b/eo/test/t-forge-algo.cpp @@ -54,19 +54,19 @@ int main(int /*argc*/, char** /*argv*/) std::string best_algo = ""; for(auto& forge_cont : continuators) { - auto& continuator = forge_cont->instanciate(); + auto& continuator = forge_cont->instantiate(); for(auto& forge_cross : crossovers) { - auto& crossover = forge_cross->instanciate(); + auto& crossover = forge_cross->instantiate(); for(auto& forge_mut : mutations ) { - auto& mutation = forge_mut->instanciate(); + auto& mutation = forge_mut->instantiate(); for(auto& forge_sel : selectors) { - auto& selector = forge_sel->instanciate(); + auto& selector = forge_sel->instantiate(); for(auto& forge_rep : replacors) { - auto& replacor = forge_rep->instanciate(); + auto& replacor = forge_rep->instantiate(); std::ostringstream algo_name; algo_name << continuator.className() << " + " diff --git a/eo/test/t-operator-forge.cpp b/eo/test/t-operator-forge.cpp index 1e38305c6..013e11696 100644 --- a/eo/test/t-operator-forge.cpp +++ b/eo/test/t-operator-forge.cpp @@ -28,14 +28,14 @@ int main(int /*argc*/, char** /*argv*/) // Forge container using indices. eoForgeVector indexed_factories; - // Capture constructor's parameters and defer instanciation. + // Capture constructor's parameters and defer instantiation. indexed_factories.add("I'm A"); indexed_factories.setup(0, "I'm actually A"); // Edit indexed_factories.add("I'm B", " prime"); indexed_factories.add("I'm a B", " junior"); - // Actually instanciante and call. - indexed_factories.instanciate(0)(); - indexed_factories.instanciate(1)(); - indexed_factories.instanciate(2)(); + // Actually instantiante and call. + indexed_factories.instantiate(0)(); + indexed_factories.instantiate(1)(); + indexed_factories.instantiate(2)(); }