From 11ff72bdd97768cbc99d5ad243938a185c096afe Mon Sep 17 00:00:00 2001 From: nojhan Date: Sun, 12 Apr 2020 16:26:37 +0200 Subject: [PATCH] fix: refactor foundry to be more dynamic than static - Remove size template in favor of dynamic container: allow using the generic interface. - Using `operator=` was inducing slicing. --- eo/src/eoAlgoFoundry.h | 31 ++++++++------- eo/src/eoAlgoFoundryEA.h | 66 ++++++++++++++++---------------- eo/src/eoEvalFoundryEA.h | 6 ++- eo/test/t-algo-forged-search.cpp | 8 ++-- eo/test/t-algo-forged.cpp | 2 +- 5 files changed, 57 insertions(+), 56 deletions(-) diff --git a/eo/src/eoAlgoFoundry.h b/eo/src/eoAlgoFoundry.h index e7d067cc2..19a3a4692 100644 --- a/eo/src/eoAlgoFoundry.h +++ b/eo/src/eoAlgoFoundry.h @@ -23,8 +23,7 @@ #ifndef _eoAlgoFoundry_H_ #define _eoAlgoFoundry_H_ -#include -#include +#include /** * @@ -32,18 +31,23 @@ * @ingroup Foundry * @ingroup Algorithms */ -template +template class eoAlgoFoundry : public eoAlgo { public: - static const size_t dim = NBOP; - - /** The constructon only take an eval, because all other operators - * are stored in the public containers. + /** */ - eoAlgoFoundry() + eoAlgoFoundry( size_t nb_operators ) : + _size(nb_operators), + _encoding(_size,0) + { } + + /** Select indices of all the operators. + */ + void select( std::vector encoding ) { - _encoding = { 0 }; // dim * 0 + assert(encoding.size() == _encoding.size()); + _encoding = encoding; } /** Access to the index of the currently selected operator. @@ -53,15 +57,14 @@ class eoAlgoFoundry : public eoAlgo return _encoding.at(i); } - /** Select indices of all the operators. - */ - void operator=( std::array a) + size_t size() const { - _encoding = a; + return _size; } protected: - std::array _encoding; + const size_t _size; + std::vector _encoding; }; diff --git a/eo/src/eoAlgoFoundryEA.h b/eo/src/eoAlgoFoundryEA.h index 179aa1f9d..396e956dc 100644 --- a/eo/src/eoAlgoFoundryEA.h +++ b/eo/src/eoAlgoFoundryEA.h @@ -76,10 +76,20 @@ * @ingroup Algorithms */ template -class eoAlgoFoundryEA : public eoAlgoFoundry +class eoAlgoFoundryEA : public eoAlgoFoundry { public: - using eoAlgoFoundry::dim; + /** The constructon only take an eval, because all other operators + * are stored in the public containers. + */ + eoAlgoFoundryEA( eoPopEvalFunc& eval, size_t max_gen ) : + eoAlgoFoundry(5), + index_of(), + _eval(eval), + _max_gen(max_gen) + { } + + public: struct Indices { @@ -93,17 +103,6 @@ class eoAlgoFoundryEA : public eoAlgoFoundry /** Helper for keeping track of the indices of the underlying encoding. */ const Indices index_of; - /** The constructon only take an eval, because all other operators - * are stored in the public containers. - */ - eoAlgoFoundryEA( eoPopEvalFunc& eval, size_t max_gen ) : - index_of(), - _eval(eval), - _max_gen(max_gen) - { - _encoding = { 0 }; // dim * 0 - } - /* Operators containers @{ */ eoForgeVector< eoContinue > continuators; eoForgeVector< eoQuadOp > crossovers; @@ -116,11 +115,11 @@ class eoAlgoFoundryEA : public eoAlgoFoundry */ void operator()(eoPop& pop) { - assert(continuators.size() > 0); assert(_encoding.at(index_of.continuators) < continuators.size()); - assert( crossovers.size() > 0); assert(_encoding.at(index_of.crossovers) < crossovers.size()); - assert( mutations.size() > 0); assert(_encoding.at(index_of.mutations) < mutations.size()); - assert( selectors.size() > 0); assert(_encoding.at(index_of.selectors) < selectors.size()); - assert(replacements.size() > 0); assert(_encoding.at(index_of.replacements) < replacements.size()); + 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()); eoSequentialOp variator; variator.add(this->crossover(), 1.0); @@ -145,48 +144,47 @@ class eoAlgoFoundryEA : public eoAlgoFoundry std::string name() { std::ostringstream name; - name << _encoding.at(index_of.continuators) << " (" << this->continuator().className() << ") + "; - name << _encoding.at(index_of.crossovers) << " (" << this->crossover().className() << ") + "; - name << _encoding.at(index_of.mutations) << " (" << this->mutation().className() << ") + "; - name << _encoding.at(index_of.selectors) << " (" << this->selector().className() << ") + "; - name << _encoding.at(index_of.replacements) << " (" << this->replacement().className() << ")"; + 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() << ")"; return name.str(); } protected: eoPopEvalFunc& _eval; const size_t _max_gen; - std::array _encoding; public: eoContinue& continuator() { - assert(_encoding.at(index_of.continuators) < continuators.size()); - return continuators.instanciate(_encoding.at(index_of.continuators)); + assert(this->at(index_of.continuators) < continuators.size()); + return continuators.instanciate(this->at(index_of.continuators)); } eoQuadOp& crossover() { - assert(_encoding.at(index_of.crossovers) < crossovers.size()); - return crossovers.instanciate(_encoding.at(index_of.crossovers)); + assert(this->at(index_of.crossovers) < crossovers.size()); + return crossovers.instanciate(this->at(index_of.crossovers)); } eoMonOp& mutation() { - assert(_encoding.at(index_of.mutations) < mutations.size()); - return mutations.instanciate(_encoding.at(index_of.mutations)); + assert(this->at(index_of.mutations) < mutations.size()); + return mutations.instanciate(this->at(index_of.mutations)); } eoSelectOne& selector() { - assert(_encoding.at(index_of.selectors) < selectors.size()); - return selectors.instanciate(_encoding.at(index_of.selectors)); + assert(this->at(index_of.selectors) < selectors.size()); + return selectors.instanciate(this->at(index_of.selectors)); } eoReplacement& replacement() { - assert(_encoding.at(index_of.replacements) < replacements.size()); - return replacements.instanciate(_encoding.at(index_of.replacements)); + assert(this->at(index_of.replacements) < replacements.size()); + return replacements.instanciate(this->at(index_of.replacements)); } }; diff --git a/eo/src/eoEvalFoundryEA.h b/eo/src/eoEvalFoundryEA.h index c2e3a778e..89145d822 100644 --- a/eo/src/eoEvalFoundryEA.h +++ b/eo/src/eoEvalFoundryEA.h @@ -72,6 +72,8 @@ public: static const size_t i_repl = eoAlgoFoundryEA::Indices::replacements; /** Decode the high-level problem encoding as an array of indices. + * + * @note: If the EOT is an eoInt, this will be optimized out. * * May be useful for getting a solution back into an eoAlgoFoundryEA. * @code @@ -80,7 +82,7 @@ public: * auto& cont = foundry.continuator(); // Get the configured operator * @encode */ - std::array::dim> decode( const EOT& sol ) + std::vector decode( const EOT& sol ) const { // Denormalize size_t cont = static_cast(std::ceil( sol[i_cont] * _foundry.continuators.size() )); @@ -121,7 +123,7 @@ public: and 0 <= sele and sele < _foundry.selectors .size() and 0 <= repl and repl < _foundry.replacements.size() ) { - _foundry = config; + _foundry.select(config); // Actually perform a search _foundry(pop); diff --git a/eo/test/t-algo-forged-search.cpp b/eo/test/t-algo-forged-search.cpp index 721b8a7c7..88b2e05b5 100644 --- a/eo/test/t-algo-forged-search.cpp +++ b/eo/test/t-algo-forged-search.cpp @@ -65,10 +65,8 @@ eoAlgoFoundryEA& make_foundry(eoFunctorStore& store, eoPopEvalFunc& // A basic PSO algorithm. std::pair< eoAlgo*, eoPop* > - make_pso(eoFunctorStore& store, eoEvalFunc& eval_foundry) + make_pso(eoFunctorStore& store, eoEvalFoundryEA& eval_foundry, size_t dim) { - const size_t dim = eoAlgoFoundryEA::dim; - auto& gen_pos = store.pack< eoUniformGenerator >(0.1,0.9); auto& random_pos = store.pack< eoInitFixedLength >(dim, gen_pos); @@ -133,13 +131,13 @@ int main(int /*argc*/, char** /*argv*/) eoAlgo* pso; eoPop* pop_foundry; - std::tie(pso, pop_foundry) = make_pso(store, eval_foundry); + std::tie(pso, pop_foundry) = make_pso(store, eval_foundry, foundry.size()); // Perform the best algorithm configuration search. (*pso)(*pop_foundry); // Print a glimpse of the best algorithm found. - foundry = eval_foundry.decode(pop_foundry->best_element()); + foundry.select(eval_foundry.decode(pop_foundry->best_element())); std::cout << "Best algorithm: " << foundry.name() << std::endl; } diff --git a/eo/test/t-algo-forged.cpp b/eo/test/t-algo-forged.cpp index 6d5861ba4..7b31b6e69 100644 --- a/eo/test/t-algo-forged.cpp +++ b/eo/test/t-algo-forged.cpp @@ -84,7 +84,7 @@ int main(int /*argc*/, char** /*argv*/) foundry.at(foundry.index_of.replacements) = i_rep; // Or, if you know the order. - foundry = {i_cont, i_cross, i_mut, i_sel, i_rep}; + foundry.select({i_cont, i_cross, i_mut, i_sel, i_rep}); // Actually perform a search foundry(pop);