From cd7787bbab55983fd05d970af2a3aea1f2dcea10 Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 7 Jul 2021 21:00:13 +0200 Subject: [PATCH 01/10] feat: adds eoForgeScalar and eoParameterFoundry - Get arithmetic types out of eoOperatorFoundry in eoParameterFoundry. - Allow for metric space variables management within irace. --- eo/contrib/irace/fastga.cpp | 155 +++++++++++++++++++++++------------ eo/src/eoAlgoFoundry.h | 19 +++++ eo/src/eoAlgoFoundryFastGA.h | 18 ++-- eo/src/eoForge.h | 83 +++++++++++++++++-- 4 files changed, 202 insertions(+), 73 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index 3334974f5..9c8c94088 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -41,17 +41,17 @@ eoAlgoFoundryFastGA& make_foundry( // foundry.continuators.add< eoSteadyFitContinue >(10,i); // } - for(double i=0.0; i<1.0; i+=0.2) { - foundry.crossover_rates.add(i); - foundry.mutation_rates.add(i); - } + // for(double i=0.0; i<1.0; i+=0.2) { + // foundry.crossover_rates.add(i); + // foundry.mutation_rates.add(i); + // } /***** Offsprings size *****/ // for(size_t i=5; i<100; i+=10) { // foundry.offspring_sizes.add(i); // } - foundry.offspring_sizes.add(0); // 0 = use parents fixed pop size. + foundry.offspring_sizes.setup(0,100); // 0 = use parents fixed pop size. /***** Crossovers ****/ for(double i=0.1; i<1.0; i+=0.2) { @@ -61,7 +61,7 @@ eoAlgoFoundryFastGA& make_foundry( foundry.crossovers.add< eoNPtsBitXover >(i); // nb of points } - foundry.crossovers.add< eo1PtBitXover >(); + // foundry.crossovers.add< eo1PtBitXover >(); // Same as NPts=1 /***** Mutations ****/ double p = 1.0; // Probability of flipping each bit. @@ -119,10 +119,8 @@ eoAlgoFoundryFastGA& make_foundry( Bits::Fitness fake_func(const Bits&) { return 0; } -void print_irace_full(const eoParam& param, const size_t slot_size, std::string type="i", std::ostream& out = std::cout) +void print_irace_categorical(const eoParam& param, const size_t slot_size, std::string type="c", std::ostream& out = std::cout) { - assert(type == "i" or type =="c"); - // If there is no choice to be made on this operator, comment it out. if(slot_size - 1 <= 0) { out << "# "; @@ -136,41 +134,77 @@ void print_irace_full(const eoParam& param, const size_t slot_size, std::string << "\t\"--" << param.longName() << "=\"" << "\t" << type; - if(type == "i") { - if(slot_size -1 <= 0) { - out << "\t(0)"; - } else { - out << "\t(0," << slot_size-1 << ")"; - } - out << std::endl; - } else if(type == "c") { - out << "\t(0"; - for(size_t i=1; i +void print_irace_ranged(const eoParam& param, const T min, const T max, std::string type="r", std::ostream& out = std::cout) +{ + // If there is no choice to be made on this operator, comment it out. + if(max - min <= 0) { + out << "# "; + } + + // irace doesn't support "-" in names. + std::string irace_name = param.longName(); + irace_name.erase(std::remove(irace_name.begin(), irace_name.end(), '-'), irace_name.end()); + + out << irace_name + << "\t\"--" << param.longName() << "=\"" + << "\t" << type; + + if(max-min <= 0) { + out << "\t(?)"; + } else { + out << "\t(" << min << "," << max << ")"; + } + out << std::endl; +} + + template -void print_irace_typed(const eoParam& param, const eoForgeVector& op_foundry, std::ostream& out = std::cout) +void print_irace_oper(const eoParam& param, const eoOperatorFoundry& op_foundry, std::ostream& out = std::cout) { - print_irace_full(param, op_foundry.size(), "c", out); + print_irace_categorical(param, op_foundry.size(), "c", out); } -template<> -void print_irace_typed(const eoParam& param, const eoForgeVector& op_foundry, std::ostream& out) +// FIXME generalize to any scalar type with enable_if +// template +void print_irace_param( + const eoParam& param, + // const eoParameterFoundry::value >::type>& op_foundry, + const eoParameterFoundry& op_foundry, + std::ostream& out) { - print_irace_full(param, op_foundry.size(), "i", out); + print_irace_ranged(param, op_foundry.min(), op_foundry.max(), "r", out); } -template -void print_irace(const eoParam& param, const OPF& op_foundry, std::ostream& out = std::cout) +// template +void print_irace_param( + const eoParam& param, + // const eoParameterFoundry::value >::type>& op_foundry, + const eoParameterFoundry& op_foundry, + std::ostream& out) { - print_irace_typed(param, op_foundry, out); + print_irace_ranged(param, op_foundry.min(), op_foundry.max(), "i", out); } +template +void print_irace(const eoParam& param, const eoOperatorFoundry& op_foundry, std::ostream& out = std::cout) +{ + print_irace_oper(param, op_foundry, out); +} +template +void print_irace(const eoParam& param, const eoParameterFoundry& op_foundry, std::ostream& out = std::cout) +{ + print_irace_param/**/(param, op_foundry, out); +} + void print_operator_typed(const eoFunctorBase& op, std::ostream& out) { @@ -182,8 +216,8 @@ void print_operator_typed(const double& op, std::ostream& out) out << op; } -template -void print_operators(const eoParam& param, OPF& op_foundry, std::ostream& out = std::cout, std::string indent=" ") +template +void print_operators(const eoParam& param, eoOperatorFoundry& op_foundry, std::ostream& out = std::cout, std::string indent=" ") { out << indent << op_foundry.size() << " " << param.longName() << ":" << std::endl; for(size_t i=0; i < op_foundry.size(); ++i) { @@ -194,6 +228,11 @@ void print_operators(const eoParam& param, OPF& op_foundry, std::ostream& out = } } +template +void print_operators(const eoParam& param, eoParameterFoundry& op_foundry, std::ostream& out = std::cout, std::string indent=" ") +{ + out << indent << "[" << op_foundry.min() << "," << op_foundry.max() << "] " << param.longName() << "." << std::endl; +} // Problem configuration. struct Problem { @@ -322,17 +361,23 @@ int main(int argc, char* argv[]) // const size_t generations = std::numeric_limits::max(); eo::log << eo::debug << "Number of generations: " << generations << std::endl; - /***** operators / parameters *****/ + /***** metric parameters *****/ + auto crossover_rate_p = parser.getORcreateParam(0.5, + "crossover-rate", "", + 'C', "Operator Choice", /*required=*/true); + const double crossover_rate = crossover_rate_p.value(); + + auto mutation_rate_p = parser.getORcreateParam(0, + "mutation-rate", "", + 'M', "Operator Choice", /*required=*/true); + const double mutation_rate = mutation_rate_p.value(); + + /***** operators *****/ auto continuator_p = parser.getORcreateParam(0, "continuator", "Stopping criterion", 'o', "Operator Choice", /*required=*/false); // Single alternative, not required. const size_t continuator = continuator_p.value(); - auto crossover_rate_p = parser.getORcreateParam(0, - "crossover-rate", "", - 'C', "Operator Choice", /*required=*/true); - const size_t crossover_rate = crossover_rate_p.value(); - auto crossover_selector_p = parser.getORcreateParam(0, "cross-selector", "How to selects candidates for cross-over", 's', "Operator Choice", /*required=*/true); @@ -348,11 +393,6 @@ int main(int argc, char* argv[]) 'a', "Operator Choice", /*required=*/false); // Single alternative, not required. const size_t aftercross_selector = aftercross_selector_p.value(); - auto mutation_rate_p = parser.getORcreateParam(0, - "mutation-rate", "", - 'M', "Operator Choice", /*required=*/true); - const size_t mutation_rate = mutation_rate_p.value(); - auto mutation_selector_p = parser.getORcreateParam(0, "mut-selector", "How to selects candidate for mutation", 'u', "Operator Choice", /*required=*/true); @@ -393,19 +433,21 @@ int main(int argc, char* argv[]) print_operators( replacement_p, fake_foundry.replacements , std::clog); print_operators( offspring_size_p, fake_foundry.offspring_sizes , std::clog); + size_t fake_sample_size = 10; size_t n = - fake_foundry.crossover_rates.size() + fake_sample_size //crossover_rates * fake_foundry.crossover_selectors.size() * fake_foundry.crossovers.size() * fake_foundry.aftercross_selectors.size() - * fake_foundry.mutation_rates.size() + * fake_sample_size //mutation_rates * fake_foundry.mutation_selectors.size() * fake_foundry.mutations.size() * fake_foundry.replacements.size() * fake_foundry.continuators.size() - * fake_foundry.offspring_sizes.size(); + * fake_sample_size //offspring_sizes + ; std::clog << std::endl; - std::clog << n << " possible algorithms configurations." << std::endl; + std::clog << "~" << n << " possible algorithms configurations." << std::endl; std::clog << "Ranges of configurable parameters (redirect the stdout in a file to use it with iRace): " << std::endl; @@ -445,16 +487,22 @@ int main(int argc, char* argv[]) // Build up an algorithm name from main parameters. std::ostringstream name; name << "FastGA"; - for(auto& p : {pop_size_p, - crossover_rate_p, + for(auto& p : { crossover_selector_p, crossover_p, aftercross_selector_p, - mutation_rate_p, mutation_selector_p, mutation_p, - replacement_p, - offspring_size_p}) { + replacement_p }) { + name << "_" << p.shortName() << "=" << p.getValue(); + } + for(auto& p : { + crossover_rate_p, + mutation_rate_p }) { + name << "_" << p.shortName() << "=" << p.getValue(); + } + for(auto& p : {pop_size_p, + offspring_size_p }) { name << "_" << p.shortName() << "=" << p.getValue(); } std::clog << name.str() << std::endl; @@ -580,7 +628,8 @@ int main(int argc, char* argv[]) std::clog << "Attainment matrix distribution: " << std::endl; assert(mat.size() > 0); assert(mat[0].size() > 1); - for(size_t i = mat.size()-1; i >= 0; --i) { + for(size_t i = mat.size()-1; i > 0; --i) { + assert(mat[i].size() >= 1); std::cout << mat[i][0]; for(size_t j = 1; j < mat[i].size(); ++j) { std::cout << "," << mat[i][j]; diff --git a/eo/src/eoAlgoFoundry.h b/eo/src/eoAlgoFoundry.h index 19ffb5023..2e7064c99 100644 --- a/eo/src/eoAlgoFoundry.h +++ b/eo/src/eoAlgoFoundry.h @@ -59,9 +59,28 @@ class eoOperatorFoundry : public eoForgeVector< Itf > size_t index() const { return _index; } protected: + //! Unique index in the eoAlgoFoundry. size_t _index; }; +template +class eoParameterFoundry : public eoForgeScalar< Itf > +{ + static_assert(std::is_arithmetic::value, + "eoParameterFoundry should only be used on arithmetic types (i.e. integer or floating point types)"); + + public: + eoParameterFoundry(size_t encoding_index, Itf min, Itf max) : + eoForgeScalar(min, max), + _index(encoding_index) + { } + + size_t index() const { return _index; } + + protected: + //! Unique index in the eoAlgoFoundry. + size_t _index; +}; /** Interface of a Foundry: a class that instantiate an eoAlgo on-the-fly, given a choice of its operators. * diff --git a/eo/src/eoAlgoFoundryFastGA.h b/eo/src/eoAlgoFoundryFastGA.h index ed766ff88..59f7dcfb2 100644 --- a/eo/src/eoAlgoFoundryFastGA.h +++ b/eo/src/eoAlgoFoundryFastGA.h @@ -90,18 +90,18 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry ) : eoAlgoFoundry(10), - crossover_rates(0, false), + crossover_rates(0, 0.0, 1.0), crossover_selectors(1, false), crossovers(2, false), aftercross_selectors(3, false), - mutation_rates(4, false), + mutation_rates(4, 0.0, 1.0), mutation_selectors(5, false), mutations(6, false), replacements(7, false), continuators(8, true), // Always re-instantiate continuators, because they hold a state. - offspring_sizes(9, false), + offspring_sizes(9, 0, std::numeric_limits::max()), _eval(eval), _init(init), _max_evals(max_evals), @@ -111,34 +111,31 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry public: /* Operators containers @{ */ - eoOperatorFoundry< double > crossover_rates; + eoParameterFoundry< double > crossover_rates; eoOperatorFoundry< eoSelectOne > crossover_selectors; eoOperatorFoundry< eoQuadOp > crossovers; eoOperatorFoundry< eoSelectOne > aftercross_selectors; - eoOperatorFoundry< double > mutation_rates; + eoParameterFoundry< double > mutation_rates; eoOperatorFoundry< eoSelectOne > mutation_selectors; eoOperatorFoundry< eoMonOp > mutations; eoOperatorFoundry< eoReplacement > replacements; eoOperatorFoundry< eoContinue > continuators; - eoOperatorFoundry< size_t > offspring_sizes; + eoParameterFoundry< size_t > offspring_sizes; /* @} */ /** instantiate and call the pre-selected algorithm. */ void operator()(eoPop& pop) { - assert( crossover_rates.size() > 0); assert(this->at( crossover_rates.index()) < crossover_rates.size()); assert( crossover_selectors.size() > 0); assert(this->at( crossover_selectors.index()) < crossover_selectors.size()); assert( crossovers.size() > 0); assert(this->at( crossovers.index()) < crossovers.size()); assert(aftercross_selectors.size() > 0); assert(this->at(aftercross_selectors.index()) < aftercross_selectors.size()); - assert( mutation_rates.size() > 0); assert(this->at( mutation_rates.index()) < mutation_rates.size()); assert( mutation_selectors.size() > 0); assert(this->at( mutation_selectors.index()) < mutation_selectors.size()); assert( mutations.size() > 0); assert(this->at( mutations.index()) < mutations.size()); assert( replacements.size() > 0); assert(this->at( replacements.index()) < replacements.size()); assert( continuators.size() > 0); assert(this->at( continuators.index()) < continuators.size()); - assert( offspring_sizes.size() > 0); assert(this->at( offspring_sizes.index()) < offspring_sizes.size()); // Objective function calls counter eoEvalCounterThrowException eval(_eval, _max_evals); @@ -212,7 +209,6 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry double& crossover_rate() { - assert(this->at(crossover_rates.index()) < crossover_rates.size()); return crossover_rates.instantiate(this->at(crossover_rates.index())); } @@ -224,7 +220,6 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry double& mutation_rate() { - assert(this->at(mutation_rates.index()) < mutation_rates.size()); return mutation_rates.instantiate(this->at(mutation_rates.index())); } @@ -254,7 +249,6 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry size_t& offspring_size() { - assert(this->at(offspring_sizes.index()) < offspring_sizes.size()); return offspring_sizes.instantiate(this->at(offspring_sizes.index())); } diff --git a/eo/src/eoForge.h b/eo/src/eoForge.h index d1cae4c93..f36476579 100644 --- a/eo/src/eoForge.h +++ b/eo/src/eoForge.h @@ -215,7 +215,7 @@ class eoForgeOperator : public eoForgeInterface * * @ingroup Foundry */ -template +template class eoForgeVector : public std::vector*> { public: @@ -238,6 +238,19 @@ class eoForgeVector : public std::vector*> _no_cache(always_reinstantiate) { } + /** instantiate the operator managed at the given index. + */ + Itf& instantiate(double index) + { + double frac_part, int_part; + frac_part = std::modf(index, &int_part); + if(frac_part != 0) { + eo::log << eo::errors << "there is a fractional part in the given index (" << index << ")" << std::endl; + assert(frac_part != 0); + } + return this->at(static_cast(index))->instantiate(_no_cache); + } + /** Add an operator to the list. * * @warning When passing a reference (as it is often the case within ParadisEO), @@ -295,13 +308,6 @@ class eoForgeVector : public std::vector*> this->at(index) = pfo; } - /** instantiate the operator managed at the given index. - */ - Itf& instantiate(size_t index) - { - return this->at(index)->instantiate(_no_cache); - } - virtual ~eoForgeVector() { for(auto p : *this) { @@ -313,5 +319,66 @@ class eoForgeVector : public std::vector*> bool _no_cache; }; +template +class eoForgeScalar +{ + public: + using Interface = Itf; + + eoForgeScalar(Itf min, Itf max) : + _min(min), + _max(max) + { } + + /** Just return the same value, without managing any instantiation. + */ + Itf& instantiate(double value) + { + this->_value = value; + if(not (_min <= value and value <= _max) ) { + eo::log << eo::errors << "ERROR: the given value is out of range, I'll cap it." << std::endl; + assert(_min <= value and value <= _max); + if(value < _min) { + this->_value = _min; + return this->_value; + } + if(value > _max) { + this->_value = _max; + return this->_value; + } + } + return this->_value; + } + + Itf min() const { return _min; } + Itf max() const { return _max; } + + void min(Itf min) + { + assert(_min <= _max); + _min = min; + } + + void max(Itf max) + { + assert(_max >= _min); + _max = max; + } + + void setup(Itf min, Itf max) + { + _min = min; + _max = max; + assert(_min <= _max); + } + + // Nothing else, as it would not make sense. + protected: + Itf _value; + + Itf _min; + Itf _max; +}; + #endif // _eoForge_H_ From 949b5818a25c4f1a1ce16372b781cc6f44c7b2a5 Mon Sep 17 00:00:00 2001 From: nojhan Date: Thu, 8 Jul 2021 12:19:10 +0200 Subject: [PATCH 02/10] adds a definition file for building fastga as a Singularity container --- eo/contrib/irace/fastga.sindef | 63 ++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 eo/contrib/irace/fastga.sindef diff --git a/eo/contrib/irace/fastga.sindef b/eo/contrib/irace/fastga.sindef new file mode 100644 index 000000000..86fa3e7cd --- /dev/null +++ b/eo/contrib/irace/fastga.sindef @@ -0,0 +1,63 @@ +Bootstrap: library +From: ubuntu:20.04 + +%post + + # Dependencies + apt -y install software-properties-common + add-apt-repository universe + apt -y update + apt -y dist-upgrade + apt -y install git clang-9 cmake make libeigen3-dev + apt clean + update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-9 90 + update-alternatives --set c++ /usr/bin/clang++-9 + + # Temporary directory where we are going to build everything. + tmpdir=$(mktemp -d) + mkdir -p ${tmpdir}/fastga/ + + # Build IOH + cd ${tmpdir}/fastga/ + git clone --branch feat+EAF --single-branch --recurse-submodules https://github.com/jdreo/IOHexperimenter.git + cd IOHexperimenter + mkdir -p release + cd release + cmake -D CMAKE_BUILD_TYPE=Release -D BUILD_TESTS=OFF -D BUILD_EXAMPLE=OFF -D BUILD_GMOCK=OFF .. + make + + # Build Paradiseo + cd ${tmpdir}/fastga/ + git clone --branch feat+num_foundry --single-branch https://github.com/jdreo/paradiseo.git + cd paradiseo + touch LICENSE + mkdir -p release + cd release + cmake -D CMAKE_BUILD_TYPE=Release -EDO=ON -EDO_USE_LIB=Eigen3 .. + make + + # Build FastGA + cd ${tmpdir}/fastga/paradiseo/eo/contrib/irace/ + mkdir -p release + cd release + cmake -D CMAKE_BUILD_TYPE=Release -D IOH_ROOT=${tmpdir}/fastga/IOHexperimenter/ -D PARADISEO_ROOT=${tmpdir}/fastga/paradiseo/ -D PARADISEO_BUILD=${tmpdir}/fastga/paradiseo/release/ .. + make + + # Install FastGA + cp fastga /usr/local/bin/ + + # Clean-up + rm -rf ${tmpdir} + apt -y purge software-properties-common git clang-9 cmake make libeigen3-dev + apt -y --purge autoremove + apt -y autoclean + apt clean + +%environment + +%runscript + /usr/local/bin/fastga $* + +%labels + Author Quentin Renau + Author Johann Dreo From 18fec047ad179bce0756400619cfb6ad84510ba4 Mon Sep 17 00:00:00 2001 From: nojhan Date: Thu, 15 Jul 2021 18:52:21 +0200 Subject: [PATCH 03/10] fix clang 10 compatibility - random_shuffle is replaced by shuffle - get rid of EO stuff in eoPop, superseeded by stdlib random - get rid of bind2nd and use lambdas --- eo/contrib/irace/CMakeLists.txt | 2 +- eo/contrib/irace/fastga.cpp | 4 ++-- eo/src/eoInit.h | 2 +- eo/src/eoPop.h | 13 +++++++++---- eo/src/ga/eoBit.h | 3 ++- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/eo/contrib/irace/CMakeLists.txt b/eo/contrib/irace/CMakeLists.txt index a77849b15..1e968d817 100644 --- a/eo/contrib/irace/CMakeLists.txt +++ b/eo/contrib/irace/CMakeLists.txt @@ -71,5 +71,5 @@ endif() add_executable(fastga fastga.cpp) # target_link_libraries(fastga ${PARADISEO_LIBRARIES} ${IOH_LIBRARY} stdc++fs) -target_link_libraries(fastga ${PARADISEO_LIBRARIES} stdc++fs fmt) +target_link_libraries(fastga ${PARADISEO_LIBRARIES} fmt) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index 9c8c94088..ba55a22f8 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -519,8 +519,8 @@ int main(int argc, char* argv[]) ioh::trigger::OnImprovement on_improvement; ioh::watch::Evaluations evaluations; ioh::watch::TransformedYBest transformed_y_best; - std::vector> t = {std::ref(on_improvement)}; - std::vector> w = {std::ref(evaluations),std::ref(transformed_y_best)}; + std::vector> t = {on_improvement}; + std::vector> w = {evaluations,transformed_y_best}; csv_logger = std::make_shared( // {std::ref(on_improvement)}, // {std::ref(evaluations),std::ref(transformed_y_best)}, diff --git a/eo/src/eoInit.h b/eo/src/eoInit.h index 9146311fa..a73310778 100644 --- a/eo/src/eoInit.h +++ b/eo/src/eoInit.h @@ -196,7 +196,7 @@ class eoInitPermutation: public eoInit // FIXME inherit from eoInitWithDim for(unsigned idx=0;idx #include #include #include // needed for GCC 3.2 @@ -182,8 +183,10 @@ class eoPop: public std::vector, public eoObject, public eoPersistent */ void shuffle(void) { - UF_random_generator gen; - std::random_shuffle(begin(), end(), gen); + std::random_device rd; + std::mt19937 gen(rd()); + //UF_random_generator gen; // FIXME refactor + std::shuffle(begin(), end(), gen); } @@ -194,8 +197,10 @@ class eoPop: public std::vector, public eoObject, public eoPersistent std::transform(begin(), end(), result.begin(), Ref()); - UF_random_generator gen; - std::random_shuffle(result.begin(), result.end(), gen); + std::random_device rd; + std::mt19937 gen(rd()); + //UF_random_generator gen; // FIXME refactor + std::shuffle(result.begin(), result.end(), gen); } diff --git a/eo/src/ga/eoBit.h b/eo/src/ga/eoBit.h index 71c6aa62b..320a5b7d1 100644 --- a/eo/src/ga/eoBit.h +++ b/eo/src/ga/eoBit.h @@ -114,7 +114,8 @@ public: { resize(bits.size()); std::transform(bits.begin(), bits.end(), begin(), - std::bind2nd(std::equal_to(), '1')); + //std::bind2nd(std::equal_to(), '1')); + [](char bit){return bit == '1';} ); } } }; From f4a8f97f70ea339f7c7e40391099eb6387ee4bd5 Mon Sep 17 00:00:00 2001 From: nojhan Date: Thu, 15 Jul 2021 19:20:04 +0200 Subject: [PATCH 04/10] add an example of complex build script for fastga --- eo/contrib/irace/build_fastga.sh | 80 ++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100755 eo/contrib/irace/build_fastga.sh diff --git a/eo/contrib/irace/build_fastga.sh b/eo/contrib/irace/build_fastga.sh new file mode 100755 index 000000000..abaac4a20 --- /dev/null +++ b/eo/contrib/irace/build_fastga.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +######################################################################## +# This is an example of how to deal with complex builds, +# for instance on clusters with compilers provided as side modules. +######################################################################## + +# Run this script in a separate dir, e.g. +# mkdir -p code ; cd code ; ../build_fastga.sh + +# exit when any command fails +set -e + +# We need recent clang and cmake +module load LLVM/clang-llvm-10.0 +module load cmake/3.18 + +# We are going to use a specific compiler, different from the system's one. +# Path toward the compiler: +C="/opt/dev/Compilers/LLVM/10.0.1/bin" +# Path toward the include for the std lib: +I="/opt/dev/Compilers/LLVM/10.0.1/include/c++/v1/" +# Path toward the compiled std lib: +L="/opt/dev/Compilers/LLVM/10.0.1/lib" + +# As we use clang, we use its std lib (instead of gcc's "libstdc++") +S="libc++" + +# Gather all those into a set of flags: +flags="-I${I} -stdlib=${S} -L${L}" + +# Current dir, for further reference. +here=$(pwd) + +# Compiler selection +export CC=${C}/clang +export CXX=${C}/clang++ + +# If the dir already exists +if cd IOHexperimenter ; then + # Just update the code + git pull +else + # Clone the repo + git clone --branch feat+EAF --single-branch --recurse-submodules https://github.com/jdreo/IOHexperimenter.git + cd IOHexperimenter +fi +# Clean build from scratch +rm -rf release +mkdir -p release +cd release +cmake -DCMAKE_CXX_FLAGS="${flags}" -D CMAKE_BUILD_TYPE=Release -D BUILD_TESTS=OFF -D BUILD_EXAMPLE=OFF .. +make -j +# Get back to the root dir +cd ${here} + + +if cd paradiseo ; then + git pull +else + git clone --branch feat+num_foundry --single-branch --recurse-submodules https://github.com/jdreo/paradiseo.git + cd paradiseo + touch LICENSE +fi +rm -rf release +mkdir -p release +cd release +cmake -DCMAKE_CXX_FLAGS="${flags}" -D CMAKE_BUILD_TYPE=Release .. +make -j +cd ${here} + + +cd paradiseo/eo/contrib/irace +rm -rf release +mkdir -p release +cd release +cmake -DCMAKE_CXX_FLAGS="${flags}" -D CMAKE_BUILD_TYPE=Release -D IOH_ROOT=${here}/IOHexperimenter/ -D PARADISEO_ROOT=${here}/paradiseo/ -D PARADISEO_BUILD=${here}/paradiseo/release/ .. +make -j +cd ${here} + From 864bbf697dcf912e164396bc1b7e00d6b4aa1082 Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 19 Jul 2021 12:08:04 +0200 Subject: [PATCH 05/10] adds the pop_size parameters as managed by fastga --- eo/contrib/irace/fastga.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index ba55a22f8..170f69877 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -199,12 +199,17 @@ void print_irace(const eoParam& param, const eoOperatorFoundry& op_foundry, { print_irace_oper(param, op_foundry, out); } + template void print_irace(const eoParam& param, const eoParameterFoundry& op_foundry, std::ostream& out = std::cout) { print_irace_param/**/(param, op_foundry, out); } +void print_irace(const eoParam& param, const size_t min, const size_t max, std::ostream& out = std::cout) +{ + print_irace_ranged(param, min, max, "i", out); +} void print_operator_typed(const eoFunctorBase& op, std::ostream& out) { @@ -228,10 +233,16 @@ void print_operators(const eoParam& param, eoOperatorFoundry& op_foundry, s } } +template +void print_operators(const eoParam& param, T min, T max, std::ostream& out = std::cout, std::string indent=" ") +{ + out << indent << "[" << min << "," << max << "] " << param.longName() << "." << std::endl; +} + template void print_operators(const eoParam& param, eoParameterFoundry& op_foundry, std::ostream& out = std::cout, std::string indent=" ") { - out << indent << "[" << op_foundry.min() << "," << op_foundry.max() << "] " << param.longName() << "." << std::endl; + print_operators(param, op_foundry.min(), op_foundry.max(), out, indent); } // Problem configuration. @@ -350,6 +361,7 @@ int main(int argc, char* argv[]) "pop-size", "Population size", 'P', "Operator Choice", /*required=*/false); const size_t pop_size = pop_size_p.value(); + const size_t pop_size_max = 200; auto offspring_size_p = parser.getORcreateParam(0, "offspring-size", "Offsprings size (0 = same size than the parents pop, see --pop-size)", @@ -432,8 +444,13 @@ int main(int argc, char* argv[]) print_operators( mutation_p, fake_foundry.mutations , std::clog); print_operators( replacement_p, fake_foundry.replacements , std::clog); print_operators( offspring_size_p, fake_foundry.offspring_sizes , std::clog); + print_operators( pop_size_p, (size_t)1, pop_size_max , std::clog); + std::clog << std::endl; + // If we were to make a DoE sampling numeric parameters, + // we would use that many samples: size_t fake_sample_size = 10; + std::clog << "With " << fake_sample_size << " samples for numeric parameters..." << std::endl; size_t n = fake_sample_size //crossover_rates * fake_foundry.crossover_selectors.size() @@ -445,8 +462,8 @@ int main(int argc, char* argv[]) * fake_foundry.replacements.size() * fake_foundry.continuators.size() * fake_sample_size //offspring_sizes + * fake_sample_size //pop_size ; - std::clog << std::endl; std::clog << "~" << n << " possible algorithms configurations." << std::endl; std::clog << "Ranges of configurable parameters (redirect the stdout in a file to use it with iRace): " << std::endl; @@ -463,6 +480,7 @@ int main(int argc, char* argv[]) print_irace( mutation_p, fake_foundry.mutations , std::cout); print_irace( replacement_p, fake_foundry.replacements , std::cout); print_irace( offspring_size_p, fake_foundry.offspring_sizes , std::cout); + print_irace( pop_size_p, 1, pop_size_max , std::cout); // std::ofstream irace_param("fastga.params"); // irace_param << "# name\tswitch\ttype\tvalues" << std::endl; From 648357de642e62ea2a7e864bf6ae89e29f78f437 Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 19 Jul 2021 16:34:25 +0200 Subject: [PATCH 06/10] disable objective transformation in W-Model of fastga --- eo/contrib/irace/fastga.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index 170f69877..0455f07c1 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -267,6 +267,26 @@ std::ostream& operator<<(std::ostream& os, const Problem& pb) return os; } +/***************************************************************************** + * IOH problem adaptation. + *****************************************************************************/ + +class WModelFlat : public ioh::problem::wmodel::WModelOneMax +{ + public: + WModelFlat(const int instance, const int n_variables, + const double dummy_para, const int epistasis_para, const int neutrality_para, + const int ruggedness_para) + : WModelOneMax(instance, n_variables, dummy_para, epistasis_para, neutrality_para, ruggedness_para) + { } + + protected: + double transform_objectives(const double y) override + { // Disable objective function shift & scaling. + return y; + } +}; + /***************************************************************************** * Command line interface. *****************************************************************************/ @@ -562,7 +582,8 @@ int main(int argc, char* argv[]) // + "_N" + std::to_string(w_neutrality) // + "_R" + std::to_string(w_ruggedness); - ioh::problem::wmodel::WModelOneMax w_model_om( + // ioh::problem::wmodel::WModelOneMax w_model_om( + WModelFlat w_model_om( instance, dimension, w_dummy, From 6c3bffd8c26a70b38171ec79faf4a1cab6d15000 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 30 Jul 2021 10:29:03 +0200 Subject: [PATCH 07/10] [fastga] fix budget-related issues Was overridding the max-evals budget in certain cases. --- eo/contrib/irace/fastga.cpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index 0455f07c1..9dd0c0d47 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -24,13 +24,13 @@ using Bits = eoBit, int>; eoAlgoFoundryFastGA& make_foundry( eoFunctorStore& store, eoInit& init, - eoEvalFunc& eval_onemax, + eoEvalFunc& eval, const size_t max_evals, const size_t generations ) { // FIXME using max_restarts>1 does not allow to honor max evals. - auto& foundry = store.pack< eoAlgoFoundryFastGA >(init, eval_onemax, max_evals, /*max_restarts=*/1); + auto& foundry = store.pack< eoAlgoFoundryFastGA >(init, eval, max_evals, /*max_restarts=*/1); /***** Continuators ****/ foundry.continuators.add< eoGenContinue >(generations); @@ -348,7 +348,7 @@ int main(int argc, char* argv[]) const size_t instance = instance_p.value(); const size_t max_evals = parser.getORcreateParam(5 * dimension, - "max-evals", "Maximum number of evaluations", + "max-evals", "Maximum number of evaluations (default: 5*dim, else the given value)", 'e', "Stopping criterion").value(); const size_t buckets = parser.getORcreateParam(100, @@ -388,10 +388,12 @@ int main(int argc, char* argv[]) 'O', "Operator Choice", /*required=*/false); // Single alternative, not required. const size_t offspring_size = offspring_size_p.value(); - const size_t generations = static_cast(std::floor( + size_t generations = static_cast(std::floor( static_cast(max_evals) / static_cast(pop_size))); // const size_t generations = std::numeric_limits::max(); - eo::log << eo::debug << "Number of generations: " << generations << std::endl; + if(generations < 1) { + generations = 1; + } /***** metric parameters *****/ auto crossover_rate_p = parser.getORcreateParam(0.5, @@ -508,6 +510,10 @@ int main(int argc, char* argv[]) exit(NO_ERROR); } + eo::log << eo::debug << "Maximum number of evaluations: " << max_evals << std::endl; + eo::log << eo::debug << "Number of generations: " << generations << std::endl; + + /***************************************************************************** * IOH stuff. *****************************************************************************/ @@ -601,7 +607,8 @@ int main(int argc, char* argv[]) eoEvalIOHproblem onemax_pb(w_model_om, loggers); // eoEvalPrint eval_print(onemax_pb, std::clog, "\n"); - eoEvalFuncCounter eval_count(onemax_pb); + // eoEvalFuncCounter eval_count(onemax_pb); + eoEvalCounterThrowException eval_count(onemax_pb, max_evals); eoPopLoopEval onemax_eval(eval_count); @@ -609,7 +616,7 @@ int main(int argc, char* argv[]) eoBooleanGenerator bgen; eoInitFixedLength onemax_init(/*bitstring size=*/dimension, bgen); - auto& foundry = make_foundry(store, onemax_init, eval_count, max_evals - pop_size, generations); + auto& foundry = make_foundry(store, onemax_init, eval_count, max_evals, generations); Ints encoded_algo(foundry.size()); @@ -644,8 +651,13 @@ int main(int argc, char* argv[]) eoPop pop; pop.append(pop_size, onemax_init); - onemax_eval(pop,pop); - foundry(pop); // Actually run the selected algorithm. + try { + onemax_eval(pop,pop); + foundry(pop); // Actually run the selected algorithm. + + } catch(eoMaxEvalException e) { + eo::log << eo::debug << "Reached maximum evaluations: " << eval_count.getValue() << " / " << max_evals << std::endl; + } /***** IOH perf stats *****/ double perf = ioh::logger::eah::stat::under_curve::volume(eah_logger); From eb9bd4a4053d1443a9bdefa16054f12f453b6dea Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 30 Jul 2021 10:30:37 +0200 Subject: [PATCH 08/10] make some eoAlgoFoundryFastGA's parameters const --- eo/src/eoAlgoFoundryFastGA.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eo/src/eoAlgoFoundryFastGA.h b/eo/src/eoAlgoFoundryFastGA.h index 59f7dcfb2..0417511cb 100644 --- a/eo/src/eoAlgoFoundryFastGA.h +++ b/eo/src/eoAlgoFoundryFastGA.h @@ -85,8 +85,8 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry eoAlgoFoundryFastGA( eoInit & init, eoEvalFunc& eval, - size_t max_evals = 10000, - size_t max_restarts = std::numeric_limits::max() + const size_t max_evals = 10000, + const size_t max_restarts = std::numeric_limits::max() ) : eoAlgoFoundry(10), From 558d476ef34b0e5fc32b0f3b64f13b2bddf55b4c Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 30 Jul 2021 11:15:59 +0200 Subject: [PATCH 09/10] feat: adds a constructor taking a vector to eoCombinedContinue --- eo/src/eoCombinedContinue.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/eo/src/eoCombinedContinue.h b/eo/src/eoCombinedContinue.h index 756a44a89..a3b3dcbca 100644 --- a/eo/src/eoCombinedContinue.h +++ b/eo/src/eoCombinedContinue.h @@ -54,8 +54,11 @@ public: /// Ctor, make sure that at least on continuator is present eoCombinedContinue( eoContinue& _cont) : eoContinue(), std::vector* >(1, &_cont) - { - } + { } + + eoCombinedContinue( std::vector*> _conts ) + : eoContinue(), std::vector* >(_conts) + { } /* FIXME remove in next release /// Ctor - for historical reasons ... should disspear some day From e2b74349e153d759c1da1aca9f4e0256ae7a9832 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 30 Jul 2021 11:16:30 +0200 Subject: [PATCH 10/10] [fastga] adds a fitness stoping criterion --- eo/contrib/irace/fastga.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index 9dd0c0d47..73f0e5388 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -26,14 +26,20 @@ eoAlgoFoundryFastGA& make_foundry( eoInit& init, eoEvalFunc& eval, const size_t max_evals, - const size_t generations + const size_t generations, + const double optimum ) { // FIXME using max_restarts>1 does not allow to honor max evals. auto& foundry = store.pack< eoAlgoFoundryFastGA >(init, eval, max_evals, /*max_restarts=*/1); /***** Continuators ****/ - foundry.continuators.add< eoGenContinue >(generations); + auto& fitcont = store.pack< eoFitContinue >(optimum); + auto& gencont = store.pack< eoGenContinue >(generations); + auto combconts = std::make_shared< std::vector*> >(); + combconts->push_back( &fitcont ); + combconts->push_back( &gencont ); + foundry.continuators.add< eoCombinedContinue >( *combconts ); // for(size_t i=1; i<10; i++) { // foundry.continuators.add< eoGenContinue >(i); // } @@ -453,7 +459,7 @@ int main(int argc, char* argv[]) eoEvalFuncPtr fake_eval(fake_func); eoUniformGenerator fake_gen(0, 1); eoInitFixedLength fake_init(/*bitstring size=*/1, fake_gen); - auto fake_foundry = make_foundry(store, fake_init, fake_eval, max_evals, /*generations=*/ 1); + auto fake_foundry = make_foundry(store, fake_init, fake_eval, max_evals, /*generations=*/ 1, 0); std::clog << std::endl << "Available operators:" << std::endl; print_operators( continuator_p, fake_foundry.continuators , std::clog); @@ -616,7 +622,7 @@ int main(int argc, char* argv[]) eoBooleanGenerator bgen; eoInitFixedLength onemax_init(/*bitstring size=*/dimension, bgen); - auto& foundry = make_foundry(store, onemax_init, eval_count, max_evals, generations); + auto& foundry = make_foundry(store, onemax_init, eval_count, max_evals, generations, max_target); Ints encoded_algo(foundry.size());