From 2c1ff1cb3390a43bc2bf2769d38fc3f2a6039bd6 Mon Sep 17 00:00:00 2001 From: Amine Aziz-Alaoui Date: Mon, 21 Sep 2020 16:21:53 +0200 Subject: [PATCH 01/42] First version of the irace API --- eo/contrib/irace/CMakeLists.txt | 97 ++++++++++++++++ eo/contrib/irace/fastga.cpp | 195 ++++++++++++++++++++++++++++++++ 2 files changed, 292 insertions(+) create mode 100644 eo/contrib/irace/CMakeLists.txt create mode 100644 eo/contrib/irace/fastga.cpp diff --git a/eo/contrib/irace/CMakeLists.txt b/eo/contrib/irace/CMakeLists.txt new file mode 100644 index 000000000..37c82187e --- /dev/null +++ b/eo/contrib/irace/CMakeLists.txt @@ -0,0 +1,97 @@ + +###################################################################################### +# Project settings +###################################################################################### + +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) + +project("paradiseo-irace") + +enable_language(CXX) # C++ +set(CMAKE_CXX_STANDARD 17) + +## Current version +set(VERSION_MAJOR 0 CACHE STRING "Major version number" ) +set(VERSION_MINOR 1 CACHE STRING "Minor version number" ) +set(VERSION_PATCH 0 CACHE STRING "Patch version number" ) +mark_as_advanced(VERSION_MAJOR VERSION_MINOR VERSION_PATCH) + + +###################################################################################### +# Configurable user settings +###################################################################################### + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic") + +# put binaries in the build directory +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + +# Dump used compiler flags. +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + + +###################################################################################### +# Dependencies +###################################################################################### + +# ParadisEO +set(PARADISEO_ROOT "../../../../paradiseo" CACHE PATH "Where to find ParadisEO") +set(PARADISEO_BUILD "${PARADISEO_ROOT}/build" CACHE PATH "Build dir of ParadisEO") + +include_directories(${PARADISEO_ROOT}) +include_directories(${PARADISEO_ROOT}/eo/src) +link_directories(${PARADISEO_BUILD}/lib) +set(PARADISEO_LIBRARIES ga eoutils eo) + +# IOH +set(IOH_ROOT "~/code/IOHexperimenter/" CACHE PATH "Where to find IOHexperimenter") +find_path(IOH_PROBLEM_H "IOHprofiler_problem.h" PATHS ${IOH_ROOT}/src/Template/) +find_library(IOH_LIBRARY "IOH" PATHS ${IOH_ROOT} PATH_SUFFIXES release Release debug Debug build Build) + +if(EXISTS ${IOH_PROBLEM_H} AND EXISTS ${IOH_LIBRARY}) + message(STATUS "Found IOH in ${IOH_ROOT}") + include_directories(${IOH_ROOT}/build/Cpp/src/) + link_directories(${IOH_ROOT}/build/Cpp/bin/) + + # Workaround IOH's poorly designed headers inclusion scheme. + SET(PROBLEMS_BBOB_DIR "src/Problems/BBOB") + SET(PROBLEMS_BBOB_COMMON_DIR "src/Problems/BBOB/bbob_common_used_functions") + SET(PROBLEMS_COMMON_DIR "src/Problems/common_used_functions") + SET(PROBLEMS_PBO_DIR "src/Problems/PBO") + SET(PROBLEMS_WMODEL_DIR "src/Problems/WModel") + SET(PROBLEMS_PYTHON_DIR "src/Problems/Python") + SET(SUITES_DIR "src/Suites") + SET(TEMPLATE_DIR "src/Template") + SET(TEMPLATE_EXPERIMENTS_DIR "src/Template/Experiments") + SET(TEMPLATE_LOGGERS_DIR "src/Template/Loggers") + SET(IOHEXPERIMENTER_DIR + "${IOH_ROOT}/${PROBLEMS_COMMON_DIR}" + "${IOH_ROOT}/${PROBLEMS_BBOB_DIR}" + "${IOH_ROOT}/${PROBLEMS_BBOB_COMMON_DIR}" + "${IOH_ROOT}/${PROBLEMS_PBO_DIR}" + "${IOH_ROOT}/${PROBLEMS_WMODEL_DIR}" + "${IOH_ROOT}/${PROBLEMS_PYTHON_DIR}" + "${IOH_ROOT}/${SUITES_DIR}" + "${IOH_ROOT}/${TEMPLATE_DIR}" + "${IOH_ROOT}/${TEMPLATE_EXPERIMENTS_DIR}" + "${IOH_ROOT}/${TEMPLATE_LOGGERS_DIR}" + ) + include_directories(${IOHEXPERIMENTER_DIR}) + +else() + if(NOT EXISTS ${IOH_PROBLEM_H}) + message(FATAL_ERROR "Could not find `IOHprofiler_problem.h` in: ${IOH_ROOT}/src/Template/ (did you forget to compile it?)") + endif() + if(NOT EXISTS ${IOH_LIBRARIES}) + message(FATAL_ERROR "Could not find `libIOH` in: ${IOH_ROOT}/[release|debug|build] (did you forget to compile it?)") + endif() +endif() + + +###################################################################################### +# Start building +###################################################################################### + +add_executable(fastga fastga.cpp) +target_link_libraries(fastga ${PARADISEO_LIBRARIES} ${IOH_LIBRARY}) + diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp new file mode 100644 index 000000000..9682af59f --- /dev/null +++ b/eo/contrib/irace/fastga.cpp @@ -0,0 +1,195 @@ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +// using Particle = eoRealParticle; +using Ints = eoInt, size_t>; +using Bits = eoBit, int>; + +// by enumerating candidate operators and their parameters. +eoAlgoFoundryFastGA& make_foundry( + eoFunctorStore& store, + eoInit& init, + eoEvalFunc& eval_onemax, + const size_t max_evals, + const size_t generations + ) +{ + auto& foundry = store.pack< eoAlgoFoundryFastGA >(init, eval_onemax, max_evals /*, max_restarts = max */); + + /***** Continuators ****/ + foundry.continuators.add< eoGenContinue >(generations); + // for(size_t i=1; i<10; i++) { + // foundry.continuators.add< eoGenContinue >(i); + // } + // for(size_t i=10; i < 100; i+=2 ) { + // foundry.continuators.add< eoSteadyFitContinue >(10,i); + // } + + for(double i=0.1; i<1.0; i+=0.1) { + foundry.crossover_rates.add(i); + foundry.mutation_rates.add(i); + } + + for(size_t i=5; i<100; i+=10) { + foundry.pop_sizes.add(i); + } + + /***** Crossovers ****/ + for(double i=0.1; i<0.9; i+=0.1) { + foundry.crossovers.add< eoUBitXover >(i); // preference over 1 + } + for(size_t i=1; i < 11; i+=1) { + foundry.crossovers.add< eoNPtsBitXover >(i); // nb of points + } + foundry.crossovers.add< eo1PtBitXover >(); + + /***** Mutations ****/ + double p = 1.0; // Probability of flipping eath bit. + foundry.mutations.add< eoUniformBitMutation >(p); // proba of flipping k bits, k drawn in uniform distrib + foundry.mutations.add< eoStandardBitMutation >(p); // proba of flipping k bits, k drawn in binomial distrib + foundry.mutations.add< eoConditionalBitMutation >(p); // proba of flipping k bits, k drawn in binomial distrib, minus zero + foundry.mutations.add< eoShiftedBitMutation >(p); // proba of flipping k bits, k drawn in binomial distrib, changing zeros to one + foundry.mutations.add< eoNormalBitMutation >(p); // proba of flipping k bits, k drawn in normal distrib + foundry.mutations.add< eoFastBitMutation >(p); // proba of flipping k bits, k drawn in powerlaw distrib + for(size_t i=1; i < 11; i+=1) { + foundry.mutations.add< eoDetSingleBitFlip >(i); // mutate k bits without duplicates + } + + /***** Selectors *****/ + foundry.selectors.add< eoRandomSelect >(); + foundry.selectors.add< eoSequentialSelect >(); + foundry.selectors.add< eoProportionalSelect >(); + for(size_t i=2; i < 10; i+=1) { // Tournament size. + foundry.selectors.add< eoDetTournamentSelect >(i); + } + for(double i=0.51; i<0.91; i+=0.1) { // Tournament size as perc of pop. + foundry.selectors.add< eoStochTournamentSelect >(i); + } + + /***** Replacements ****/ + foundry.replacements.add< eoPlusReplacement >(); + foundry.replacements.add< eoCommaReplacement >(); + foundry.replacements.add< eoSSGAWorseReplacement >(); + for(double i=0.51; i<0.91; i+=0.1) { + foundry.replacements.add< eoSSGAStochTournamentReplacement >(i); + } + for(size_t i=2; i < 10; i+=1) { + foundry.replacements.add< eoSSGADetTournamentReplacement >(i); + } + + return foundry; +} + +Bits::Fitness fake_func(const Bits&) { return 0; } + + +int main(int argc, char* argv[]) +{ + /***** Global parameters. *****/ + enum { ERROR_USAGE = 100 }; + + const size_t dimension = 1000; + const size_t max_evals = 2 * dimension; + const size_t buckets = 100; + + eoFunctorStore store; + + /***** Parameters managed by the caller. *****/ + assert(argc == 11); + const int pb_instance = std::atoi(argv[1]); + + std::string s(argv[2]); + eo::rng.reseed(std::stoull(s)); + + Ints encoded_algo(8); + encoded_algo[0] = std::atoi(argv[3]); // continuator + encoded_algo[1] = std::atoi(argv[4]); // crossover_rate + encoded_algo[2] = std::atoi(argv[5]); // crossover + encoded_algo[3] = std::atoi(argv[6]); // mutation_rate + encoded_algo[4] = std::atoi(argv[7]); // mutation + encoded_algo[5] = std::atoi(argv[8]); // selection + encoded_algo[6] = std::atoi(argv[9]); // pop_size + encoded_algo[7] = std::atoi(argv[10]); // replacement + + const size_t pop_size = encoded_algo[6]; + const size_t generations = max_evals / pop_size; + + eo::log << eo::setlevel(eo::warnings); + + /***** IOH logger *****/ + IOHprofiler_RangeLinear target_range(0, dimension, buckets); + IOHprofiler_RangeLinear budget_range(0, max_evals, buckets); + IOHprofiler_ecdf_logger logger(target_range, budget_range); + + logger.set_complete_flag(true); + logger.set_interval(0); + logger.activate_logger(); + + /***** IOH problem *****/ + double w_model_suite_dummy_para = 0; + int w_model_suite_epitasis_para = 0; + int w_model_suite_neutrality_para = 0; + int w_model_suite_ruggedness_para = 0; + + W_Model_OneMax w_model_om; + std::string problem_name = "OneMax"; + problem_name = problem_name + + "_D" + std::to_string((int)(w_model_suite_dummy_para * dimension)) + + "_E" + std::to_string(w_model_suite_epitasis_para) + + "_N" + std::to_string(w_model_suite_neutrality_para) + + "_R" + std::to_string(w_model_suite_ruggedness_para); + + /// This must be called to configure the w-model to be tested. + w_model_om.set_w_setting(w_model_suite_dummy_para,w_model_suite_epitasis_para, + w_model_suite_neutrality_para,w_model_suite_ruggedness_para); + + /// Set problem_name based on the configuration. + w_model_om.IOHprofiler_set_problem_name(problem_name); + + /// Set problem_id as 1 + w_model_om.IOHprofiler_set_problem_id(1); + w_model_om.IOHprofiler_set_instance_id(pb_instance); + + /// Set dimension. + w_model_om.IOHprofiler_set_number_of_variables(dimension); + + /***** Bindings *****/ + logger.track_problem(w_model_om); + + eoEvalIOHproblem onemax_eval(w_model_om, logger); + eoPopLoopEval pop_onemax(onemax_eval); + + /***** Instanciate and run the algo *****/ + + eoUniformGenerator ugen(0, 1); + eoInitFixedLength onemax_init(/*bitstring size=*/dimension, ugen); + auto& foundry = make_foundry(store, onemax_init, onemax_eval, max_evals, generations); + + size_t n = foundry.continuators.size() * foundry.crossovers.size() * foundry.mutations.size() * foundry.selectors.size() * foundry.replacements.size(); + std::clog << n << " possible algorithms instances." << std::endl; + + // Evaluation of a forged encoded_algo on the sub-problem + eoEvalFoundryFastGA eval_foundry( + foundry, onemax_init, pop_onemax, /*penalization=*/ 0); + + // Actually instanciate and run the algorithm. + eval_foundry(encoded_algo); + + /***** IOH perf stats *****/ + IOHprofiler_ecdf_sum ecdf_sum; + // iRace expects minimization + size_t perf = -1 * ecdf_sum(logger.data()); + + // Output + std::cout << perf << std::endl; +} From 6e8767515c8af9dca72ef19dd845920a9c5de7bf Mon Sep 17 00:00:00 2001 From: Amine Aziz-Alaoui Date: Mon, 21 Sep 2020 17:39:11 +0200 Subject: [PATCH 02/42] add some help to fastga irace contrib --- eo/contrib/irace/fastga.cpp | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index 9682af59f..fecb12759 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -105,7 +105,29 @@ int main(int argc, char* argv[]) eoFunctorStore store; /***** Parameters managed by the caller. *****/ - assert(argc == 11); + if(argc != 11) { + // Fake operators, just to be able to call make_foundry + // to get the configured operators slots. + 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); + + std::cerr << "Usage: " << argv[0] << std::endl; + std::cerr << "\t in [0,18]" << std::endl; + std::cerr << "\t in [0,MAXULONG[" << std::endl; + std::cerr << "\t in [0," << fake_foundry.continuators .size() << "[" << std::endl; + std::cerr << "\t in [0," << fake_foundry.crossover_rates.size() << "[" << std::endl; + std::cerr << "\t in [0," << fake_foundry.crossovers .size() << "[" << std::endl; + std::cerr << "\t in [0," << fake_foundry.mutation_rates .size() << "[" << std::endl; + std::cerr << "\t in [0," << fake_foundry.mutations .size() << "[" << std::endl; + std::cerr << "\t in [0," << fake_foundry.selectors .size() << "[" << std::endl; + std::cerr << "\t in [0," << fake_foundry.pop_sizes .size() << "[" << std::endl; + std::cerr << "\t in [0," << fake_foundry.replacements .size() << "[" << std::endl; + + exit(ERROR_USAGE); + } + const int pb_instance = std::atoi(argv[1]); std::string s(argv[2]); @@ -188,8 +210,10 @@ int main(int argc, char* argv[]) /***** IOH perf stats *****/ IOHprofiler_ecdf_sum ecdf_sum; // iRace expects minimization - size_t perf = -1 * ecdf_sum(logger.data()); + long perf = ecdf_sum(logger.data()); // Output - std::cout << perf << std::endl; + std::cout << -1 * perf << std::endl; + + assert(0 < perf and perf <= buckets*buckets); } From 8f949409e706f65d74f7b9db04f6d03aa6ce9f59 Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 21 Sep 2020 17:40:49 +0200 Subject: [PATCH 03/42] add a scalar template to eoInt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some applications may want size_t instead of a siméle int, for example. --- eo/src/eoInt.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/eo/src/eoInt.h b/eo/src/eoInt.h index 3975743e8..0f0feb3e1 100644 --- a/eo/src/eoInt.h +++ b/eo/src/eoInt.h @@ -36,7 +36,7 @@ * * @ingroup Representations */ -template class eoInt: public eoVector +template class eoInt: public eoVector { public: @@ -45,14 +45,14 @@ template class eoInt: public eoVector * @param size Size of the std::vector * @param value fill the vector with this value */ - eoInt(unsigned size = 0, int value = 0) : - eoVector(size, value) + eoInt(unsigned size = 0, T value = 0) : + eoVector(size, value) {} /** Constructor copying from a vector (or an initialization list). */ - eoInt(std::vector vec) : - eoVector(vec) + eoInt(std::vector vec) : + eoVector(vec) {} /// My class name. From a6c68f324a34806f4680a56b98c900c452163915 Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 21 Sep 2020 17:41:35 +0200 Subject: [PATCH 04/42] add templatized version of eoM**imizingFitness Called eoM**imizingFitnessT, so as to not break up ascendent compatibility. --- eo/src/eoScalarFitness.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/eo/src/eoScalarFitness.h b/eo/src/eoScalarFitness.h index 090589446..b31b6acbb 100644 --- a/eo/src/eoScalarFitness.h +++ b/eo/src/eoScalarFitness.h @@ -112,9 +112,14 @@ comparing with less is the default behaviour. // typedef eoScalarFitness > eoMinimizingFitness; // #endif -using eoMaximizingFitness = eoScalarFitness >; -using eoMinimizingFitness = eoScalarFitness >; +template +using eoMaximizingFitnessT = eoScalarFitness >; +template +using eoMinimizingFitnessT = eoScalarFitness >; + +using eoMaximizingFitness = eoMaximizingFitnessT; +using eoMinimizingFitness = eoMinimizingFitnessT; template std::ostream& operator<<(std::ostream& os, const eoScalarFitness& f) From 3f4d9bf7280156a1711ace8789284cdaf8c2fec3 Mon Sep 17 00:00:00 2001 From: Amine Aziz-Alaoui Date: Mon, 21 Sep 2020 17:45:13 +0200 Subject: [PATCH 05/42] fix foundry encoding - remove normalization, use direct encoding in foundries - add fastGA in --- eo/src/eo | 1 + eo/src/eoAlgoFoundryFastGA.h | 39 ++++++++++++++++++++---------------- eo/src/eoEasyEA.h | 2 +- eo/src/eoEvalFoundryEA.h | 19 ++++++++++++------ 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/eo/src/eo b/eo/src/eo index a296c7091..ced1abdcc 100644 --- a/eo/src/eo +++ b/eo/src/eo @@ -164,6 +164,7 @@ #include "eoAlgoFoundryEA.h" #include "eoAlgoFoundryFastGA.h" #include "eoEvalFoundryEA.h" +#include "eoEvalFoundryFastGA.h" //----------------------------------------------------------------------------- // to be continued ... diff --git a/eo/src/eoAlgoFoundryFastGA.h b/eo/src/eoAlgoFoundryFastGA.h index f9ab98f00..ca64f44e8 100644 --- a/eo/src/eoAlgoFoundryFastGA.h +++ b/eo/src/eoAlgoFoundryFastGA.h @@ -82,7 +82,12 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry /** The constructon only take an eval, because all other operators * are stored in the public containers. */ - eoAlgoFoundryFastGA( eoInit & init, eoEvalFunc& eval, size_t max_evals = 10000, size_t max_restarts = std::numeric_limits::max() ) : + eoAlgoFoundryFastGA( + eoInit & init, + eoEvalFunc& eval, + size_t max_evals = 10000, + size_t max_restarts = std::numeric_limits::max() + ) : eoAlgoFoundry(8), continuators(0, true), // Always re-instantiate continuators, because they hold a state. crossover_rates(1, false), @@ -115,14 +120,14 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry */ void operator()(eoPop& pop) { - assert(continuators.size() > 0); assert(this->at(continuators.index()) < continuators.size()); - assert( crossover_rates.size() > 0); assert(this->at( crossover_rates.index()) < crossover_rates.size()); - assert( crossovers.size() > 0); assert(this->at( crossovers.index()) < crossovers.size()); - assert( mutation_rates.size() > 0); assert(this->at( mutation_rates.index()) < mutation_rates.size()); - assert( mutations.size() > 0); assert(this->at( mutations.index()) < mutations.size()); - assert( selectors.size() > 0); assert(this->at( selectors.index()) < selectors.size()); - assert( pop_sizes.size() > 0); assert(this->at( pop_sizes.index()) < pop_sizes.size()); - assert(replacements.size() > 0); assert(this->at(replacements.index()) < replacements.size()); + assert( continuators.size() > 0); assert(this->at( continuators.index()) < continuators.size()); + assert(crossover_rates.size() > 0); assert(this->at(crossover_rates.index()) < crossover_rates.size()); + assert( crossovers.size() > 0); assert(this->at( crossovers.index()) < crossovers.size()); + assert( mutation_rates.size() > 0); assert(this->at( mutation_rates.index()) < mutation_rates.size()); + assert( mutations.size() > 0); assert(this->at( mutations.index()) < mutations.size()); + assert( selectors.size() > 0); assert(this->at( selectors.index()) < selectors.size()); + assert( pop_sizes.size() > 0); assert(this->at( pop_sizes.index()) < pop_sizes.size()); + assert( replacements.size() > 0); assert(this->at( replacements.index()) < replacements.size()); // Crossover or clone double cross_rate = this->crossover_rate(); @@ -180,14 +185,14 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry std::string name() { std::ostringstream name; - name << this->at(continuators.index()) << " (" << this->continuator().className() << ") + "; - name << this->at(crossover_rates.index()) << " (" << this->crossover_rate().className() << ") + "; - name << this->at(crossovers.index()) << " (" << this->crossover().className() << ") + "; - name << this->at(mutation_rates.index()) << " (" << this->mutation_rate().className() << ") + "; - name << this->at(mutations.index()) << " (" << this->mutation().className() << ") + "; - name << this->at(selectors.index()) << " (" << this->selector().className() << ") + "; - name << this->at(pop_sizes.index()) << " (" << this->pop_size().className() << ")"; - name << this->at(replacements.index()) << " (" << this->replacement().className() << ")"; + name << this->at( continuators.index()) << " (" << this-> continuator().className() << ") + "; + name << this->at(crossover_rates.index()) << " (" << this->crossover_rate() << ") + "; + name << this->at( crossovers.index()) << " (" << this-> crossover().className() << ") + "; + name << this->at( mutation_rates.index()) << " (" << this-> mutation_rate() << ") + "; + name << this->at( mutations.index()) << " (" << this-> mutation().className() << ") + "; + name << this->at( selectors.index()) << " (" << this-> selector().className() << ") + "; + name << this->at( pop_sizes.index()) << " (" << this-> pop_size() << ")"; + name << this->at( replacements.index()) << " (" << this-> replacement().className() << ")"; return name.str(); } diff --git a/eo/src/eoEasyEA.h b/eo/src/eoEasyEA.h index fc2ebd6b2..ace02604a 100644 --- a/eo/src/eoEasyEA.h +++ b/eo/src/eoEasyEA.h @@ -272,7 +272,7 @@ template class eoEasyEA: public eoAlgo replace(_pop, offspring); // after replace, the new pop. is in _pop - std::cout << _pop << std::endl; + // std::cout << _pop << std::endl; if (pSize > _pop.size()) throw eoException("Population shrinking!"); diff --git a/eo/src/eoEvalFoundryEA.h b/eo/src/eoEvalFoundryEA.h index f3b33cba5..76521c9b6 100644 --- a/eo/src/eoEvalFoundryEA.h +++ b/eo/src/eoEvalFoundryEA.h @@ -92,12 +92,19 @@ public: */ std::vector decode( const EOT& sol ) const { - // Denormalize - size_t cont = static_cast(std::ceil( sol[i_cont] * _foundry.continuators.size() )); - size_t cros = static_cast(std::ceil( sol[i_cros] * _foundry.crossovers .size() )); - size_t muta = static_cast(std::ceil( sol[i_muta] * _foundry.mutations .size() )); - size_t sele = static_cast(std::ceil( sol[i_sele] * _foundry.selectors .size() )); - size_t repl = static_cast(std::ceil( sol[i_repl] * _foundry.replacements.size() )); + // // Denormalize + // size_t cont = static_cast(std::ceil( sol[i_cont] * _foundry.continuators.size() )); + // size_t cros = static_cast(std::ceil( sol[i_cros] * _foundry.crossovers .size() )); + // size_t muta = static_cast(std::ceil( sol[i_muta] * _foundry.mutations .size() )); + // size_t sele = static_cast(std::ceil( sol[i_sele] * _foundry.selectors .size() )); + // size_t repl = static_cast(std::ceil( sol[i_repl] * _foundry.replacements.size() )); + + // Direct encoding + size_t cont = static_cast(std::ceil( sol[i_cont] )); + size_t cros = static_cast(std::ceil( sol[i_cros] )); + size_t muta = static_cast(std::ceil( sol[i_muta] )); + size_t sele = static_cast(std::ceil( sol[i_sele] )); + size_t repl = static_cast(std::ceil( sol[i_repl] )); return {cont, cros, muta, sele, repl}; } From 7512ed0635ca6168e645d3f7b37f6b7e7de0a7e2 Mon Sep 17 00:00:00 2001 From: nojhan Date: Mon, 21 Sep 2020 18:05:08 +0200 Subject: [PATCH 06/42] add missing header in a test --- eo/src/eoProportionalSelect.h | 1 + 1 file changed, 1 insertion(+) diff --git a/eo/src/eoProportionalSelect.h b/eo/src/eoProportionalSelect.h index 1aa74a35b..3fd49aded 100644 --- a/eo/src/eoProportionalSelect.h +++ b/eo/src/eoProportionalSelect.h @@ -34,6 +34,7 @@ #include "utils/eoRNG.h" #include "utils/selectors.h" +#include "utils/eoLogger.h" #include "eoSelectOne.h" #include "eoPop.h" From 5d3253ef7ad917b05ce8769ce0f966915ae114d5 Mon Sep 17 00:00:00 2001 From: Amine Aziz-Alaoui Date: Mon, 21 Sep 2020 18:05:40 +0200 Subject: [PATCH 07/42] add two FastGA tests --- eo/test/CMakeLists.txt | 1 + eo/test/t-FastGA.cpp | 62 ++++++++++++++++++++ eo/test/t-forge-FastGA.cpp | 115 +++++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 eo/test/t-FastGA.cpp create mode 100644 eo/test/t-forge-FastGA.cpp diff --git a/eo/test/CMakeLists.txt b/eo/test/CMakeLists.txt index 5229f99f4..07093d4fe 100644 --- a/eo/test/CMakeLists.txt +++ b/eo/test/CMakeLists.txt @@ -76,6 +76,7 @@ set (TEST_LIST t-algo-forged t-algo-forged-search t-FastGA + t-forge-FastGA t-eoFoundryFastGA ) diff --git a/eo/test/t-FastGA.cpp b/eo/test/t-FastGA.cpp new file mode 100644 index 000000000..3dc08b370 --- /dev/null +++ b/eo/test/t-FastGA.cpp @@ -0,0 +1,62 @@ +#include +#include + +#include +#include +#include "../../problems/eval/oneMaxEval.h" + +using EOT = eoBit; + +int main(int /*argc*/, char** /*argv*/) +{ + size_t dim = 5; + size_t pop_size = 3; + + oneMaxEval evalfunc; + eoPopLoopEval eval(evalfunc); + + eoBooleanGenerator gen(0.5); + eoInitFixedLength init(dim, gen); + + double cross_rate = 0.5; + eoProportionalOp cross; + // Cross-over that produce only one offspring, + // made by wrapping the quad op (which produce 2 offsprings) + // in a bin op (which ignore the second offspring). + eo1PtBitXover crossover; + eoQuad2BinOp mono_cross(crossover); + cross.add(mono_cross, cross_rate); + eoBinCloneOp bin_clone; + cross.add(bin_clone, 1 - cross_rate); // Clone + + double mut_rate = 0.5; + eoProportionalOp mut; + eoShiftedBitMutation mutation(0.5); + mut.add(mutation, mut_rate); + eoMonCloneOp mon_clone; + mut.add(mon_clone, 1 - mut_rate); // FIXME TBC + + eoSequentialOp variator; + variator.add(cross,1.0); + variator.add(mut,1.0); + + double lambda = 1.0; // i.e. 100% + eoStochTournamentSelect selector(0.5); + eoGeneralBreeder breeder(selector, variator, lambda); + + eoGenContinue common_cont(3); + eoCombinedContinue gen_cont(common_cont); + //gen_cont.add(continuator); + + eoPlusReplacement replacement; + + eoEasyEA algo = eoEasyEA(gen_cont, eval, breeder, replacement); + + eoPop pop; + pop.append(pop_size, init); + eval(pop,pop); + + algo(pop); + + std::cout << pop.best_element() << std::endl; +} diff --git a/eo/test/t-forge-FastGA.cpp b/eo/test/t-forge-FastGA.cpp new file mode 100644 index 000000000..e4f713cff --- /dev/null +++ b/eo/test/t-forge-FastGA.cpp @@ -0,0 +1,115 @@ +#include +#include + +#include +#include +#include "../../problems/eval/oneMaxEval.h" + +int main(int /*argc*/, char** /*argv*/) +{ + size_t dim = 500; + size_t pop_size = 10; + + eo::log << eo::setlevel(eo::warnings); + + using EOT = eoBit; + + oneMaxEval eval; + + eoBooleanGenerator gen(0.5); + eoInitFixedLength init(dim, gen); + + eoGenContinue common_cont(100); + + eoForgeVector< eoContinue > continuators; + continuators.add< eoSteadyFitContinue >(10,10); + continuators.add< eoGenContinue >(100); + + eoForgeVector< eoQuadOp > crossovers; + crossovers.add< eo1PtBitXover >(); + crossovers.add< eoUBitXover >(0.5); // preference over 1 + crossovers.add< eoNPtsBitXover >(2); // nb of points + + eoForgeVector< eoMonOp > mutations; + mutations.add< eoBitMutation >(0.01); // proba of flipping one bit + mutations.add< eoDetBitFlip >(1); // mutate k bits + + eoForgeVector< eoSelectOne > selectors; + selectors.add< eoDetTournamentSelect >(pop_size/2); + selectors.add< eoStochTournamentSelect >(0.5); + selectors.add< eoSequentialSelect >(); + selectors.add< eoProportionalSelect >(); + + eoForgeVector< eoReplacement > replacors; + replacors.add< eoCommaReplacement >(); + replacors.add< eoPlusReplacement >(); + replacors.add< eoSSGAWorseReplacement >(); + replacors.add< eoSSGADetTournamentReplacement >(pop_size/2); + replacors.add< eoSSGAStochTournamentReplacement >(0.51); + + std::clog << continuators.size() * crossovers.size() * mutations.size() * selectors.size() * replacors.size() + << " possible algorithms instances." << std::endl; + + EOT best_sol; + std::string best_algo = ""; + + for(auto& forge_cont : continuators) { + auto& continuator = forge_cont->instantiate(); + + for(auto& forge_cross : crossovers) { + auto& crossover = forge_cross->instantiate(); + + for(auto& forge_mut : mutations ) { + auto& mutation = forge_mut->instantiate(); + + for(auto& forge_sel : selectors) { + auto& selector = forge_sel->instantiate(); + + for(auto& forge_rep : replacors) { + auto& replacor = forge_rep->instantiate(); + + std::ostringstream algo_name; + algo_name << continuator.className() << " + " + << crossover.className() << " + " + << mutation.className() << " + " + << selector.className() << " + " + << replacor.className(); + + std::clog << "ALGO: " << algo_name.str(); + std::clog.flush(); + + eoSequentialOp variator; + variator.add(crossover, 1.0); + variator.add(mutation, 1.0); + + eoGeneralBreeder breeder(selector, variator, 1.0); + + eoCombinedContinue gen_cont(common_cont); + gen_cont.add(continuator); + + eoEasyEA algo(gen_cont, eval, breeder, replacor); + + eoPop pop; + pop.append(pop_size, init); + ::apply(eval,pop); + + algo(pop); + + std::clog << " = " << pop.best_element().fitness() << std::endl; + + if(best_sol.invalid()) { + best_sol = pop.best_element(); + best_algo = algo_name.str(); + } else if(pop.best_element().fitness() > best_sol.fitness()) { + best_sol = pop.best_element(); + best_algo = algo_name.str(); + } + + } + } + } + } + } + std::cout << "Best algo: " << best_algo << ", with " << best_sol << std::endl; + +} From 5d6f87c98c0f2e90a4f69d4fb0b1f791d07365d7 Mon Sep 17 00:00:00 2001 From: Amine Aziz-Alaoui Date: Tue, 22 Sep 2020 15:41:13 +0200 Subject: [PATCH 08/42] add missing eval foundry for fastga --- eo/src/eoEvalFoundryFastGA.h | 196 +++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 eo/src/eoEvalFoundryFastGA.h diff --git a/eo/src/eoEvalFoundryFastGA.h b/eo/src/eoEvalFoundryFastGA.h new file mode 100644 index 000000000..4b2232eea --- /dev/null +++ b/eo/src/eoEvalFoundryFastGA.h @@ -0,0 +1,196 @@ + +/* + 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; + version 2 of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + © 2020 Thales group + + Authors: + Johann Dreo +*/ + +#ifndef _eoEvalFoundryFastGA_H_ +#define _eoEvalFoundryFastGA_H_ + +#include "eoEvalFunc.h" +#include "eoAlgoFoundryFastGA.h" +#include "eoInit.h" +#include "eoPopEvalFunc.h" + +/** Evaluate an algorithm assembled by an eoAlgoFoundryFastGA, encoded as a numeric vector. + * + * Allows to plug another search algorithm on top of an eoAlgoFoundryFastGA, + * so as to find the best configuration. + * + * The first template EOT is the encoding of the high-level algorithm selection problem, + * the second template SUB is the encoding of the low-level generic problem. + * + * @ingroup Evaluation + * @ingroup Foundry + */ +template +class eoEvalFoundryFastGA : public eoEvalFunc +{ +public: + /** Takes the necessary parameters to perform a search on the sub-problem. + * + * @param foundry The set of algorithms among which to select. + * @param subpb_init An initilizer for sub-problem encoding. + * @param pop_size Population size for the sub-problem solver. + * @param subpb_eval The sub-problem itself. + * @param penalization If any solution to the high-level algorithm selection problem is out of bounds, set it to this value. + */ + eoEvalFoundryFastGA( + eoAlgoFoundryFastGA& foundry, + eoInit& subpb_init, + eoPopEvalFunc& subpb_eval, + const typename SUB::Fitness penalization + ) : + _subpb_init(subpb_init), + _subpb_eval(subpb_eval), + _foundry(foundry), + _penalization(penalization), + i_cont(foundry.continuators.index()), + i_crat(foundry.crossover_rates.index()), + i_cros(foundry.crossovers.index()), + i_mrat(foundry.mutation_rates.index()), + i_muta(foundry.mutations.index()), + i_sele(foundry.selectors.index()), + i_pops(foundry.pop_sizes.index()), + i_repl(foundry.replacements.index()) + { } + +protected: + const size_t i_cont; + const size_t i_crat; + const size_t i_cros; + const size_t i_mrat; + const size_t i_muta; + const size_t i_sele; + const size_t i_pops; + const size_t i_repl; + +public: + + /** 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 eoAlgoFoundryFastGA. + * @code + * foundry = eval.decode(pop.best_element()); + * std::cout << foundry.name() << std::endl; + * auto& cont = foundry.continuator(); // Get the configured operator + * @encode + */ + std::vector decode( const EOT& sol ) const + { + // Denormalize + // size_t cont = static_cast(std::ceil( sol[i_cont] * _foundry.continuators .size() )); + // size_t crat = static_cast(std::ceil( sol[i_crat] * _foundry.crossover_rates.size() )); + // size_t cros = static_cast(std::ceil( sol[i_cros] * _foundry.crossovers .size() )); + // size_t mrat = static_cast(std::ceil( sol[i_mrat] * _foundry.mutation_rates .size() )); + // size_t muta = static_cast(std::ceil( sol[i_muta] * _foundry.mutations .size() )); + // size_t sele = static_cast(std::ceil( sol[i_sele] * _foundry.selectors .size() )); + // size_t pops = static_cast(std::ceil( sol[i_pops] * _foundry.pop_sizes .size() )); + // size_t repl = static_cast(std::ceil( sol[i_repl] * _foundry.replacements .size() )); + + // Direct encoding + size_t cont = static_cast(std::ceil( sol[i_cont] )); + size_t crat = static_cast(std::ceil( sol[i_crat] )); + size_t cros = static_cast(std::ceil( sol[i_cros] )); + size_t mrat = static_cast(std::ceil( sol[i_mrat] )); + size_t muta = static_cast(std::ceil( sol[i_muta] )); + size_t sele = static_cast(std::ceil( sol[i_sele] )); + size_t pops = static_cast(std::ceil( sol[i_pops] )); + size_t repl = static_cast(std::ceil( sol[i_repl] )); + + return {cont, crat, cros, mrat, muta, sele, pops, repl}; + } + + /** Perform a sub-problem search with the configuration encoded in the given solution + * and set its (high-level) fitness to the best (low-level) fitness found. + * + * You may want to overload this to perform multiple runs or solve multiple sub-problems. + */ + virtual void operator()(EOT& sol) + { + if(not sol.invalid()) { + return; + } + + auto config = decode(sol); + double cont = config[i_cont]; + double crat = config[i_crat]; + double cros = config[i_cros]; + double mrat = config[i_mrat]; + double muta = config[i_muta]; + double sele = config[i_sele]; + double pops = config[i_pops]; + double repl = config[i_repl]; + + if( + 0 <= cont and cont < _foundry.continuators .size() + and 0 <= crat and crat < _foundry.crossover_rates.size() + and 0 <= cros and cros < _foundry.crossovers .size() + and 0 <= mrat and mrat < _foundry.mutation_rates .size() + and 0 <= muta and muta < _foundry.mutations .size() + and 0 <= sele and sele < _foundry.selectors .size() + and 0 <= pops and pops < _foundry.pop_sizes .size() + and 0 <= repl and repl < _foundry.replacements .size() + ) { + _foundry.select(config); + + // FIXME should pop_size belong to this eval and moved out from the foundry? + // Reset pop + eoPop pop; + pop.append( _foundry.pop_size(), _subpb_init); + _subpb_eval(pop,pop); + + // Actually perform a search + _foundry(pop); + + sol.fitness( pop.best_element().fitness() ); + + } else { + eo::log << eo::warnings << "WARNING: encoded algo is out of bounds" << std::endl; + sol.fitness( _penalization ); // penalization + } + } + +protected: + eoInit& _subpb_init; + eoPopEvalFunc& _subpb_eval; + eoAlgoFoundryFastGA& _foundry; + const typename EOT::Fitness _penalization; +}; + +/** Helper function to instanciate an eoEvalFoundryFastGA without having to indicate the template for the sub-problem encoding. + * + * The template is deduced from the constructor's parameters. + * Not sure it's more concise than a classical instanciation… + */ +template +eoEvalFoundryFastGA& + make_eoEvalFoundryFastGA( + eoInit& subpb_init, + eoPopEvalFunc& subpb_eval, + eoAlgoFoundryFastGA& foundry, + const typename SUB::Fitness penalization ) +{ + return *(new eoEvalFoundryFastGA(subpb_init, subpb_eval, foundry, penalization)); +} + +#endif // _eoEvalFoundryFastGA_H_ + From 70f21e95cf594851076a4f2fe3afeb552ab19c90 Mon Sep 17 00:00:00 2001 From: Amine Aziz-Alaoui Date: Tue, 22 Sep 2020 15:42:05 +0200 Subject: [PATCH 09/42] add a parameter to make_help to inidicate output --- eo/src/utils/checkpointing | 2 +- eo/src/utils/make_help.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/eo/src/utils/checkpointing b/eo/src/utils/checkpointing index ad190602a..60f2b81d4 100644 --- a/eo/src/utils/checkpointing +++ b/eo/src/utils/checkpointing @@ -50,7 +50,7 @@ #include "eoGenCounter.h" // and make_help - any better suggestion to include it? -void make_help(eoParser & _parser, bool exit_after = true); +void make_help(eoParser & _parser, bool exit_after = true, std::ostream& out = std::cout); #endif // !_CHECKPOINTING_ diff --git a/eo/src/utils/make_help.cpp b/eo/src/utils/make_help.cpp index b7d5ff766..b021e0177 100644 --- a/eo/src/utils/make_help.cpp +++ b/eo/src/utils/make_help.cpp @@ -44,7 +44,7 @@ * It is declared in all make_xxx.h files in representation-dependent dirs * but it is NOT representation-dependent itself - that's why it's in utils */ -void make_help(eoParser & _parser, bool exit_after) +void make_help(eoParser & _parser, bool exit_after, std::ostream& out) { // name of the "status" file where all actual parameter values will be saved std::string str_status = _parser.ProgramName() + ".status"; // default value @@ -62,8 +62,8 @@ void make_help(eoParser & _parser, bool exit_after) // i.e. in case you need parameters somewhere else, postpone these if (_parser.userNeedsHelp()) { - _parser.printHelp(std::cout); - std::cout << "You can use an edited copy of file " << statusParam.value() + _parser.printHelp(out); + out << "You can use an edited copy of file " << statusParam.value() << " as parameter file" << std::endl; if(exit_after) { exit(0); From 93da7a8dae5361b081d7bbf5f63dd34f765cdda4 Mon Sep 17 00:00:00 2001 From: Amine Aziz-Alaoui Date: Tue, 22 Sep 2020 15:42:31 +0200 Subject: [PATCH 10/42] fix wrong doc for algo foundry --- eo/src/eoAlgoFoundry.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/eo/src/eoAlgoFoundry.h b/eo/src/eoAlgoFoundry.h index 0efa18a6d..19ffb5023 100644 --- a/eo/src/eoAlgoFoundry.h +++ b/eo/src/eoAlgoFoundry.h @@ -76,12 +76,12 @@ class eoOperatorFoundry : public eoForgeVector< Itf > * In a second step, the operators to be used should be selected * by indicating their index, just like if the foundry was an array: * @code - * foundry = {0, 1, 2}; - * // ^ ^ ^ - * // | | | - * // | | + 3d operator - * // | + 2d operator - * // + 1st operator + * foundry.select({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, From 367a8c8ab1e11eecbe09f5b7defb06f46b0283fc Mon Sep 17 00:00:00 2001 From: Amine Aziz-Alaoui Date: Tue, 22 Sep 2020 15:42:49 +0200 Subject: [PATCH 11/42] easier interface for fastga in irace contrib --- eo/contrib/irace/fastga.cpp | 167 +++++++++++++++++++++++++++--------- 1 file changed, 128 insertions(+), 39 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index fecb12759..dc413466a 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -92,20 +92,97 @@ eoAlgoFoundryFastGA& make_foundry( Bits::Fitness fake_func(const Bits&) { return 0; } +void print_param_range(const eoParam& param, const size_t slot_size, std::ostream& out = std::cout) +{ + out << param.longName() + << "\t\"--" << param.longName() << "=\"" + << "\ti" + << "\t(0," << slot_size << ")" + << std::endl; +} int main(int argc, char* argv[]) { /***** Global parameters. *****/ - enum { ERROR_USAGE = 100 }; - - const size_t dimension = 1000; - const size_t max_evals = 2 * dimension; - const size_t buckets = 100; + enum { NO_ERROR = 0, ERROR_USAGE = 100 }; eoFunctorStore store; - /***** Parameters managed by the caller. *****/ - if(argc != 11) { + eoParser parser(argc, argv, "FastGA interface for iRace"); + + const size_t dimension = parser.getORcreateParam(1000, + "dimension", "Dimension size", + 'd', "Problem").value(); + + const size_t max_evals = parser.getORcreateParam(2 * dimension, + "max-evals", "Maximum number of evaluations", + 'e', "Stopping criterion").value(); + + const size_t buckets = parser.getORcreateParam(100, + "buckets", "Number of buckets for discretizing the ECDF", + 'b', "Performance estimation").value(); + + uint32_t seed = + parser.getORcreateParam(0, + "seed", "Random number seed (0 = epoch)", + 'S').value(); + if(seed == 0) { + seed = time(0); + } + // rng is a global + rng.reseed(seed); + + auto instance_p = parser.getORcreateParam(1, + "instance", "Instance ID", + 'i', "Problem", /*required=*/true); + const size_t instance = instance_p.value(); + + auto continuator_p = parser.getORcreateParam(0, + "continuator", "", + 'o', "Evolution Engine", /*required=*/true); + const size_t continuator = continuator_p.value(); + + auto crossover_rate_p = parser.getORcreateParam(0, + "crossover-rate", "", + 'C', "Evolution Engine", /*required=*/true); + const size_t crossover_rate = crossover_rate_p.value(); + + auto crossover_p = parser.getORcreateParam(0, + "crossover", "", + 'c', "Evolution Engine", /*required=*/true); + const size_t crossover = crossover_p.value(); + + auto mutation_rate_p = parser.getORcreateParam(0, + "mutation-rate", "", + 'M', "Evolution Engine", /*required=*/true); + const size_t mutation_rate = mutation_rate_p.value(); + + auto mutation_p = parser.getORcreateParam(0, + "mutation", "", + 'm', "Evolution Engine", /*required=*/true); + const size_t mutation = mutation_p.value(); + + auto selector_p = parser.getORcreateParam(0, + "selector", "", + 's', "Evolution Engine", /*required=*/true); + const size_t selector = selector_p.value(); + + auto pop_size_p = parser.getORcreateParam(0, + "pop-size", "", + 'P', "Evolution Engine", /*required=*/true); + const size_t pop_size = pop_size_p.value(); + + auto replacement_p = parser.getORcreateParam(0, + "replacement", "", + 'r', "Evolution Engine", /*required=*/true); + const size_t replacement = replacement_p.value(); + + // Help + Verbose routines + make_verbose(parser); + make_help(parser, /*exit_after*/false, std::clog); + + if(parser.userNeedsHelp()) { + // Fake operators, just to be able to call make_foundry // to get the configured operators slots. eoEvalFuncPtr fake_eval(fake_func); @@ -113,40 +190,44 @@ int main(int argc, char* argv[]) eoInitFixedLength fake_init(/*bitstring size=*/1, fake_gen); auto fake_foundry = make_foundry(store, fake_init, fake_eval, max_evals, /*generations=*/ 1); - std::cerr << "Usage: " << argv[0] << std::endl; - std::cerr << "\t in [0,18]" << std::endl; - std::cerr << "\t in [0,MAXULONG[" << std::endl; - std::cerr << "\t in [0," << fake_foundry.continuators .size() << "[" << std::endl; - std::cerr << "\t in [0," << fake_foundry.crossover_rates.size() << "[" << std::endl; - std::cerr << "\t in [0," << fake_foundry.crossovers .size() << "[" << std::endl; - std::cerr << "\t in [0," << fake_foundry.mutation_rates .size() << "[" << std::endl; - std::cerr << "\t in [0," << fake_foundry.mutations .size() << "[" << std::endl; - std::cerr << "\t in [0," << fake_foundry.selectors .size() << "[" << std::endl; - std::cerr << "\t in [0," << fake_foundry.pop_sizes .size() << "[" << std::endl; - std::cerr << "\t in [0," << fake_foundry.replacements .size() << "[" << std::endl; + size_t n = fake_foundry.continuators.size() + * fake_foundry.crossovers.size() + * fake_foundry.mutations.size() + * fake_foundry.selectors.size() + * fake_foundry.replacements.size(); + std::clog << n << " possible algorithms instances." << std::endl; - exit(ERROR_USAGE); + std::clog << "Ranges of required parameters (redirect the stdout in a file to use it with iRace): " << std::endl; + + std::cout << "# name\tswitch\ttype\trange" << std::endl; + print_param_range( instance_p, 18, std::cout); + print_param_range( continuator_p, fake_foundry.continuators .size(), std::cout); + print_param_range( crossover_p, fake_foundry.crossovers .size(), std::cout); + print_param_range(crossover_rate_p, fake_foundry.crossover_rates.size(), std::cout); + print_param_range( mutation_p, fake_foundry.mutations .size(), std::cout); + print_param_range( mutation_rate_p, fake_foundry.mutation_rates .size(), std::cout); + print_param_range( selector_p, fake_foundry.selectors .size(), std::cout); + print_param_range( pop_size_p, fake_foundry.pop_sizes .size(), std::cout); + print_param_range( replacement_p, fake_foundry.replacements .size(), std::cout); + + // std::ofstream irace_param("fastga.params"); + // irace_param << "# name\tswitch\ttype\tvalues" << std::endl; + + exit(NO_ERROR); } - const int pb_instance = std::atoi(argv[1]); - - std::string s(argv[2]); - eo::rng.reseed(std::stoull(s)); + const size_t generations = static_cast(std::floor( + static_cast(max_evals) / static_cast(pop_size))); Ints encoded_algo(8); - encoded_algo[0] = std::atoi(argv[3]); // continuator - encoded_algo[1] = std::atoi(argv[4]); // crossover_rate - encoded_algo[2] = std::atoi(argv[5]); // crossover - encoded_algo[3] = std::atoi(argv[6]); // mutation_rate - encoded_algo[4] = std::atoi(argv[7]); // mutation - encoded_algo[5] = std::atoi(argv[8]); // selection - encoded_algo[6] = std::atoi(argv[9]); // pop_size - encoded_algo[7] = std::atoi(argv[10]); // replacement - - const size_t pop_size = encoded_algo[6]; - const size_t generations = max_evals / pop_size; - - eo::log << eo::setlevel(eo::warnings); + encoded_algo[0] = continuator; + encoded_algo[1] = crossover_rate; + encoded_algo[2] = crossover; + encoded_algo[3] = mutation_rate; + encoded_algo[4] = mutation; + encoded_algo[5] = selector; + encoded_algo[6] = pop_size; + encoded_algo[7] = replacement; /***** IOH logger *****/ IOHprofiler_RangeLinear target_range(0, dimension, buckets); @@ -180,7 +261,7 @@ int main(int argc, char* argv[]) /// Set problem_id as 1 w_model_om.IOHprofiler_set_problem_id(1); - w_model_om.IOHprofiler_set_instance_id(pb_instance); + w_model_om.IOHprofiler_set_instance_id(instance); /// Set dimension. w_model_om.IOHprofiler_set_number_of_variables(dimension); @@ -197,8 +278,16 @@ int main(int argc, char* argv[]) eoInitFixedLength onemax_init(/*bitstring size=*/dimension, ugen); auto& foundry = make_foundry(store, onemax_init, onemax_eval, max_evals, generations); - size_t n = foundry.continuators.size() * foundry.crossovers.size() * foundry.mutations.size() * foundry.selectors.size() * foundry.replacements.size(); - std::clog << n << " possible algorithms instances." << std::endl; + std::clog << "Encoded algorithm:" << std::endl; + foundry.select(encoded_algo); + std::clog << "\tcontinuator:\t" << foundry.continuator ().className() << std::endl; + std::clog << "\tcrossover:\t" << foundry.crossover ().className() << std::endl; + std::clog << "\tcrossover_rate:\t" << foundry.crossover_rate() << std::endl; + std::clog << "\tmutation:\t" << foundry.mutation ().className() << std::endl; + std::clog << "\tmutation_rate:\t" << foundry.mutation_rate () << std::endl; + std::clog << "\tselector:\t" << foundry.selector ().className() << std::endl; + std::clog << "\tpop_size:\t" << foundry.pop_size () << std::endl; + std::clog << "\treplacement:\t" << foundry.replacement ().className() << std::endl; // Evaluation of a forged encoded_algo on the sub-problem eoEvalFoundryFastGA eval_foundry( From 40c80eda45f624296ea555380475e9b15fb1beee Mon Sep 17 00:00:00 2001 From: Amine Aziz-Alaoui Date: Wed, 30 Sep 2020 09:47:02 +0200 Subject: [PATCH 12/42] feat: adds a FastGA algo, update the Foundry --- eo/src/eo | 1 + eo/src/eoAlgoFoundryFastGA.h | 148 +++++++++++++++-------------- eo/src/eoFastGA.h | 150 ++++++++++++++++++++++++++++++ eo/test/CMakeLists.txt | 2 + eo/test/t-FastGA.cpp | 17 ++++ eo/test/t-eoAlgoFoundryFastGA.cpp | 147 +++++++++++++++++++++++++++++ eo/test/t-eoFastGA.cpp | 72 ++++++++++++++ 7 files changed, 467 insertions(+), 70 deletions(-) create mode 100644 eo/src/eoFastGA.h create mode 100644 eo/test/t-eoAlgoFoundryFastGA.cpp create mode 100644 eo/test/t-eoFastGA.cpp diff --git a/eo/src/eo b/eo/src/eo index ced1abdcc..b77e9bf2c 100644 --- a/eo/src/eo +++ b/eo/src/eo @@ -146,6 +146,7 @@ // Algorithms #include "eoEasyEA.h" #include "eoSGA.h" +#include "eoFastGA.h" // #include "eoEvolutionStrategy.h" removed for a while - until eoGenOp is done #include "eoAlgoReset.h" #include "eoAlgoRestart.h" diff --git a/eo/src/eoAlgoFoundryFastGA.h b/eo/src/eoAlgoFoundryFastGA.h index ca64f44e8..099507103 100644 --- a/eo/src/eoAlgoFoundryFastGA.h +++ b/eo/src/eoAlgoFoundryFastGA.h @@ -27,30 +27,30 @@ #include #include -/** A class that assemble an eoEasyEA on the fly, given a combination of available operators. +/** A class that assemble an eoFastGA on the fly, given a combination of available operators. * * The foundry should first be set up with sets of operators - * for the main modules of an EA: - * continuators, crossovers, mutations, selection and replacement operators. + * for the main modules of a FastGA: + * continuators, crossovers, mutations, selections, replacement operators, etc. * * This 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 - * foundry.selectors.add< eoStochTournamentSelect >( 0.5 ); + * foundry.selectors.add< eoRandomSelect >(); * @endcode * * @warning If the constructor takes a reference YOU SHOULD ABSOLUTELY wrap it * in a `std::ref`, or it will silently be passed as a copy, - * which would effectively disable any link between operators. + * which would effectively disable any link with other operator(s). * * In a second step, the operators to be used should be selected - * by indicating their index, passing an array of eight elements: + * by indicating their index, passing an array of 10 elements: * @code - * foundry.select({0, 1, 2, 3, 4, 5, 6, 7}); + * foundry.select({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); * @endcode * - * @note: by default, the firsts of the eight operators are selected. + * @note: by default, the firsts of the 10 operators are selected. * * If you don't (want to) recall the order of the operators in the encoding, * you can use the `index()` member, for example: @@ -58,7 +58,7 @@ * 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: + * Now, you can call the foundry just like any eoAlgo, by passing it an eoPop: * @code * foundry(pop); * @encode @@ -69,7 +69,7 @@ * 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 + * foundry.selector.at(0).setup(0.5); // Will call constructor's arguments * @endcode * * @ingroup Foundry @@ -88,15 +88,20 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry size_t max_evals = 10000, size_t max_restarts = std::numeric_limits::max() ) : - eoAlgoFoundry(8), - continuators(0, true), // Always re-instantiate continuators, because they hold a state. - crossover_rates(1, false), + eoAlgoFoundry(10), + + crossover_rates(0, false), + crossover_selectors(1, false), crossovers(2, false), - mutation_rates(3, false), - mutations(4, false), - selectors(5, false), - pop_sizes(6, false), + aftercross_selectors(3, false), + + mutation_rates(4, false), + mutation_selectors(5, false), + mutations(6, false), + replacements(7, false), + continuators(8, true), // Always re-instantiate continuators, because they hold a state. + pop_sizes(9, false), _eval(eval), _init(init), _max_evals(max_evals), @@ -106,62 +111,53 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry public: /* Operators containers @{ */ - eoOperatorFoundry< eoContinue > continuators; eoOperatorFoundry< double > crossover_rates; + eoOperatorFoundry< eoSelectOne > crossover_selectors; eoOperatorFoundry< eoQuadOp > crossovers; + eoOperatorFoundry< eoSelectOne > aftercross_selectors; + eoOperatorFoundry< double > mutation_rates; + eoOperatorFoundry< eoSelectOne > mutation_selectors; eoOperatorFoundry< eoMonOp > mutations; - eoOperatorFoundry< eoSelectOne > selectors; - eoOperatorFoundry< size_t > pop_sizes; + eoOperatorFoundry< eoReplacement > replacements; + eoOperatorFoundry< eoContinue > continuators; + eoOperatorFoundry< size_t > pop_sizes; /* @} */ /** instantiate and call the pre-selected algorithm. */ void operator()(eoPop& pop) { - assert( continuators.size() > 0); assert(this->at( continuators.index()) < continuators.size()); - assert(crossover_rates.size() > 0); assert(this->at(crossover_rates.index()) < crossover_rates.size()); - assert( crossovers.size() > 0); assert(this->at( crossovers.index()) < crossovers.size()); - assert( mutation_rates.size() > 0); assert(this->at( mutation_rates.index()) < mutation_rates.size()); - assert( mutations.size() > 0); assert(this->at( mutations.index()) < mutations.size()); - assert( selectors.size() > 0); assert(this->at( selectors.index()) < selectors.size()); - assert( pop_sizes.size() > 0); assert(this->at( pop_sizes.index()) < pop_sizes.size()); - assert( replacements.size() > 0); assert(this->at( replacements.index()) < replacements.size()); - - // Crossover or clone - double cross_rate = this->crossover_rate(); - eoProportionalOp cross; - // Cross-over that produce only one offspring, - // made by wrapping the quad op (which produce 2 offsprings) - // in a bin op (which ignore the second offspring). - eoQuad2BinOp single_cross(this->crossover()); - cross.add(single_cross, cross_rate); - eoBinCloneOp cross_clone; - cross.add(cross_clone, 1 - cross_rate); // Clone - - // Mutation or clone - double mut_rate = this->mutation_rate(); - eoProportionalOp mut; - mut.add(this->mutation(), mut_rate); - eoMonCloneOp mut_clone; - mut.add(mut_clone, 1 - mut_rate); // FIXME TBC - - // Apply mutation after cross-over. - eoSequentialOp variator; - variator.add(cross,1.0); - variator.add(mut,1.0); - - // All variatiors - double lambda = this->pop_size(); - eoGeneralBreeder breeder(this->selector(), variator, lambda, /*as rate*/false); + 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( pop_sizes.size() > 0); assert(this->at( pop_sizes.index()) < pop_sizes.size()); // Objective function calls counter eoEvalCounterThrowException eval(_eval, _max_evals); eoPopLoopEval pop_eval(eval); // Algorithm itself - eoEasyEA algo = eoEasyEA(this->continuator(), pop_eval, breeder, this->replacement()); + eoFastGA algo( + this->crossover_rate(), + this->crossover_selector(), + this->crossover(), + this->aftercross_selector(), + this->mutation_rate(), + this->mutation_selector(), + this->mutation(), + pop_eval, + this->replacement(), + this->continuator(), + this->pop_size() + ); // Restart wrapper eoAlgoPopReset reset_pop(_init, pop_eval); @@ -172,27 +168,27 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry restart(pop); } catch(eoMaxEvalException e) { // In case some solutions were not evaluated when max eval occured. + // FIXME can this even be considered legal? eoPopLoopEval pop_last_eval(_eval); pop_last_eval(pop,pop); } } /** Return an approximate name of the selected algorithm. - * - * @note: does not take into account parameters of the operators, - * only show class names. */ std::string name() { std::ostringstream name; - name << this->at( continuators.index()) << " (" << this-> continuator().className() << ") + "; - name << this->at(crossover_rates.index()) << " (" << this->crossover_rate() << ") + "; - name << this->at( crossovers.index()) << " (" << this-> crossover().className() << ") + "; - name << this->at( mutation_rates.index()) << " (" << this-> mutation_rate() << ") + "; - name << this->at( mutations.index()) << " (" << this-> mutation().className() << ") + "; - name << this->at( selectors.index()) << " (" << this-> selector().className() << ") + "; - name << this->at( pop_sizes.index()) << " (" << this-> pop_size() << ")"; - name << this->at( replacements.index()) << " (" << this-> replacement().className() << ")"; + name << this->at( crossover_rates.index()) << " (" << this-> crossover_rate() << ") + "; + name << this->at( crossover_selectors.index()) << " (" << this-> crossover_selector().className() << ") + "; + name << this->at(aftercross_selectors.index()) << " (" << this->aftercross_selector().className() << ") + "; + name << this->at( crossovers.index()) << " (" << this-> crossover().className() << ") + "; + name << this->at( mutation_rates.index()) << " (" << this-> mutation_rate() << ") + "; + name << this->at( mutation_selectors.index()) << " (" << this-> mutation_selector().className() << ") + "; + name << this->at( mutations.index()) << " (" << this-> mutation().className() << ") + "; + name << this->at( replacements.index()) << " (" << this-> replacement().className() << ") + "; + name << this->at( continuators.index()) << " (" << this-> continuator().className() << ") + "; + name << this->at( pop_sizes.index()) << " (" << this-> pop_size() << ")"; return name.str(); } @@ -233,10 +229,22 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry return mutations.instantiate(this->at(mutations.index())); } - eoSelectOne& selector() + eoSelectOne& crossover_selector() { - assert(this->at(selectors.index()) < selectors.size()); - return selectors.instantiate(this->at(selectors.index())); + assert(this->at(crossover_selectors.index()) < crossover_selectors.size()); + return crossover_selectors.instantiate(this->at(crossover_selectors.index())); + } + + eoSelectOne& aftercross_selector() + { + assert(this->at(aftercross_selectors.index()) < aftercross_selectors.size()); + return aftercross_selectors.instantiate(this->at(aftercross_selectors.index())); + } + + eoSelectOne& mutation_selector() + { + assert(this->at(mutation_selectors.index()) < mutation_selectors.size()); + return mutation_selectors.instantiate(this->at(mutation_selectors.index())); } size_t& pop_size() diff --git a/eo/src/eoFastGA.h b/eo/src/eoFastGA.h new file mode 100644 index 000000000..ac38f2532 --- /dev/null +++ b/eo/src/eoFastGA.h @@ -0,0 +1,150 @@ + +/* + 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; + version 2 of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _eoFastGA_H_ +#define _eoFastGA_H_ + +/** The Fast Genetic Algorithm. + * + * @ingroup Algorithms + */ +template +class eoFastGA : public eoAlgo +{ +protected: + double _rate_crossover; + eoSelectOne& _select_cross; + eoQuadOp& _crossover; + eoSelectOne& _select_aftercross; + + double _rate_mutation; + eoSelectOne& _select_mut; + eoMonOp& _mutation; + + eoPopEvalFunc& _pop_eval; + eoReplacement& _replace; + + eoContinue& _continuator; + + double _offsprings_size; + +public: + + eoFastGA( + double rate_crossover, + eoSelectOne& select_cross, + eoQuadOp& crossover, + eoSelectOne& select_aftercross, + double rate_mutation, + eoSelectOne& select_mut, + eoMonOp& mutation, + eoPopEvalFunc& pop_eval, + eoReplacement& replace, + eoContinue& continuator, + double offsprings_size = 0 + ) : + _rate_crossover(rate_crossover), + _select_cross(select_cross), + _crossover(crossover), + _select_aftercross(select_aftercross), + _rate_mutation(rate_mutation), + _select_mut(select_mut), + _mutation(mutation), + _pop_eval(pop_eval), + _replace(replace), + _continuator(continuator), + _offsprings_size(offsprings_size) + { + } + + void operator()(eoPop& pop) + { +#ifndef NDEBUG + assert(pop.size() > 0); + for(auto sol : pop) { + assert(not sol.invalid()); + } +#endif + // Set lambda to the pop size + // if it was not set up at construction. + if(_offsprings_size == 0) { + _offsprings_size = pop.size(); + } + + do { + eoPop offsprings; + + for(size_t i=0; i < _offsprings_size; ++i) { + + if(eo::rng.flip(_rate_crossover)) { + // Manual setup of eoSelectOne + // (usually they are setup in a + // wrapping eoSelect). + _select_cross.setup(pop); + + // Copy of const ref solutions, + // because one alter them hereafter. + EOT sol1 = _select_cross(pop); + EOT sol2 = _select_cross(pop); + + // If the operator returns true, + // olutions have been altered. + if(_crossover(sol1, sol2)) { + sol1.invalidate(); + sol2.invalidate(); + } + + // Select one of the two solutions + // which have been crossed. + eoPop crossed; + crossed.push_back(sol1); + crossed.push_back(sol2); + _select_aftercross.setup(crossed); + EOT sol3 = _select_aftercross(crossed); + + // Additional mutation (X)OR the crossed/cloned solution. + if(eo::rng.flip(_rate_mutation)) { + if(_mutation(sol3)) { + sol3.invalidate(); + } + } + offsprings.push_back(sol3); + + } else { // If not crossing, always mutate. + _select_mut.setup(pop); + EOT sol3 = _select_mut(pop); + _mutation(sol3); + offsprings.push_back(sol3); + } + } + assert(offsprings.size() == _offsprings_size); + + _pop_eval(pop, offsprings); + _replace(pop, offsprings); + + } while(_continuator(pop)); +#ifndef NDEBUG + assert(pop.size() > 0); + for(auto sol : pop) { + assert(not sol.invalid()); + } +#endif + } + +}; + +#endif // _eoFastGA_H_ diff --git a/eo/test/CMakeLists.txt b/eo/test/CMakeLists.txt index 07093d4fe..b6b9afee6 100644 --- a/eo/test/CMakeLists.txt +++ b/eo/test/CMakeLists.txt @@ -76,8 +76,10 @@ set (TEST_LIST t-algo-forged t-algo-forged-search t-FastGA + t-eoFastGA t-forge-FastGA t-eoFoundryFastGA + t-eoAlgoFoundryFastGA ) diff --git a/eo/test/t-FastGA.cpp b/eo/test/t-FastGA.cpp index 3dc08b370..548733673 100644 --- a/eo/test/t-FastGA.cpp +++ b/eo/test/t-FastGA.cpp @@ -1,3 +1,20 @@ + +/* + 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; + version 2 of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + #include #include diff --git a/eo/test/t-eoAlgoFoundryFastGA.cpp b/eo/test/t-eoAlgoFoundryFastGA.cpp new file mode 100644 index 000000000..9c5881eb2 --- /dev/null +++ b/eo/test/t-eoAlgoFoundryFastGA.cpp @@ -0,0 +1,147 @@ +#include +#include + +#include +#include +#include "../../problems/eval/oneMaxEval.h" + + +int main(int /*argc*/, char** /*argv*/) +{ + size_t dim = 500; + size_t pop_size = 10; + + eo::log << eo::setlevel(eo::warnings); + + using EOT = eoBit; + + oneMaxEval eval; + + eoBooleanGenerator gen(0.5); + eoInitFixedLength init(dim, gen); + + eoAlgoFoundryFastGA foundry(init, eval, pop_size*10); + + /***** Variation rates *****/ + for(double r = 0.0; r < 1.0; r+=0.1) { + foundry.crossover_rates.add(r); + foundry. mutation_rates.add(r); + } + + /***** Crossovers ****/ + foundry.crossovers.add< eo1PtBitXover >(); + foundry.crossovers.add< eoUBitXover >(0.5); // preference over 1 + for(size_t i=1; i < 11; i+=4) { + foundry.crossovers.add< eoNPtsBitXover >(i); // nb of points + } + + /***** Mutations ****/ + foundry.mutations.add< eoBitMutation >(0.01); // proba of flipping one bit + for(size_t i=1; i < 11; i+=4) { + foundry.mutations.add< eoDetBitFlip >(i); // mutate k bits + } + + /***** Selectors *****/ + for(eoOperatorFoundry>& ops : + {std::ref(foundry.crossover_selectors), + std::ref(foundry.aftercross_selectors), + std::ref(foundry.mutation_selectors) }) { + + ops.add< eoRandomSelect >(); + ops.add< eoStochTournamentSelect >(0.5); + ops.add< eoSequentialSelect >(); + ops.add< eoProportionalSelect >(); + for(size_t i=2; i < 10; i+=4) { + ops.add< eoDetTournamentSelect >(i); + } + } + + /***** Replacements ****/ + foundry.replacements.add< eoCommaReplacement >(); + foundry.replacements.add< eoPlusReplacement >(); + foundry.replacements.add< eoSSGAWorseReplacement >(); + foundry.replacements.add< eoSSGAStochTournamentReplacement >(0.51); + for(size_t i=2; i < 10; i+=4) { + foundry.replacements.add< eoSSGADetTournamentReplacement >(i); + } + + /***** Continuators ****/ + for(size_t i=10; i < 30; i+=10 ) { + foundry.continuators.add< eoSteadyFitContinue >(10,i); + } + + /***** Offspring population size *****/ + foundry.pop_sizes.add(0); // 0 = same as parent pop + // for(size_t s = pop_size; s < 2*pop_size; s+=pop_size/10) { + // foundry.pop_sizes.add(s); + // } + + + size_t n = + foundry.crossover_rates.size() + * foundry.crossover_selectors.size() + * foundry.crossovers.size() + * foundry.aftercross_selectors.size() + * foundry.mutation_rates.size() + * foundry.mutation_selectors.size() + * foundry.mutations.size() + * foundry.replacements.size() + * foundry.continuators.size() + * foundry.pop_sizes.size(); + std::clog << n << " possible algorithms instances." << std::endl; + + EOT best_sol; + std::string best_algo = ""; + + size_t i=0; + for(size_t i_crossrate = 0; i_crossrate < foundry.crossover_rates.size(); ++i_crossrate ) { + for(size_t i_crossselect = 0; i_crossselect < foundry.crossover_selectors.size(); ++i_crossselect ) { + for(size_t i_cross = 0; i_cross < foundry.crossovers.size(); ++i_cross ) { + for(size_t i_aftercrosel = 0; i_aftercrosel < foundry.aftercross_selectors.size(); ++i_aftercrosel ) { + for(size_t i_mutrate = 0; i_mutrate < foundry.mutation_rates.size(); ++i_mutrate ) { + for(size_t i_mutselect = 0; i_mutselect < foundry.mutation_selectors.size(); ++i_mutselect ) { + for(size_t i_mut = 0; i_mut < foundry.mutations.size(); ++i_mut ) { + for(size_t i_rep = 0; i_rep < foundry.replacements.size(); ++i_rep ) { + for(size_t i_cont = 0; i_cont < foundry.continuators.size(); ++i_cont ) { + for(size_t i_pop = 0; i_pop < foundry.pop_sizes.size(); ++i_pop ) { + std::clog << "\r" << i++ << "/" << n-1; std::clog.flush(); + + eoPop pop; + pop.append(pop_size, init); + + foundry.select({ + i_crossrate, + i_crossselect, + i_cross, + i_aftercrosel, + i_mutrate, + i_mutselect, + i_mut, + i_rep, + i_cont, + i_pop + }); + + // Actually perform a search + foundry(pop); + + if(best_sol.invalid()) { + best_sol = pop.best_element(); + best_algo = foundry.name(); + } else if(pop.best_element().fitness() > best_sol.fitness()) { + best_sol = pop.best_element(); + best_algo = foundry.name(); + } + } + } + } + } + } + } + } + } + } + } + std::cout << std::endl << "Best algo: " << best_algo << ", with " << best_sol << std::endl; + +} diff --git a/eo/test/t-eoFastGA.cpp b/eo/test/t-eoFastGA.cpp new file mode 100644 index 000000000..965a63b23 --- /dev/null +++ b/eo/test/t-eoFastGA.cpp @@ -0,0 +1,72 @@ + +/* + 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; + version 2 of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include + +#include +#include +#include "../../problems/eval/oneMaxEval.h" + +using EOT = eoBit; + +int main(int /*argc*/, char** /*argv*/) +{ + size_t dim = 100; + size_t pop_size = 10; + + oneMaxEval evalfunc; + eoPopLoopEval eval(evalfunc); + + eoBooleanGenerator gen(0.5); + eoInitFixedLength init(dim, gen); + + double cross_rate = 0.5; + eoSequentialSelect select_cross; + eoUBitXover crossover; + eoRandomSelect select_aftercross; + + double mut_rate = 0.5; + eoSequentialSelect select_mut; + eoStandardBitMutation mutation(0.5); + + eoPlusReplacement replacement; + + eoGenContinue common_cont(dim*2); + eoCombinedContinue gen_cont(common_cont); + + eoFastGA algo( + cross_rate, + select_cross, + crossover, + select_aftercross, + mut_rate, + select_mut, + mutation, + eval, + replacement, + common_cont + ); + + eoPop pop; + pop.append(pop_size, init); + eval(pop,pop); + + algo(pop); + + std::cout << pop.best_element() << std::endl; +} From 560dedbef0ef2f60603071e977956f27243547e3 Mon Sep 17 00:00:00 2001 From: Amine Aziz-Alaoui Date: Wed, 30 Sep 2020 15:06:48 +0200 Subject: [PATCH 13/42] feat update eval foundry for fastga --- eo/src/eoEvalFoundryFastGA.h | 100 ++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 42 deletions(-) diff --git a/eo/src/eoEvalFoundryFastGA.h b/eo/src/eoEvalFoundryFastGA.h index 4b2232eea..80ae27378 100644 --- a/eo/src/eoEvalFoundryFastGA.h +++ b/eo/src/eoEvalFoundryFastGA.h @@ -55,31 +55,37 @@ public: eoAlgoFoundryFastGA& foundry, eoInit& subpb_init, eoPopEvalFunc& subpb_eval, - const typename SUB::Fitness penalization + const typename SUB::Fitness penalization, + const bool normalized = false ) : _subpb_init(subpb_init), _subpb_eval(subpb_eval), _foundry(foundry), _penalization(penalization), - i_cont(foundry.continuators.index()), + _normalized(normalized), i_crat(foundry.crossover_rates.index()), + i_crsl(foundry.crossover_selectors.index()), i_cros(foundry.crossovers.index()), + i_afcr(foundry.aftercross_selectors.index()), i_mrat(foundry.mutation_rates.index()), + i_musl(foundry.mutation_selectors.index()), i_muta(foundry.mutations.index()), - i_sele(foundry.selectors.index()), - i_pops(foundry.pop_sizes.index()), - i_repl(foundry.replacements.index()) + i_repl(foundry.replacements.index()), + i_cont(foundry.continuators.index()), + i_pops(foundry.pop_sizes.index()) { } protected: - const size_t i_cont; const size_t i_crat; + const size_t i_crsl; const size_t i_cros; + const size_t i_afcr; const size_t i_mrat; + const size_t i_musl; const size_t i_muta; - const size_t i_sele; - const size_t i_pops; const size_t i_repl; + const size_t i_cont; + const size_t i_pops; public: @@ -96,27 +102,32 @@ public: */ std::vector decode( const EOT& sol ) const { - // Denormalize - // size_t cont = static_cast(std::ceil( sol[i_cont] * _foundry.continuators .size() )); - // size_t crat = static_cast(std::ceil( sol[i_crat] * _foundry.crossover_rates.size() )); - // size_t cros = static_cast(std::ceil( sol[i_cros] * _foundry.crossovers .size() )); - // size_t mrat = static_cast(std::ceil( sol[i_mrat] * _foundry.mutation_rates .size() )); - // size_t muta = static_cast(std::ceil( sol[i_muta] * _foundry.mutations .size() )); - // size_t sele = static_cast(std::ceil( sol[i_sele] * _foundry.selectors .size() )); - // size_t pops = static_cast(std::ceil( sol[i_pops] * _foundry.pop_sizes .size() )); - // size_t repl = static_cast(std::ceil( sol[i_repl] * _foundry.replacements .size() )); + if(_normalized) { + size_t crat = static_cast(std::ceil( sol[i_crat] * _foundry.crossover_rates.size() )), + size_t crsl = static_cast(std::ceil( sol[i_crsl] * _foundry.crossover_selectors.size() )), + size_t cros = static_cast(std::ceil( sol[i_cros] * _foundry.crossovers.size() )), + size_t afcr = static_cast(std::ceil( sol[i_afcr] * _foundry.aftercross_selectors.size() )), + size_t mrat = static_cast(std::ceil( sol[i_mrat] * _foundry.mutation_rates.size() )), + size_t musl = static_cast(std::ceil( sol[i_musl] * _foundry.mutation_selectors.size() )), + size_t muta = static_cast(std::ceil( sol[i_muta] * _foundry.mutations.size() )), + size_t repl = static_cast(std::ceil( sol[i_repl] * _foundry.replacements.size() )), + size_t cont = static_cast(std::ceil( sol[i_cont] * _foundry.continuators.size() )), + size_t pops = static_cast(std::ceil( sol[i_pops] * _foundry.pop_sizes.size() )) - // Direct encoding - size_t cont = static_cast(std::ceil( sol[i_cont] )); - size_t crat = static_cast(std::ceil( sol[i_crat] )); - size_t cros = static_cast(std::ceil( sol[i_cros] )); - size_t mrat = static_cast(std::ceil( sol[i_mrat] )); - size_t muta = static_cast(std::ceil( sol[i_muta] )); - size_t sele = static_cast(std::ceil( sol[i_sele] )); - size_t pops = static_cast(std::ceil( sol[i_pops] )); - size_t repl = static_cast(std::ceil( sol[i_repl] )); + } else { + size_t crat = static_cast(std::ceil( sol[i_crat] )); + size_t crsl = static_cast(std::ceil( sol[i_crsl] )); + size_t cros = static_cast(std::ceil( sol[i_cros] )); + size_t afcr = static_cast(std::ceil( sol[i_afcr] )); + size_t mrat = static_cast(std::ceil( sol[i_mrat] )); + size_t musl = static_cast(std::ceil( sol[i_musl] )); + size_t muta = static_cast(std::ceil( sol[i_muta] )); + size_t repl = static_cast(std::ceil( sol[i_repl] )); + size_t cont = static_cast(std::ceil( sol[i_cont] )); + size_t pops = static_cast(std::ceil( sol[i_pops] )); - return {cont, crat, cros, mrat, muta, sele, pops, repl}; + } + return {crat, crsl, cros, afcr, mrat, musl, muta, repl, cont, pops}; } /** Perform a sub-problem search with the configuration encoded in the given solution @@ -129,27 +140,30 @@ public: if(not sol.invalid()) { return; } - auto config = decode(sol); - double cont = config[i_cont]; double crat = config[i_crat]; + double crsl = config[i_crsl]; double cros = config[i_cros]; + double afcr = config[i_afcr]; double mrat = config[i_mrat]; + double musl = config[i_musl]; double muta = config[i_muta]; - double sele = config[i_sele]; - double pops = config[i_pops]; double repl = config[i_repl]; + double cont = config[i_cont]; + double pops = config[i_pops]; if( - 0 <= cont and cont < _foundry.continuators .size() - and 0 <= crat and crat < _foundry.crossover_rates.size() - and 0 <= cros and cros < _foundry.crossovers .size() - and 0 <= mrat and mrat < _foundry.mutation_rates .size() - and 0 <= muta and muta < _foundry.mutations .size() - and 0 <= sele and sele < _foundry.selectors .size() - and 0 <= pops and pops < _foundry.pop_sizes .size() - and 0 <= repl and repl < _foundry.replacements .size() - ) { + 0 <= crat and crat < _foundry.crossover_rates.size() + and 0 <= crsl and crsl < _foundry.crossover_selectors.size() + and 0 <= cros and cros < _foundry.crossovers.size() + and 0 <= afcr and afcr < _foundry.aftercross_selectors.size() + and 0 <= mrat and mrat < _foundry.mutation_rates.size() + and 0 <= musl and musl < _foundry.mutation_selectors.size() + and 0 <= muta and muta < _foundry.mutations.size() + and 0 <= repl and repl < _foundry.replacements.size() + and 0 <= cont and cont < _foundry.continuators.size() + and 0 <= pops and pops < _foundry.pop_sizes.size() + ) { _foundry.select(config); // FIXME should pop_size belong to this eval and moved out from the foundry? @@ -174,6 +188,7 @@ protected: eoPopEvalFunc& _subpb_eval; eoAlgoFoundryFastGA& _foundry; const typename EOT::Fitness _penalization; + const bool _normalized; }; /** Helper function to instanciate an eoEvalFoundryFastGA without having to indicate the template for the sub-problem encoding. @@ -187,9 +202,10 @@ eoEvalFoundryFastGA& eoInit& subpb_init, eoPopEvalFunc& subpb_eval, eoAlgoFoundryFastGA& foundry, - const typename SUB::Fitness penalization ) + const typename SUB::Fitness penalization, + const bool normalized = false ) { - return *(new eoEvalFoundryFastGA(subpb_init, subpb_eval, foundry, penalization)); + return *(new eoEvalFoundryFastGA(subpb_init, subpb_eval, foundry, penalization, normalized)); } #endif // _eoEvalFoundryFastGA_H_ From 8fa2270ffd633557bf29b2e5b9da35cdfd6d388d Mon Sep 17 00:00:00 2001 From: Amine Aziz-Alaoui Date: Thu, 1 Oct 2020 11:50:57 +0200 Subject: [PATCH 14/42] update the irace interface with the new FastGA foundry - fix: comment out useless rparamsin irace config --- eo/contrib/irace/fastga.cpp | 162 +++++++++++++++++++++-------------- eo/src/eoEvalFoundryFastGA.h | 52 ++++++----- problems/eval/eoEvalIOH.h | 2 +- 3 files changed, 130 insertions(+), 86 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index dc413466a..3cc7d7a0f 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -40,9 +40,12 @@ eoAlgoFoundryFastGA& make_foundry( foundry.mutation_rates.add(i); } - for(size_t i=5; i<100; i+=10) { - foundry.pop_sizes.add(i); - } + /***** Offsprings size *****/ + // for(size_t i=5; i<100; i+=10) { + // foundry.pop_sizes.add(i); + // } + + foundry.pop_sizes.add(0); // 0 = use parents fixed pop size. /***** Crossovers ****/ for(double i=0.1; i<0.9; i+=0.1) { @@ -66,16 +69,22 @@ eoAlgoFoundryFastGA& make_foundry( } /***** Selectors *****/ - foundry.selectors.add< eoRandomSelect >(); - foundry.selectors.add< eoSequentialSelect >(); - foundry.selectors.add< eoProportionalSelect >(); - for(size_t i=2; i < 10; i+=1) { // Tournament size. - foundry.selectors.add< eoDetTournamentSelect >(i); - } - for(double i=0.51; i<0.91; i+=0.1) { // Tournament size as perc of pop. - foundry.selectors.add< eoStochTournamentSelect >(i); + for(eoOperatorFoundry>& ops : + {std::ref(foundry.crossover_selectors), + std::ref(foundry.mutation_selectors) }) { + + ops.add< eoRandomSelect >(); + ops.add< eoStochTournamentSelect >(0.5); + ops.add< eoSequentialSelect >(); + ops.add< eoProportionalSelect >(); + for(size_t i=2; i < 10; i+=4) { + ops.add< eoDetTournamentSelect >(i); + } } + foundry.aftercross_selectors.add< eoRandomSelect >(); + + /***** Replacements ****/ foundry.replacements.add< eoPlusReplacement >(); foundry.replacements.add< eoCommaReplacement >(); @@ -94,11 +103,21 @@ Bits::Fitness fake_func(const Bits&) { return 0; } void print_param_range(const eoParam& param, const size_t slot_size, std::ostream& out = std::cout) { + // If there is no choice to be made on this operator, comment it out. + if(slot_size - 1 <= 0) { + out << "# "; + } + out << param.longName() << "\t\"--" << param.longName() << "=\"" - << "\ti" - << "\t(0," << slot_size << ")" - << std::endl; + << "\ti"; + + if(slot_size -1 <= 0) { + out << "\t(0)"; + } else { + out << "\t(0," << slot_size-1 << ")"; + } + out << std::endl; } int main(int argc, char* argv[]) @@ -138,45 +157,55 @@ int main(int argc, char* argv[]) const size_t instance = instance_p.value(); auto continuator_p = parser.getORcreateParam(0, - "continuator", "", - 'o', "Evolution Engine", /*required=*/true); + "continuator", "Stopping criterion", + 'o', "Operator Choice", /*required=*/true); const size_t continuator = continuator_p.value(); auto crossover_rate_p = parser.getORcreateParam(0, "crossover-rate", "", - 'C', "Evolution Engine", /*required=*/true); + '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); + const size_t crossover_selector = crossover_selector_p.value(); + auto crossover_p = parser.getORcreateParam(0, "crossover", "", - 'c', "Evolution Engine", /*required=*/true); + 'c', "Operator Choice", /*required=*/true); const size_t crossover = crossover_p.value(); + auto aftercross_selector_p = parser.getORcreateParam(0, + "aftercross-selector", "How to selects between the two individuals altered by cross-over which one will mutate", + 'a', "Operator Choice", /*required=*/true); + const size_t aftercross_selector = aftercross_selector_p.value(); + auto mutation_rate_p = parser.getORcreateParam(0, "mutation-rate", "", - 'M', "Evolution Engine", /*required=*/true); + '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); + const size_t mutation_selector = mutation_selector_p.value(); + auto mutation_p = parser.getORcreateParam(0, "mutation", "", - 'm', "Evolution Engine", /*required=*/true); + 'm', "Operator Choice", /*required=*/true); const size_t mutation = mutation_p.value(); - auto selector_p = parser.getORcreateParam(0, - "selector", "", - 's', "Evolution Engine", /*required=*/true); - const size_t selector = selector_p.value(); - - auto pop_size_p = parser.getORcreateParam(0, - "pop-size", "", - 'P', "Evolution Engine", /*required=*/true); - const size_t pop_size = pop_size_p.value(); - auto replacement_p = parser.getORcreateParam(0, "replacement", "", - 'r', "Evolution Engine", /*required=*/true); + 'r', "Operator Choice", /*required=*/true); const size_t replacement = replacement_p.value(); + auto pop_size_p = parser.getORcreateParam(0, + "pop-size", "Offsprings pop size (0 = same size than the parents pop)", + 'P', "Operator Choice", /*required=*/true); + const size_t pop_size = pop_size_p.value(); + // Help + Verbose routines make_verbose(parser); make_help(parser, /*exit_after*/false, std::clog); @@ -190,25 +219,34 @@ int main(int argc, char* argv[]) eoInitFixedLength fake_init(/*bitstring size=*/1, fake_gen); auto fake_foundry = make_foundry(store, fake_init, fake_eval, max_evals, /*generations=*/ 1); - size_t n = fake_foundry.continuators.size() - * fake_foundry.crossovers.size() - * fake_foundry.mutations.size() - * fake_foundry.selectors.size() - * fake_foundry.replacements.size(); + size_t n = + fake_foundry.crossover_rates.size() + * fake_foundry.crossover_selectors.size() + * fake_foundry.crossovers.size() + * fake_foundry.aftercross_selectors.size() + * fake_foundry.mutation_rates.size() + * fake_foundry.mutation_selectors.size() + * fake_foundry.mutations.size() + * fake_foundry.replacements.size() + * fake_foundry.continuators.size() + * fake_foundry.pop_sizes.size(); + std::clog << std::endl; std::clog << n << " possible algorithms instances." << std::endl; - std::clog << "Ranges of required parameters (redirect the stdout in a file to use it with iRace): " << std::endl; + std::clog << "Ranges of configurable parameters (redirect the stdout in a file to use it with iRace): " << std::endl; std::cout << "# name\tswitch\ttype\trange" << std::endl; - print_param_range( instance_p, 18, std::cout); - print_param_range( continuator_p, fake_foundry.continuators .size(), std::cout); - print_param_range( crossover_p, fake_foundry.crossovers .size(), std::cout); - print_param_range(crossover_rate_p, fake_foundry.crossover_rates.size(), std::cout); - print_param_range( mutation_p, fake_foundry.mutations .size(), std::cout); - print_param_range( mutation_rate_p, fake_foundry.mutation_rates .size(), std::cout); - print_param_range( selector_p, fake_foundry.selectors .size(), std::cout); - print_param_range( pop_size_p, fake_foundry.pop_sizes .size(), std::cout); - print_param_range( replacement_p, fake_foundry.replacements .size(), std::cout); + print_param_range( instance_p, 18, std::cout); + print_param_range( continuator_p, fake_foundry.continuators .size(), std::cout); + print_param_range( crossover_rate_p, fake_foundry.crossover_rates .size(), std::cout); + print_param_range( crossover_selector_p, fake_foundry.crossover_selectors .size(), std::cout); + print_param_range(aftercross_selector_p, fake_foundry.aftercross_selectors.size(), std::cout); + print_param_range( crossover_p, fake_foundry.crossovers .size(), std::cout); + print_param_range( mutation_rate_p, fake_foundry.mutation_rates .size(), std::cout); + print_param_range( mutation_selector_p, fake_foundry.mutation_selectors .size(), std::cout); + print_param_range( mutation_p, fake_foundry.mutations .size(), std::cout); + print_param_range( replacement_p, fake_foundry.replacements .size(), std::cout); + print_param_range( pop_size_p, fake_foundry.pop_sizes .size(), std::cout); // std::ofstream irace_param("fastga.params"); // irace_param << "# name\tswitch\ttype\tvalues" << std::endl; @@ -219,16 +257,6 @@ int main(int argc, char* argv[]) const size_t generations = static_cast(std::floor( static_cast(max_evals) / static_cast(pop_size))); - Ints encoded_algo(8); - encoded_algo[0] = continuator; - encoded_algo[1] = crossover_rate; - encoded_algo[2] = crossover; - encoded_algo[3] = mutation_rate; - encoded_algo[4] = mutation; - encoded_algo[5] = selector; - encoded_algo[6] = pop_size; - encoded_algo[7] = replacement; - /***** IOH logger *****/ IOHprofiler_RangeLinear target_range(0, dimension, buckets); IOHprofiler_RangeLinear budget_range(0, max_evals, buckets); @@ -278,16 +306,22 @@ int main(int argc, char* argv[]) eoInitFixedLength onemax_init(/*bitstring size=*/dimension, ugen); auto& foundry = make_foundry(store, onemax_init, onemax_eval, max_evals, generations); + Ints encoded_algo(foundry.size()); + + encoded_algo[foundry.crossover_rates .index()] = crossover_rate; + encoded_algo[foundry.crossover_selectors .index()] = crossover_selector; + encoded_algo[foundry.crossovers .index()] = crossover; + encoded_algo[foundry.aftercross_selectors.index()] = aftercross_selector; + encoded_algo[foundry.mutation_rates .index()] = mutation_rate; + encoded_algo[foundry.mutation_selectors .index()] = mutation_selector; + encoded_algo[foundry.mutations .index()] = mutation; + encoded_algo[foundry.replacements .index()] = replacement; + encoded_algo[foundry.continuators .index()] = continuator; + encoded_algo[foundry.pop_sizes .index()] = pop_size; + std::clog << "Encoded algorithm:" << std::endl; foundry.select(encoded_algo); - std::clog << "\tcontinuator:\t" << foundry.continuator ().className() << std::endl; - std::clog << "\tcrossover:\t" << foundry.crossover ().className() << std::endl; - std::clog << "\tcrossover_rate:\t" << foundry.crossover_rate() << std::endl; - std::clog << "\tmutation:\t" << foundry.mutation ().className() << std::endl; - std::clog << "\tmutation_rate:\t" << foundry.mutation_rate () << std::endl; - std::clog << "\tselector:\t" << foundry.selector ().className() << std::endl; - std::clog << "\tpop_size:\t" << foundry.pop_size () << std::endl; - std::clog << "\treplacement:\t" << foundry.replacement ().className() << std::endl; + std::clog << foundry.name() << std::endl; // Evaluation of a forged encoded_algo on the sub-problem eoEvalFoundryFastGA eval_foundry( diff --git a/eo/src/eoEvalFoundryFastGA.h b/eo/src/eoEvalFoundryFastGA.h index 80ae27378..88d6d34a7 100644 --- a/eo/src/eoEvalFoundryFastGA.h +++ b/eo/src/eoEvalFoundryFastGA.h @@ -102,30 +102,40 @@ public: */ std::vector decode( const EOT& sol ) const { + size_t crat; + size_t crsl; + size_t cros; + size_t afcr; + size_t mrat; + size_t musl; + size_t muta; + size_t repl; + size_t cont; + size_t pops; + if(_normalized) { - size_t crat = static_cast(std::ceil( sol[i_crat] * _foundry.crossover_rates.size() )), - size_t crsl = static_cast(std::ceil( sol[i_crsl] * _foundry.crossover_selectors.size() )), - size_t cros = static_cast(std::ceil( sol[i_cros] * _foundry.crossovers.size() )), - size_t afcr = static_cast(std::ceil( sol[i_afcr] * _foundry.aftercross_selectors.size() )), - size_t mrat = static_cast(std::ceil( sol[i_mrat] * _foundry.mutation_rates.size() )), - size_t musl = static_cast(std::ceil( sol[i_musl] * _foundry.mutation_selectors.size() )), - size_t muta = static_cast(std::ceil( sol[i_muta] * _foundry.mutations.size() )), - size_t repl = static_cast(std::ceil( sol[i_repl] * _foundry.replacements.size() )), - size_t cont = static_cast(std::ceil( sol[i_cont] * _foundry.continuators.size() )), - size_t pops = static_cast(std::ceil( sol[i_pops] * _foundry.pop_sizes.size() )) + crat = static_cast(std::ceil( sol[i_crat] * _foundry.crossover_rates.size() )); + crsl = static_cast(std::ceil( sol[i_crsl] * _foundry.crossover_selectors.size() )); + cros = static_cast(std::ceil( sol[i_cros] * _foundry.crossovers.size() )); + afcr = static_cast(std::ceil( sol[i_afcr] * _foundry.aftercross_selectors.size() )); + mrat = static_cast(std::ceil( sol[i_mrat] * _foundry.mutation_rates.size() )); + musl = static_cast(std::ceil( sol[i_musl] * _foundry.mutation_selectors.size() )); + muta = static_cast(std::ceil( sol[i_muta] * _foundry.mutations.size() )); + repl = static_cast(std::ceil( sol[i_repl] * _foundry.replacements.size() )); + cont = static_cast(std::ceil( sol[i_cont] * _foundry.continuators.size() )); + pops = static_cast(std::ceil( sol[i_pops] * _foundry.pop_sizes.size() )); } else { - size_t crat = static_cast(std::ceil( sol[i_crat] )); - size_t crsl = static_cast(std::ceil( sol[i_crsl] )); - size_t cros = static_cast(std::ceil( sol[i_cros] )); - size_t afcr = static_cast(std::ceil( sol[i_afcr] )); - size_t mrat = static_cast(std::ceil( sol[i_mrat] )); - size_t musl = static_cast(std::ceil( sol[i_musl] )); - size_t muta = static_cast(std::ceil( sol[i_muta] )); - size_t repl = static_cast(std::ceil( sol[i_repl] )); - size_t cont = static_cast(std::ceil( sol[i_cont] )); - size_t pops = static_cast(std::ceil( sol[i_pops] )); - + crat = static_cast(std::ceil( sol[i_crat] )); + crsl = static_cast(std::ceil( sol[i_crsl] )); + cros = static_cast(std::ceil( sol[i_cros] )); + afcr = static_cast(std::ceil( sol[i_afcr] )); + mrat = static_cast(std::ceil( sol[i_mrat] )); + musl = static_cast(std::ceil( sol[i_musl] )); + muta = static_cast(std::ceil( sol[i_muta] )); + repl = static_cast(std::ceil( sol[i_repl] )); + cont = static_cast(std::ceil( sol[i_cont] )); + pops = static_cast(std::ceil( sol[i_pops] )); } return {crat, crsl, cros, afcr, mrat, musl, muta, repl, cont, pops}; } diff --git a/problems/eval/eoEvalIOH.h b/problems/eval/eoEvalIOH.h index 7a5c1b5a6..9da86bdfc 100644 --- a/problems/eval/eoEvalIOH.h +++ b/problems/eval/eoEvalIOH.h @@ -200,7 +200,7 @@ class eoEvalIOHsuiteSingleDim : public eoEvalFunc // Evaluate the performance of the encoded algo instance // on a whole IOH suite benchmark. typename IOHprofiler_suite::Problem_ptr pb; - while(pb = _ioh_suite->get_next_problem()) { + while( (pb = _ioh_suite->get_next_problem()) ) { // Consider a new problem. _eval.problem(*pb); // Will call logger's target_problem. From f24efdd770b3ba89df4eb8e00bb3391a40055107 Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Fri, 2 Oct 2020 16:01:02 +0200 Subject: [PATCH 15/42] fix offspring_size versus pop_size mistake --- eo/contrib/irace/fastga.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index 3cc7d7a0f..c50f650f1 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -151,6 +151,11 @@ int main(int argc, char* argv[]) // rng is a global rng.reseed(seed); + auto pop_size_p = parser.getORcreateParam(0, + "pop-size", "Population size", + 'P', "Operator Choice", /*required=*/false); + const size_t pop_size = pop_size_p.value(); + auto instance_p = parser.getORcreateParam(1, "instance", "Instance ID", 'i', "Problem", /*required=*/true); @@ -201,10 +206,11 @@ int main(int argc, char* argv[]) 'r', "Operator Choice", /*required=*/true); const size_t replacement = replacement_p.value(); - auto pop_size_p = parser.getORcreateParam(0, - "pop-size", "Offsprings pop size (0 = same size than the parents pop)", + auto offspring_size_p = parser.getORcreateParam(0, + "offspring-size", "Offspringssize (0 = same size than the parents pop, see --pop-size)", 'P', "Operator Choice", /*required=*/true); - const size_t pop_size = pop_size_p.value(); + const size_t offspring_size = offspring_size_p.value(); + // Help + Verbose routines make_verbose(parser); @@ -246,7 +252,7 @@ int main(int argc, char* argv[]) print_param_range( mutation_selector_p, fake_foundry.mutation_selectors .size(), std::cout); print_param_range( mutation_p, fake_foundry.mutations .size(), std::cout); print_param_range( replacement_p, fake_foundry.replacements .size(), std::cout); - print_param_range( pop_size_p, fake_foundry.pop_sizes .size(), std::cout); + print_param_range( offspring_size_p, fake_foundry.pop_sizes .size(), std::cout); // std::ofstream irace_param("fastga.params"); // irace_param << "# name\tswitch\ttype\tvalues" << std::endl; @@ -317,7 +323,7 @@ int main(int argc, char* argv[]) encoded_algo[foundry.mutations .index()] = mutation; encoded_algo[foundry.replacements .index()] = replacement; encoded_algo[foundry.continuators .index()] = continuator; - encoded_algo[foundry.pop_sizes .index()] = pop_size; + encoded_algo[foundry.pop_sizes .index()] = offspring_size; std::clog << "Encoded algorithm:" << std::endl; foundry.select(encoded_algo); From fd77cccd85c5e5dfe497e0c50bc4569aef1ab98f Mon Sep 17 00:00:00 2001 From: aaziz-alaoui Date: Fri, 2 Oct 2020 16:15:12 +0200 Subject: [PATCH 16/42] adding problem congifuration interface create problem_config_mapping instance --- eo/contrib/irace/fastga.cpp | 47 ++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index 3cc7d7a0f..d163ab267 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -1,7 +1,6 @@ #include #include #include - #include #include #include @@ -257,8 +256,43 @@ int main(int argc, char* argv[]) const size_t generations = static_cast(std::floor( static_cast(max_evals) / static_cast(pop_size))); + + + // Problem configuration code. + struct Problem { + double dummy; + size_t epistasis; + size_t neutrality; + size_t ruggedness; + size_t max_target; + }; + + std::map problem_config_mapping { + {0, {0, 0, 1, 0, 1000}}, + {1, {0, 0, 3, 0, 333}}, + {2, {0, 0, 5, 0, 200}}, + {3, {0, 2, 1, 0, 1000}}, + {4, {0, 2, 3, 0, 333}}, + {5, {0, 2, 3, 0, 200}}, + {6, {0, 4, 1, 0, 1000}}, + {7, {0, 4, 3, 0, 333}}, + {8, {0, 4, 5, 0, 200}}, + {9, {0.5, 0, 1, 0, 500}}, + {10, {0.5, 0, 3, 0, 166}}, + {11, {0.5, 0, 5, 0, 100}}, + {12, {0.5, 2, 1, 0, 500}}, + {13, {0.5, 2, 3, 0, 166}}, + {14, {0.5, 2, 5, 0, 100}}, + {15, {0.5, 4, 1, 0, 500}}, + {16, {0.5, 4, 3, 0, 166}}, + {17, {0.5, 4, 5, 0, 100}}, + }; + + + /***** IOH logger *****/ - IOHprofiler_RangeLinear target_range(0, dimension, buckets); + auto max_target_para = problem_config_mapping[instance - 1].max_target; + IOHprofiler_RangeLinear target_range(0, max_target_para, buckets); IOHprofiler_RangeLinear budget_range(0, max_evals, buckets); IOHprofiler_ecdf_logger logger(target_range, budget_range); @@ -267,10 +301,10 @@ int main(int argc, char* argv[]) logger.activate_logger(); /***** IOH problem *****/ - double w_model_suite_dummy_para = 0; - int w_model_suite_epitasis_para = 0; - int w_model_suite_neutrality_para = 0; - int w_model_suite_ruggedness_para = 0; + double w_model_suite_dummy_para = problem_config_mapping[instance - 1].dummy; + int w_model_suite_epitasis_para = problem_config_mapping[instance - 1].epistasis; + int w_model_suite_neutrality_para = problem_config_mapping[instance - 1].neutrality; + int w_model_suite_ruggedness_para = problem_config_mapping[instance - 1].ruggedness; W_Model_OneMax w_model_om; std::string problem_name = "OneMax"; @@ -280,6 +314,7 @@ int main(int argc, char* argv[]) + "_N" + std::to_string(w_model_suite_neutrality_para) + "_R" + std::to_string(w_model_suite_ruggedness_para); + /// This must be called to configure the w-model to be tested. w_model_om.set_w_setting(w_model_suite_dummy_para,w_model_suite_epitasis_para, w_model_suite_neutrality_para,w_model_suite_ruggedness_para); From 7f2e5918917e03a809bde16efa726eb8094058b7 Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Fri, 2 Oct 2020 16:19:49 +0200 Subject: [PATCH 17/42] fix default pop size --- eo/contrib/irace/fastga.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index c50f650f1..78475e742 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -151,7 +151,7 @@ int main(int argc, char* argv[]) // rng is a global rng.reseed(seed); - auto pop_size_p = parser.getORcreateParam(0, + auto pop_size_p = parser.getORcreateParam(1, "pop-size", "Population size", 'P', "Operator Choice", /*required=*/false); const size_t pop_size = pop_size_p.value(); @@ -207,7 +207,7 @@ int main(int argc, char* argv[]) const size_t replacement = replacement_p.value(); auto offspring_size_p = parser.getORcreateParam(0, - "offspring-size", "Offspringssize (0 = same size than the parents pop, see --pop-size)", + "offspring-size", "Offsprings size (0 = same size than the parents pop, see --pop-size)", 'P', "Operator Choice", /*required=*/true); const size_t offspring_size = offspring_size_p.value(); From 75f1d9524fa6b668e9276cecd3e5885371c9d2ac Mon Sep 17 00:00:00 2001 From: Amine Aziz-Alaoui Date: Fri, 2 Oct 2020 17:38:44 +0200 Subject: [PATCH 18/42] fix offspring/pop misconception in FastGA foundry --- eo/contrib/irace/fastga.cpp | 79 +++++++++++++++++++----------------- eo/src/eoAlgoFoundryFastGA.h | 16 ++++---- eo/src/eoEvalFoundryFastGA.h | 24 ++++++----- 3 files changed, 62 insertions(+), 57 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index f79b6b7d1..b20e5aa9c 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -41,10 +41,10 @@ eoAlgoFoundryFastGA& make_foundry( /***** Offsprings size *****/ // for(size_t i=5; i<100; i+=10) { - // foundry.pop_sizes.add(i); + // foundry.offspring_sizes.add(i); // } - foundry.pop_sizes.add(0); // 0 = use parents fixed pop size. + foundry.offspring_sizes.add(0); // 0 = use parents fixed pop size. /***** Crossovers ****/ for(double i=0.1; i<0.9; i+=0.1) { @@ -155,14 +155,14 @@ int main(int argc, char* argv[]) 'P', "Operator Choice", /*required=*/false); const size_t pop_size = pop_size_p.value(); - auto instance_p = parser.getORcreateParam(1, + auto instance_p = parser.getORcreateParam(0, "instance", "Instance ID", 'i', "Problem", /*required=*/true); const size_t instance = instance_p.value(); auto continuator_p = parser.getORcreateParam(0, "continuator", "Stopping criterion", - 'o', "Operator Choice", /*required=*/true); + 'o', "Operator Choice", /*required=*/false); // Single alternative, not required. const size_t continuator = continuator_p.value(); auto crossover_rate_p = parser.getORcreateParam(0, @@ -182,7 +182,7 @@ int main(int argc, char* argv[]) auto aftercross_selector_p = parser.getORcreateParam(0, "aftercross-selector", "How to selects between the two individuals altered by cross-over which one will mutate", - 'a', "Operator Choice", /*required=*/true); + '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, @@ -207,7 +207,7 @@ int main(int argc, char* argv[]) auto offspring_size_p = parser.getORcreateParam(0, "offspring-size", "Offsprings size (0 = same size than the parents pop, see --pop-size)", - 'P', "Operator Choice", /*required=*/true); + 'P', "Operator Choice", /*required=*/false); // Single alternative, not required. const size_t offspring_size = offspring_size_p.value(); @@ -234,7 +234,7 @@ int main(int argc, char* argv[]) * fake_foundry.mutations.size() * fake_foundry.replacements.size() * fake_foundry.continuators.size() - * fake_foundry.pop_sizes.size(); + * fake_foundry.offspring_sizes.size(); std::clog << std::endl; std::clog << n << " possible algorithms instances." << std::endl; @@ -251,7 +251,7 @@ int main(int argc, char* argv[]) print_param_range( mutation_selector_p, fake_foundry.mutation_selectors .size(), std::cout); print_param_range( mutation_p, fake_foundry.mutations .size(), std::cout); print_param_range( replacement_p, fake_foundry.replacements .size(), std::cout); - print_param_range( offspring_size_p, fake_foundry.pop_sizes .size(), std::cout); + print_param_range( offspring_size_p, fake_foundry.offspring_sizes .size(), std::cout); // std::ofstream irace_param("fastga.params"); // irace_param << "# name\tswitch\ttype\tvalues" << std::endl; @@ -274,30 +274,30 @@ int main(int argc, char* argv[]) }; std::map problem_config_mapping { - {0, {0, 0, 1, 0, 1000}}, - {1, {0, 0, 3, 0, 333}}, - {2, {0, 0, 5, 0, 200}}, - {3, {0, 2, 1, 0, 1000}}, - {4, {0, 2, 3, 0, 333}}, - {5, {0, 2, 3, 0, 200}}, - {6, {0, 4, 1, 0, 1000}}, - {7, {0, 4, 3, 0, 333}}, - {8, {0, 4, 5, 0, 200}}, - {9, {0.5, 0, 1, 0, 500}}, - {10, {0.5, 0, 3, 0, 166}}, - {11, {0.5, 0, 5, 0, 100}}, - {12, {0.5, 2, 1, 0, 500}}, - {13, {0.5, 2, 3, 0, 166}}, - {14, {0.5, 2, 5, 0, 100}}, - {15, {0.5, 4, 1, 0, 500}}, - {16, {0.5, 4, 3, 0, 166}}, - {17, {0.5, 4, 5, 0, 100}}, + { 0, {0, 0, 1, 0, 1000}}, + { 1, {0, 0, 3, 0, 333}}, + { 2, {0, 0, 5, 0, 200}}, + { 3, {0, 2, 1, 0, 1000}}, + { 4, {0, 2, 3, 0, 333}}, + { 5, {0, 2, 3, 0, 200}}, + { 6, {0, 4, 1, 0, 1000}}, + { 7, {0, 4, 3, 0, 333}}, + { 8, {0, 4, 5, 0, 200}}, + { 9, {0.5, 0, 1, 0, 500}}, + {10, {0.5, 0, 3, 0, 166}}, + {11, {0.5, 0, 5, 0, 100}}, + {12, {0.5, 2, 1, 0, 500}}, + {13, {0.5, 2, 3, 0, 166}}, + {14, {0.5, 2, 5, 0, 100}}, + {15, {0.5, 4, 1, 0, 500}}, + {16, {0.5, 4, 3, 0, 166}}, + {17, {0.5, 4, 5, 0, 100}}, }; /***** IOH logger *****/ - auto max_target_para = problem_config_mapping[instance - 1].max_target; + auto max_target_para = problem_config_mapping[instance].max_target; IOHprofiler_RangeLinear target_range(0, max_target_para, buckets); IOHprofiler_RangeLinear budget_range(0, max_evals, buckets); IOHprofiler_ecdf_logger logger(target_range, budget_range); @@ -307,10 +307,10 @@ int main(int argc, char* argv[]) logger.activate_logger(); /***** IOH problem *****/ - double w_model_suite_dummy_para = problem_config_mapping[instance - 1].dummy; - int w_model_suite_epitasis_para = problem_config_mapping[instance - 1].epistasis; - int w_model_suite_neutrality_para = problem_config_mapping[instance - 1].neutrality; - int w_model_suite_ruggedness_para = problem_config_mapping[instance - 1].ruggedness; + double w_model_suite_dummy_para = problem_config_mapping[instance].dummy; + int w_model_suite_epitasis_para = problem_config_mapping[instance].epistasis; + int w_model_suite_neutrality_para = problem_config_mapping[instance].neutrality; + int w_model_suite_ruggedness_para = problem_config_mapping[instance].ruggedness; W_Model_OneMax w_model_om; std::string problem_name = "OneMax"; @@ -329,8 +329,8 @@ int main(int argc, char* argv[]) w_model_om.IOHprofiler_set_problem_name(problem_name); /// Set problem_id as 1 - w_model_om.IOHprofiler_set_problem_id(1); - w_model_om.IOHprofiler_set_instance_id(instance); + w_model_om.IOHprofiler_set_problem_id(0); // FIXME check what that means + w_model_om.IOHprofiler_set_instance_id(instance); // FIXME check what that means /// Set dimension. w_model_om.IOHprofiler_set_number_of_variables(dimension); @@ -338,14 +338,14 @@ int main(int argc, char* argv[]) /***** Bindings *****/ logger.track_problem(w_model_om); - eoEvalIOHproblem onemax_eval(w_model_om, logger); - eoPopLoopEval pop_onemax(onemax_eval); + eoEvalIOHproblem onemax_pb(w_model_om, logger); + eoPopLoopEval onemax_eval(onemax_pb); /***** Instanciate and run the algo *****/ eoUniformGenerator ugen(0, 1); eoInitFixedLength onemax_init(/*bitstring size=*/dimension, ugen); - auto& foundry = make_foundry(store, onemax_init, onemax_eval, max_evals, generations); + auto& foundry = make_foundry(store, onemax_init, onemax_pb, max_evals, generations); Ints encoded_algo(foundry.size()); @@ -358,7 +358,7 @@ int main(int argc, char* argv[]) encoded_algo[foundry.mutations .index()] = mutation; encoded_algo[foundry.replacements .index()] = replacement; encoded_algo[foundry.continuators .index()] = continuator; - encoded_algo[foundry.pop_sizes .index()] = offspring_size; + encoded_algo[foundry.offspring_sizes .index()] = offspring_size; std::clog << "Encoded algorithm:" << std::endl; foundry.select(encoded_algo); @@ -366,7 +366,10 @@ int main(int argc, char* argv[]) // Evaluation of a forged encoded_algo on the sub-problem eoEvalFoundryFastGA eval_foundry( - foundry, onemax_init, pop_onemax, /*penalization=*/ 0); + foundry, pop_size, + onemax_init, onemax_eval, + /*penalization=*/ dimension, // Worst case penalization. + /*normalized=*/ false); // Use direct integer encoding. // Actually instanciate and run the algorithm. eval_foundry(encoded_algo); diff --git a/eo/src/eoAlgoFoundryFastGA.h b/eo/src/eoAlgoFoundryFastGA.h index 099507103..3766b8a44 100644 --- a/eo/src/eoAlgoFoundryFastGA.h +++ b/eo/src/eoAlgoFoundryFastGA.h @@ -101,7 +101,7 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry replacements(7, false), continuators(8, true), // Always re-instantiate continuators, because they hold a state. - pop_sizes(9, false), + offspring_sizes(9, false), _eval(eval), _init(init), _max_evals(max_evals), @@ -122,7 +122,7 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry eoOperatorFoundry< eoReplacement > replacements; eoOperatorFoundry< eoContinue > continuators; - eoOperatorFoundry< size_t > pop_sizes; + eoOperatorFoundry< size_t > offspring_sizes; /* @} */ /** instantiate and call the pre-selected algorithm. @@ -138,7 +138,7 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry 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( pop_sizes.size() > 0); assert(this->at( pop_sizes.index()) < pop_sizes.size()); + assert( offspring_sizes.size() > 0); assert(this->at( offspring_sizes.index()) < offspring_sizes.size()); // Objective function calls counter eoEvalCounterThrowException eval(_eval, _max_evals); @@ -156,7 +156,7 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry pop_eval, this->replacement(), this->continuator(), - this->pop_size() + this->offspring_size() ); // Restart wrapper @@ -188,7 +188,7 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry name << this->at( mutations.index()) << " (" << this-> mutation().className() << ") + "; name << this->at( replacements.index()) << " (" << this-> replacement().className() << ") + "; name << this->at( continuators.index()) << " (" << this-> continuator().className() << ") + "; - name << this->at( pop_sizes.index()) << " (" << this-> pop_size() << ")"; + name << this->at( offspring_sizes.index()) << " (" << this-> offspring_size() << ")"; return name.str(); } @@ -247,10 +247,10 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry return mutation_selectors.instantiate(this->at(mutation_selectors.index())); } - size_t& pop_size() + size_t& offspring_size() { - assert(this->at(pop_sizes.index()) < pop_sizes.size()); - return pop_sizes.instantiate(this->at(pop_sizes.index())); + assert(this->at(offspring_sizes.index()) < offspring_sizes.size()); + return offspring_sizes.instantiate(this->at(offspring_sizes.index())); } eoReplacement& replacement() diff --git a/eo/src/eoEvalFoundryFastGA.h b/eo/src/eoEvalFoundryFastGA.h index 88d6d34a7..b85561d1a 100644 --- a/eo/src/eoEvalFoundryFastGA.h +++ b/eo/src/eoEvalFoundryFastGA.h @@ -47,17 +47,19 @@ public: * * @param foundry The set of algorithms among which to select. * @param subpb_init An initilizer for sub-problem encoding. - * @param pop_size Population size for the sub-problem solver. + * @param offspring_size Population size for the sub-problem solver. * @param subpb_eval The sub-problem itself. * @param penalization If any solution to the high-level algorithm selection problem is out of bounds, set it to this value. */ eoEvalFoundryFastGA( eoAlgoFoundryFastGA& foundry, + const size_t pop_size, eoInit& subpb_init, eoPopEvalFunc& subpb_eval, const typename SUB::Fitness penalization, const bool normalized = false ) : + _pop_size(pop_size), _subpb_init(subpb_init), _subpb_eval(subpb_eval), _foundry(foundry), @@ -72,7 +74,7 @@ public: i_muta(foundry.mutations.index()), i_repl(foundry.replacements.index()), i_cont(foundry.continuators.index()), - i_pops(foundry.pop_sizes.index()) + i_offs(foundry.offspring_sizes.index()) { } protected: @@ -85,7 +87,7 @@ protected: const size_t i_muta; const size_t i_repl; const size_t i_cont; - const size_t i_pops; + const size_t i_offs; public: @@ -111,7 +113,7 @@ public: size_t muta; size_t repl; size_t cont; - size_t pops; + size_t offs; if(_normalized) { crat = static_cast(std::ceil( sol[i_crat] * _foundry.crossover_rates.size() )); @@ -123,7 +125,7 @@ public: muta = static_cast(std::ceil( sol[i_muta] * _foundry.mutations.size() )); repl = static_cast(std::ceil( sol[i_repl] * _foundry.replacements.size() )); cont = static_cast(std::ceil( sol[i_cont] * _foundry.continuators.size() )); - pops = static_cast(std::ceil( sol[i_pops] * _foundry.pop_sizes.size() )); + offs = static_cast(std::ceil( sol[i_offs] * _foundry.offspring_sizes.size() )); } else { crat = static_cast(std::ceil( sol[i_crat] )); @@ -135,9 +137,9 @@ public: muta = static_cast(std::ceil( sol[i_muta] )); repl = static_cast(std::ceil( sol[i_repl] )); cont = static_cast(std::ceil( sol[i_cont] )); - pops = static_cast(std::ceil( sol[i_pops] )); + offs = static_cast(std::ceil( sol[i_offs] )); } - return {crat, crsl, cros, afcr, mrat, musl, muta, repl, cont, pops}; + return {crat, crsl, cros, afcr, mrat, musl, muta, repl, cont, offs}; } /** Perform a sub-problem search with the configuration encoded in the given solution @@ -160,7 +162,7 @@ public: double muta = config[i_muta]; double repl = config[i_repl]; double cont = config[i_cont]; - double pops = config[i_pops]; + double offs = config[i_offs]; if( 0 <= crat and crat < _foundry.crossover_rates.size() @@ -172,14 +174,13 @@ public: and 0 <= muta and muta < _foundry.mutations.size() and 0 <= repl and repl < _foundry.replacements.size() and 0 <= cont and cont < _foundry.continuators.size() - and 0 <= pops and pops < _foundry.pop_sizes.size() + and 0 <= offs and offs < _foundry.offspring_sizes.size() ) { _foundry.select(config); - // FIXME should pop_size belong to this eval and moved out from the foundry? // Reset pop eoPop pop; - pop.append( _foundry.pop_size(), _subpb_init); + pop.append( _pop_size, _subpb_init); _subpb_eval(pop,pop); // Actually perform a search @@ -194,6 +195,7 @@ public: } protected: + const size_t _pop_size; eoInit& _subpb_init; eoPopEvalFunc& _subpb_eval; eoAlgoFoundryFastGA& _foundry; From 03201c4f4fdf29365df96de8e2e373f5b8cd7aa3 Mon Sep 17 00:00:00 2001 From: aaziz-alaoui Date: Tue, 6 Oct 2020 13:54:44 +0200 Subject: [PATCH 19/42] fastga add problem parameter + irace target runner --- eo/contrib/irace/fastga.cpp | 45 ++++++---- .../irace/irace-algo-search/target-runner | 87 +++++++++++++++++++ 2 files changed, 114 insertions(+), 18 deletions(-) create mode 100755 eo/contrib/irace/irace-algo-search/target-runner diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index b20e5aa9c..a7a7c4be7 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -34,7 +34,7 @@ eoAlgoFoundryFastGA& make_foundry( // foundry.continuators.add< eoSteadyFitContinue >(10,i); // } - for(double i=0.1; i<1.0; i+=0.1) { + for(double i=0.1; i<1.0; i+=0.2) { foundry.crossover_rates.add(i); foundry.mutation_rates.add(i); } @@ -47,10 +47,11 @@ eoAlgoFoundryFastGA& make_foundry( foundry.offspring_sizes.add(0); // 0 = use parents fixed pop size. /***** Crossovers ****/ - for(double i=0.1; i<0.9; i+=0.1) { + for(double i=0.1; i<1.0; i+=0.2) { foundry.crossovers.add< eoUBitXover >(i); // preference over 1 } - for(size_t i=1; i < 11; i+=1) { + for(size_t i=1; i < 10; i+=2) { + foundry.crossovers.add< eoNPtsBitXover >(i); // nb of points } foundry.crossovers.add< eo1PtBitXover >(); @@ -63,7 +64,7 @@ eoAlgoFoundryFastGA& make_foundry( foundry.mutations.add< eoShiftedBitMutation >(p); // proba of flipping k bits, k drawn in binomial distrib, changing zeros to one foundry.mutations.add< eoNormalBitMutation >(p); // proba of flipping k bits, k drawn in normal distrib foundry.mutations.add< eoFastBitMutation >(p); // proba of flipping k bits, k drawn in powerlaw distrib - for(size_t i=1; i < 11; i+=1) { + for(size_t i=1; i < 11; i+=2) { foundry.mutations.add< eoDetSingleBitFlip >(i); // mutate k bits without duplicates } @@ -76,7 +77,7 @@ eoAlgoFoundryFastGA& make_foundry( ops.add< eoStochTournamentSelect >(0.5); ops.add< eoSequentialSelect >(); ops.add< eoProportionalSelect >(); - for(size_t i=2; i < 10; i+=4) { + for(size_t i=2; i < 11; i+=4) { ops.add< eoDetTournamentSelect >(i); } } @@ -88,10 +89,10 @@ eoAlgoFoundryFastGA& make_foundry( foundry.replacements.add< eoPlusReplacement >(); foundry.replacements.add< eoCommaReplacement >(); foundry.replacements.add< eoSSGAWorseReplacement >(); - for(double i=0.51; i<0.91; i+=0.1) { + for(double i=0.51; i<0.92; i+=0.2) { foundry.replacements.add< eoSSGAStochTournamentReplacement >(i); } - for(size_t i=2; i < 10; i+=1) { + for(size_t i=2; i < 11; i+=2) { foundry.replacements.add< eoSSGADetTournamentReplacement >(i); } @@ -150,14 +151,21 @@ int main(int argc, char* argv[]) // rng is a global rng.reseed(seed); - auto pop_size_p = parser.getORcreateParam(1, + + auto problem_p = parser.getORcreateParam(0, + "problem", "Problem ID", + 'p', "Problem", /*required=*/true); + const size_t problem = problem_p.value(); + + + auto pop_size_p = parser.getORcreateParam(5, "pop-size", "Population size", 'P', "Operator Choice", /*required=*/false); const size_t pop_size = pop_size_p.value(); auto instance_p = parser.getORcreateParam(0, "instance", "Instance ID", - 'i', "Problem", /*required=*/true); + 'i', "Instance", /*required=*/false); const size_t instance = instance_p.value(); auto continuator_p = parser.getORcreateParam(0, @@ -207,7 +215,7 @@ int main(int argc, char* argv[]) auto offspring_size_p = parser.getORcreateParam(0, "offspring-size", "Offsprings size (0 = same size than the parents pop, see --pop-size)", - 'P', "Operator Choice", /*required=*/false); // Single alternative, not required. + 'O', "Operator Choice", /*required=*/false); // Single alternative, not required. const size_t offspring_size = offspring_size_p.value(); @@ -236,12 +244,13 @@ int main(int argc, char* argv[]) * fake_foundry.continuators.size() * fake_foundry.offspring_sizes.size(); std::clog << std::endl; - std::clog << n << " possible algorithms instances." << 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; std::cout << "# name\tswitch\ttype\trange" << std::endl; - print_param_range( instance_p, 18, std::cout); + print_param_range( instance_p, 41, std::cout); + print_param_range( problem_p, 18, std::cout); print_param_range( continuator_p, fake_foundry.continuators .size(), std::cout); print_param_range( crossover_rate_p, fake_foundry.crossover_rates .size(), std::cout); print_param_range( crossover_selector_p, fake_foundry.crossover_selectors .size(), std::cout); @@ -297,7 +306,7 @@ int main(int argc, char* argv[]) /***** IOH logger *****/ - auto max_target_para = problem_config_mapping[instance].max_target; + auto max_target_para = problem_config_mapping[problem].max_target; IOHprofiler_RangeLinear target_range(0, max_target_para, buckets); IOHprofiler_RangeLinear budget_range(0, max_evals, buckets); IOHprofiler_ecdf_logger logger(target_range, budget_range); @@ -307,10 +316,10 @@ int main(int argc, char* argv[]) logger.activate_logger(); /***** IOH problem *****/ - double w_model_suite_dummy_para = problem_config_mapping[instance].dummy; - int w_model_suite_epitasis_para = problem_config_mapping[instance].epistasis; - int w_model_suite_neutrality_para = problem_config_mapping[instance].neutrality; - int w_model_suite_ruggedness_para = problem_config_mapping[instance].ruggedness; + double w_model_suite_dummy_para = problem_config_mapping[problem].dummy; + int w_model_suite_epitasis_para = problem_config_mapping[problem].epistasis; + int w_model_suite_neutrality_para = problem_config_mapping[problem].neutrality; + int w_model_suite_ruggedness_para = problem_config_mapping[problem].ruggedness; W_Model_OneMax w_model_om; std::string problem_name = "OneMax"; @@ -329,7 +338,7 @@ int main(int argc, char* argv[]) w_model_om.IOHprofiler_set_problem_name(problem_name); /// Set problem_id as 1 - w_model_om.IOHprofiler_set_problem_id(0); // FIXME check what that means + w_model_om.IOHprofiler_set_problem_id(problem); // FIXME check what that means w_model_om.IOHprofiler_set_instance_id(instance); // FIXME check what that means /// Set dimension. diff --git a/eo/contrib/irace/irace-algo-search/target-runner b/eo/contrib/irace/irace-algo-search/target-runner new file mode 100755 index 000000000..f9b0e3198 --- /dev/null +++ b/eo/contrib/irace/irace-algo-search/target-runner @@ -0,0 +1,87 @@ +#!/bin/bash +############################################################################### +# This script is the command that is executed every run. +# Check the examples in examples/ +# +# This script is run in the execution directory (execDir, --exec-dir). +# +# PARAMETERS: +# $1 is the candidate configuration number +# $2 is the instance ID +# $3 is the seed +# $4 is the instance name +# The rest ($* after `shift 4') are parameters to the run +# +# RETURN VALUE: +# This script should print one numerical value: the cost that must be minimized. +# Exit with 0 if no error, with 1 in case of error +############################################################################### +error() { + echo "`TZ=UTC date`: $0: error: $@" + exit 1 +} + + +EXE="/home/aaziz-alaoui/Documents/GitHub/paradiseo/eo/contrib/irace/irace-algo-search/bin/fastga" + +FIXED_PARAMS="" + +CONFIG_ID=$1 +INSTANCE_ID=$2 +SEED=$3 +INSTANCE=$4 +CROSSOVER_RATE=$5 +CROSSOVER_SELECTOR=$6 +CROSSOVER=$7 +MUTATION_RATE=$8 +MUT_SELECTOR=$9 +MUTATION=${10} +REPLACEMENT=${11} +shift 11 || error "Not enough parameters" + +CONFIG_PARAMS=$* + +STDOUT=c${CONFIG_ID}-${INSTANCE_ID}-${SEED}.stdout +STDERR=c${CONFIG_ID}-${INSTANCE_ID}-${SEED}.stderr + +if [ ! -x "${EXE}" ]; then + error "${EXE}: not found or not executable (pwd: $(pwd))" +fi + +# If the program just prints a number, we can use 'exec' to avoid +# creating another process, but there can be no other commands after exec. +#exec $EXE ${FIXED_PARAMS} -i $INSTANCE ${CONFIG_PARAMS} +# exit 1 +# +# Otherwise, save the output to a file, and parse the result from it. +# (If you wish to ignore segmentation faults you can use '{}' around +# the command.) +$EXE ${FIXED_PARAMS} --instance=$INSTANCE --seed=${SEED} --crossover-rate=${CROSSOVER_RATE} --cross-selector=${CROSSOVER_SELECTOR} --crossover=${CROSSOVER} --mutation-rate=${MUTATION_RATE} --mut-selector=${MUT_SELECTOR} --mutation=${MUTATION} --replacement=${REPLACEMENT} 1> ${STDOUT} 2> ${STDERR} + +#echo ${cmd} + + +# --instance=$INSTANCE --seed=$SEED +# remplacer config param par la même config que seed et instance id + + + +# This may be used to introduce a delay if there are filesystem +# issues. +#SLEEPTIME=1 +#while [ ! -s "${STDOUT}" ]; do +# sleep $SLEEPTIME +# let "SLEEPTIME += 1" +#done + +# This is an example of reading a number from the output. +# It assumes that the objective value is the first number in +# the first column of the last line of the output. +if [ -s "${STDOUT}" ]; then + COST=$(tail -n 1 ${STDOUT} | grep -e '^[[:space:]]*[+-]\?[0-9]' | cut -f1) + echo "$COST" + rm -f "${STDOUT}" "${STDERR}" + exit 0 +else + error "${STDOUT}: No such file or directory" +fi From b84a13e108c2d0a4d0fd70a2f5dc24b86b48df85 Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 6 Oct 2020 15:07:04 +0200 Subject: [PATCH 20/42] fix tests after FastGA foundry changes --- eo/test/t-eoAlgoFoundryFastGA.cpp | 8 +++--- eo/test/t-eoFoundryFastGA.cpp | 42 +++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/eo/test/t-eoAlgoFoundryFastGA.cpp b/eo/test/t-eoAlgoFoundryFastGA.cpp index 9c5881eb2..b80d19eb5 100644 --- a/eo/test/t-eoAlgoFoundryFastGA.cpp +++ b/eo/test/t-eoAlgoFoundryFastGA.cpp @@ -71,9 +71,9 @@ int main(int /*argc*/, char** /*argv*/) } /***** Offspring population size *****/ - foundry.pop_sizes.add(0); // 0 = same as parent pop + foundry.offspring_sizes.add(0); // 0 = same as parent pop // for(size_t s = pop_size; s < 2*pop_size; s+=pop_size/10) { - // foundry.pop_sizes.add(s); + // foundry.offspring_sizes.add(s); // } @@ -87,7 +87,7 @@ int main(int /*argc*/, char** /*argv*/) * foundry.mutations.size() * foundry.replacements.size() * foundry.continuators.size() - * foundry.pop_sizes.size(); + * foundry.offspring_sizes.size(); std::clog << n << " possible algorithms instances." << std::endl; EOT best_sol; @@ -103,7 +103,7 @@ int main(int /*argc*/, char** /*argv*/) for(size_t i_mut = 0; i_mut < foundry.mutations.size(); ++i_mut ) { for(size_t i_rep = 0; i_rep < foundry.replacements.size(); ++i_rep ) { for(size_t i_cont = 0; i_cont < foundry.continuators.size(); ++i_cont ) { - for(size_t i_pop = 0; i_pop < foundry.pop_sizes.size(); ++i_pop ) { + for(size_t i_pop = 0; i_pop < foundry.offspring_sizes.size(); ++i_pop ) { std::clog << "\r" << i++ << "/" << n-1; std::clog.flush(); eoPop pop; diff --git a/eo/test/t-eoFoundryFastGA.cpp b/eo/test/t-eoFoundryFastGA.cpp index 2718f514e..45abe7d84 100644 --- a/eo/test/t-eoFoundryFastGA.cpp +++ b/eo/test/t-eoFoundryFastGA.cpp @@ -26,7 +26,7 @@ eoAlgoFoundryFastGA& make_foundry(eoFunctorStore& store, eoInit& ini } for(size_t i=5; i<100; i+=10) { - foundry.pop_sizes.add(i); + foundry.offspring_sizes.add(i); } /***** Crossovers ****/ @@ -51,14 +51,24 @@ eoAlgoFoundryFastGA& make_foundry(eoFunctorStore& store, eoInit& ini } /***** Selectors *****/ - foundry.selectors.add< eoRandomSelect >(); - foundry.selectors.add< eoSequentialSelect >(); - foundry.selectors.add< eoProportionalSelect >(); - for(size_t i=2; i < 10; i+=1) { // Tournament size. - foundry.selectors.add< eoDetTournamentSelect >(i); + for(eoOperatorFoundry>& ops : + {std::ref(foundry.crossover_selectors), + std::ref(foundry.aftercross_selectors), + std::ref(foundry.mutation_selectors) }) { + + ops.add< eoRandomSelect >(); + ops.add< eoStochTournamentSelect >(0.5); + ops.add< eoSequentialSelect >(); + ops.add< eoProportionalSelect >(); + for(size_t i=2; i < 10; i+=4) { + ops.add< eoDetTournamentSelect >(i); + } } - for(double i=0.51; i<0.91; i+=0.1) { // Tournament size as perc of pop. - foundry.selectors.add< eoStochTournamentSelect >(i); + + /***** Variation rates *****/ + for(double r = 0.0; r < 1.0; r+=0.1) { + foundry.crossover_rates.add(r); + foundry. mutation_rates.add(r); } /***** Replacements ****/ @@ -88,8 +98,20 @@ int main(int /*argc*/, char** /*argv*/) auto& foundry = make_foundry(store, init, onemax_eval); - size_t n = foundry.continuators.size() * foundry.crossovers.size() * foundry.mutations.size() * foundry.selectors.size() * foundry.replacements.size()* foundry.crossover_rates.size() * foundry.mutation_rates.size() * foundry.pop_sizes.size(); - std::clog << n << " possible algorithms instances." << std::endl; + + size_t n = + foundry.crossover_rates.size() + * foundry.crossover_selectors.size() + * foundry.crossovers.size() + * foundry.aftercross_selectors.size() + * foundry.mutation_rates.size() + * foundry.mutation_selectors.size() + * foundry.mutations.size() + * foundry.replacements.size() + * foundry.continuators.size() + * foundry.offspring_sizes.size(); + + std::clog << n << " possible algorithms instances." << std::endl; eoPop pop; pop.append(5,init); From 3f61b435760343e482d8a5afbea093cceb3f35c2 Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 6 Oct 2020 15:07:23 +0200 Subject: [PATCH 21/42] fix eoProportionalSelect: fallback to last solution --- eo/src/eoProportionalSelect.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eo/src/eoProportionalSelect.h b/eo/src/eoProportionalSelect.h index 3fd49aded..7f10d53dc 100644 --- a/eo/src/eoProportionalSelect.h +++ b/eo/src/eoProportionalSelect.h @@ -93,9 +93,9 @@ public: typename FitVec::iterator result = std::upper_bound(cumulative.begin(), cumulative.end(), fortune); - assert(fortune <= cumulative.back()); + // assert(fortune <= cumulative.back()); - if(result - cumulative.begin() == _pop.size()) { + if(result - cumulative.begin() >= _pop.size()) { return _pop.back(); } else { return _pop[result - cumulative.begin()]; From b2a6fea7d2192fce193d8671efc8dd4c39574386 Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 6 Oct 2020 15:43:24 +0200 Subject: [PATCH 22/42] fix irace names, fix param output, remove perf assert --- eo/contrib/irace/fastga.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index a7a7c4be7..2170b2473 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -108,7 +108,11 @@ void print_param_range(const eoParam& param, const size_t slot_size, std::ostrea out << "# "; } - out << param.longName() + // 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() << "=\"" << "\ti"; @@ -248,9 +252,8 @@ int main(int argc, char* argv[]) std::clog << "Ranges of configurable parameters (redirect the stdout in a file to use it with iRace): " << std::endl; + // Do not print problem and instances, as they are managed separately by irace. std::cout << "# name\tswitch\ttype\trange" << std::endl; - print_param_range( instance_p, 41, std::cout); - print_param_range( problem_p, 18, std::cout); print_param_range( continuator_p, fake_foundry.continuators .size(), std::cout); print_param_range( crossover_rate_p, fake_foundry.crossover_rates .size(), std::cout); print_param_range( crossover_selector_p, fake_foundry.crossover_selectors .size(), std::cout); @@ -388,8 +391,14 @@ int main(int argc, char* argv[]) // iRace expects minimization long perf = ecdf_sum(logger.data()); + // assert(0 < perf and perf <= buckets*buckets); + if(perf <= 0 or buckets*buckets < perf) { + std::cerr << "WARNING: illogical performance: " << perf + << ", check the bounds?" + << " Will let it as is." << std::endl; + } + // Output std::cout << -1 * perf << std::endl; - assert(0 < perf and perf <= buckets*buckets); } From 2c80a01fadb364fce3faa184a19d74515e0b8de1 Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 6 Oct 2020 15:44:08 +0200 Subject: [PATCH 23/42] feat: add tailored irace config files --- .../irace/irace-config/default.instances | 48 ++++ eo/contrib/irace/irace-config/example.scen | 227 ++++++++++++++++++ eo/contrib/irace/irace-config/target-runner | 84 +++++++ eo/contrib/irace/run_irace.sh | 19 ++ 4 files changed, 378 insertions(+) create mode 100644 eo/contrib/irace/irace-config/default.instances create mode 100644 eo/contrib/irace/irace-config/example.scen create mode 100755 eo/contrib/irace/irace-config/target-runner create mode 100755 eo/contrib/irace/run_irace.sh diff --git a/eo/contrib/irace/irace-config/default.instances b/eo/contrib/irace/irace-config/default.instances new file mode 100644 index 000000000..a0a1adfc3 --- /dev/null +++ b/eo/contrib/irace/irace-config/default.instances @@ -0,0 +1,48 @@ +## This is an example of specifying instances with a file. + +# Each line is an instance relative to trainInstancesDir +# (see scenario.txt.tmpl) and an optional sequence of instance-specific +# parameters that will be passed to target-runnerx when invoked on that +# instance. + +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 diff --git a/eo/contrib/irace/irace-config/example.scen b/eo/contrib/irace/irace-config/example.scen new file mode 100644 index 000000000..6c7abb972 --- /dev/null +++ b/eo/contrib/irace/irace-config/example.scen @@ -0,0 +1,227 @@ +###################################################### -*- mode: r -*- ##### +## Scenario setup for Iterated Race (irace). +############################################################################ + +## To use the default value of a parameter of iRace, simply do not set +## the parameter (comment it out in this file, and do not give any +## value on the command line). + +## File that contains the description of the parameters of the target +## algorithm. +parameterFile = "./fastga.param" + +## Directory where the programs will be run. +execDir = "." + +## File to save tuning results as an R dataset, either absolute path or +## relative to execDir. +# logFile = "./irace.Rdata" + +## Previously saved log file to recover the execution of irace, either +## absolute path or relative to the current directory. If empty or NULL, +## recovery is not performed. +# recoveryFile = "" + +## Directory where training instances are located; either absolute path or +## relative to current directory. If no trainInstancesFiles is provided, +## all the files in trainInstancesDir will be listed as instances. +trainInstancesDir = "." + +## File that contains a list of training instances and optionally +## additional parameters for them. If trainInstancesDir is provided, irace +## will search for the files in this folder. +trainInstancesFile = "./default.instances" + +## File that contains a table of initial configurations. If empty or NULL, +## all initial configurations are randomly generated. +# configurationsFile = "" + +## File that contains a list of logical expressions that cannot be TRUE +## for any evaluated configuration. If empty or NULL, do not use forbidden +## expressions. +# forbiddenFile = "" + +## Script called for each configuration that executes the target algorithm +## to be tuned. See templates. +targetRunner = "./target-runner" + +## Number of times to retry a call to targetRunner if the call failed. +# targetRunnerRetries = 0 + +## Optional data passed to targetRunner. This is ignored by the default +## targetRunner function, but it may be used by custom targetRunner +## functions to pass persistent data around. +# targetRunnerData = "" + +## Optional R function to provide custom parallelization of targetRunner. +# targetRunnerParallel = "" + +## Optional script or R function that provides a numeric value for each +## configuration. See templates/target-evaluator.tmpl +# targetEvaluator = "" + +## Maximum number of runs (invocations of targetRunner) that will be +## performed. It determines the maximum budget of experiments for the +## tuning. +maxExperiments = 2000 + +## Maximum total execution time in seconds for the executions of +## targetRunner. targetRunner must return two values: cost and time. +# maxTime = 60 + +## Fraction (smaller than 1) of the budget used to estimate the mean +## computation time of a configuration. Only used when maxTime > 0 +# budgetEstimation = 0.02 + +## Maximum number of decimal places that are significant for numerical +## (real) parameters. +digits = 2 + +## Debug level of the output of irace. Set this to 0 to silence all debug +## messages. Higher values provide more verbose debug messages. +# debugLevel = 0 + +## Number of iterations. +# nbIterations = 0 + +## Number of runs of the target algorithm per iteration. +# nbExperimentsPerIteration = 0 + +## Randomly sample the training instances or use them in the order given. +# sampleInstances = 1 + +## Statistical test used for elimination. Default test is always F-test +## unless capping is enabled, in which case the default test is t-test. +## Valid values are: F-test (Friedman test), t-test (pairwise t-tests with +## no correction), t-test-bonferroni (t-test with Bonferroni's correction +## for multiple comparisons), t-test-holm (t-test with Holm's correction +## for multiple comparisons). +# testType = "F-test" + +## Number of instances evaluated before the first elimination test. It +## must be a multiple of eachTest. +# firstTest = 5 + +## Number of instances evaluated between elimination tests. +# eachTest = 1 + +## Minimum number of configurations needed to continue the execution of +## each race (iteration). +# minNbSurvival = 0 + +## Number of configurations to be sampled and evaluated at each iteration. +# nbConfigurations = 0 + +## Parameter used to define the number of configurations sampled and +## evaluated at each iteration. +# mu = 5 + +## Confidence level for the elimination test. +# confidence = 0.95 + +## If the target algorithm is deterministic, configurations will be +## evaluated only once per instance. +# deterministic = 0 + +## Seed of the random number generator (by default, generate a random +## seed). +# seed = NA + +## Number of calls to targetRunner to execute in parallel. Values 0 or 1 +## mean no parallelization. +# parallel = 0 + +## Enable/disable load-balancing when executing experiments in parallel. +## Load-balancing makes better use of computing resources, but increases +## communication overhead. If this overhead is large, disabling +## load-balancing may be faster. +# loadBalancing = 1 + +## Enable/disable MPI. Use Rmpi to execute targetRunner in parallel +## (parameter parallel is the number of slaves). +# mpi = 0 + +## Specify how irace waits for jobs to finish when targetRunner submits +## jobs to a batch cluster: sge, pbs, torque or slurm. targetRunner must +## submit jobs to the cluster using, for example, qsub. +# batchmode = 0 + +## Enable/disable the soft restart strategy that avoids premature +## convergence of the probabilistic model. +# softRestart = 1 + +## Soft restart threshold value for numerical parameters. If NA, NULL or +## "", it is computed as 10^-digits. +# softRestartThreshold = "" + +## Directory where testing instances are located, either absolute or +## relative to current directory. +# testInstancesDir = "" + +## File containing a list of test instances and optionally additional +## parameters for them. +# testInstancesFile = "" + +## Number of elite configurations returned by irace that will be tested if +## test instances are provided. +# testNbElites = 1 + +## Enable/disable testing the elite configurations found at each +## iteration. +# testIterationElites = 0 + +## Enable/disable elitist irace. +# elitist = 1 + +## Number of instances added to the execution list before previous +## instances in elitist irace. +# elitistNewInstances = 1 + +## In elitist irace, maximum number per race of elimination tests that do +## not eliminate a configuration. Use 0 for no limit. +# elitistLimit = 2 + +## User-defined R function that takes a configuration generated by irace +## and repairs it. +# repairConfiguration = "" + +## Enable the use of adaptive capping, a technique designed for minimizing +## the computation time of configurations. This is only available when +## elitist is active. +# capping = 0 + +## Measure used to obtain the execution bound from the performance of the +## elite configurations: median, mean, worst, best. +# cappingType = "median" + +## Method to calculate the mean performance of elite configurations: +## candidate or instance. +# boundType = "candidate" + +## Maximum execution bound for targetRunner. It must be specified when +## capping is enabled. +# boundMax = 0 + +## Precision used for calculating the execution time. It must be specified +## when capping is enabled. +# boundDigits = 0 + +## Penalization constant for timed out executions (executions that reach +## boundMax execution time). +# boundPar = 1 + +## Replace the configuration cost of bounded executions with boundMax. +# boundAsTimeout = 1 + +## Percentage of the configuration budget used to perform a postselection +## race of the best configurations of each iteration after the execution +## of irace. +# postselection = 0 + +## Enable/disable AClib mode. This option enables compatibility with +## GenericWrapper4AC as targetRunner script. +# aclib = 0 + +## END of scenario file +############################################################################ + diff --git a/eo/contrib/irace/irace-config/target-runner b/eo/contrib/irace/irace-config/target-runner new file mode 100755 index 000000000..e09729eb2 --- /dev/null +++ b/eo/contrib/irace/irace-config/target-runner @@ -0,0 +1,84 @@ +#!/bin/bash +############################################################################### +# This script is the command that is executed every run. +# Check the examples in examples/ +# +# This script is run in the execution directory (execDir, --exec-dir). +# +# PARAMETERS: +# $1 is the candidate configuration number +# $2 is the instance ID +# $3 is the seed +# $4 is the instance name +# The rest ($* after `shift 4') are parameters to the run +# +# RETURN VALUE: +# This script should print one numerical value: the cost that must be minimized. +# Exit with 0 if no error, with 1 in case of error +############################################################################### +error() { + echo "`TZ=UTC date`: $0: error: $@" + exit 1 +} + + +EXE="./fastga" + +FIXED_PARAMS="--problem=0" + +CONFIG_ID=$1 +INSTANCE_ID=$2 +SEED=$3 +INSTANCE=$(echo $4 | sed 's/\//\n/g'|tail -n 1) +CROSSOVER_RATE=$5 +CROSSOVER_SELECTOR=$6 +CROSSOVER=$7 +MUTATION_RATE=$8 +MUT_SELECTOR=$9 +MUTATION=${10} +REPLACEMENT=${11} +shift 11 || error "Not enough parameters" + +INSTANCE_PARAMS=$* + +STDOUT=c${CONFIG_ID}_i${INSTANCE_ID}_s${SEED}.stdout +STDERR=c${CONFIG_ID}_i${INSTANCE_ID}_s${SEED}.stderr + +if [ ! -x "${EXE}" ]; then + error "${EXE}: not found or not executable (pwd: $(pwd))" +fi + +# If the program just prints a number, we can use 'exec' to avoid +# creating another process, but there can be no other commands after exec. +#exec $EXE ${FIXED_PARAMS} -i $INSTANCE ${INSTANCE_PARAMS} +# exit 1 +# +# Otherwise, save the output to a file, and parse the result from it. +# (If you wish to ignore segmentation faults you can use '{}' around +# the command.) +cmd="$EXE ${FIXED_PARAMS} --instance=${INSTANCE} --seed=${SEED} ${CROSSOVER_RATE} ${CROSSOVER_SELECTOR} ${CROSSOVER} ${MUTATION_RATE} ${MUT_SELECTOR} ${MUTATION} ${REPLACEMENT}" +# NOTE: irace seems to capture both stderr and stdout, so you should not output to stderr +echo ${cmd} > ${STDERR} +$cmd 2> ${STDERR} | tee ${STDOUT} + +# The following code is useless if the binary only output a single number on stdout. + +# This may be used to introduce a delay if there are filesystem +# issues. +# SLEEPTIME=1 +# while [ ! -s "${STDOUT}" ]; do +# sleep $SLEEPTIME +# let "SLEEPTIME += 1" +# done + +# This is an example of reading a number from the output. +# It assumes that the objective value is the first number in +# the first column of the last line of the output. +# if [ -s "${STDOUT}" ]; then +# COST=$(tail -n 1 ${STDOUT} | grep -e '^[[:space:]]*[+-]\?[0-9]' | cut -f1) +# echo "$COST" +# rm -f "${STDOUT}" "${STDERR}" +# exit 0 +# else +# error "${STDOUT}: No such file or directory" +# fi diff --git a/eo/contrib/irace/run_irace.sh b/eo/contrib/irace/run_irace.sh new file mode 100755 index 000000000..1f852b7f9 --- /dev/null +++ b/eo/contrib/irace/run_irace.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +if [[ $# != 1 ]] ; then + echo "ERROR: build dir not indicated" + exit 1 +fi + +cd $1 +pwd + +# Fore some reason, irace absolutely need those files... +cp ../irace-config/example.scen . +cp ../irace-config/target-runner . +cp ../irace-config/default.instances . + +# Generate the parameter list file. +./fastga -h > fastga.param 2>/dev/null +/usr/lib/R/site-library/irace/bin/irace --scenario example.scen + From be230c34cdce452c835139f5d08ea13d0296972b Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 6 Oct 2020 17:53:37 +0200 Subject: [PATCH 24/42] feat add a debug log for restarts --- eo/src/eoAlgoRestart.h | 1 + 1 file changed, 1 insertion(+) diff --git a/eo/src/eoAlgoRestart.h b/eo/src/eoAlgoRestart.h index 2f61ea4e5..690a27ccb 100644 --- a/eo/src/eoAlgoRestart.h +++ b/eo/src/eoAlgoRestart.h @@ -147,6 +147,7 @@ public: virtual void operator()(eoPop & pop) { do { + eo::log << eo::debug << "Restart" << std::endl; _reseter(pop); _algo(pop); } while( _continue(pop) ); From fd09739770a24d4a4c980f08586984d32582236e Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 6 Oct 2020 17:54:11 +0200 Subject: [PATCH 25/42] fix: maximization & max restarts, feat: always use absolute values in logger --- eo/contrib/irace/fastga.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index 2170b2473..cabf06220 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -11,8 +11,8 @@ #include // using Particle = eoRealParticle; -using Ints = eoInt, size_t>; -using Bits = eoBit, int>; +using Ints = eoInt, size_t>; +using Bits = eoBit, int>; // by enumerating candidate operators and their parameters. eoAlgoFoundryFastGA& make_foundry( @@ -23,7 +23,8 @@ eoAlgoFoundryFastGA& make_foundry( const size_t generations ) { - auto& foundry = store.pack< eoAlgoFoundryFastGA >(init, eval_onemax, max_evals /*, max_restarts = max */); + // 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); /***** Continuators ****/ foundry.continuators.add< eoGenContinue >(generations); @@ -312,7 +313,9 @@ int main(int argc, char* argv[]) auto max_target_para = problem_config_mapping[problem].max_target; IOHprofiler_RangeLinear target_range(0, max_target_para, buckets); IOHprofiler_RangeLinear budget_range(0, max_evals, buckets); - IOHprofiler_ecdf_logger logger(target_range, budget_range); + IOHprofiler_ecdf_logger logger( + target_range, budget_range, + /*use_known_optimum*/false); logger.set_complete_flag(true); logger.set_interval(0); @@ -394,8 +397,7 @@ int main(int argc, char* argv[]) // assert(0 < perf and perf <= buckets*buckets); if(perf <= 0 or buckets*buckets < perf) { std::cerr << "WARNING: illogical performance: " << perf - << ", check the bounds?" - << " Will let it as is." << std::endl; + << ", check the bounds or the algorithm." << std::endl; } // Output From 82ff91d59b8b07eb4b1a3a6fc4da7f553f6d4094 Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 6 Oct 2020 18:08:35 +0200 Subject: [PATCH 26/42] fix: disable IOH_set_instance, seems bugged --- eo/contrib/irace/fastga.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index cabf06220..6d1b98bb0 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -345,7 +345,7 @@ int main(int argc, char* argv[]) /// Set problem_id as 1 w_model_om.IOHprofiler_set_problem_id(problem); // FIXME check what that means - w_model_om.IOHprofiler_set_instance_id(instance); // FIXME check what that means + // w_model_om.IOHprofiler_set_instance_id(instance); // FIXME changing the instance seems to change the target upper bound. /// Set dimension. w_model_om.IOHprofiler_set_number_of_variables(dimension); From b2e565a3d861f43f1b88097a7eb114888030fe70 Mon Sep 17 00:00:00 2001 From: nojhan Date: Tue, 6 Oct 2020 18:27:11 +0200 Subject: [PATCH 27/42] add an assert on the problem id --- eo/contrib/irace/fastga.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index 6d1b98bb0..410b1aaa4 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -307,7 +307,7 @@ int main(int argc, char* argv[]) {17, {0.5, 4, 5, 0, 100}}, }; - + assert(0 <= problem and problem < problem_config_mapping.size()); /***** IOH logger *****/ auto max_target_para = problem_config_mapping[problem].max_target; From e975f0f388a1728217181dc16a2043f553170b69 Mon Sep 17 00:00:00 2001 From: nojhan Date: Wed, 7 Oct 2020 15:53:36 +0200 Subject: [PATCH 28/42] fix eoDetSingleBitFlip num_bit setting - remove the reference in the constructor, which is error prone because not explicit. - replace it with an explicit setter. - add an assert to check that num_bit is consistent at call. --- eo/src/ga/eoBitOp.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/eo/src/ga/eoBitOp.h b/eo/src/ga/eoBitOp.h index 8645a86e1..b3e33efec 100644 --- a/eo/src/ga/eoBitOp.h +++ b/eo/src/ga/eoBitOp.h @@ -110,10 +110,8 @@ class eoDetSingleBitFlip: public eoMonOp * (Default) Constructor. * @param _num_bit The number of bits to change * default is one - equivalent to eoOneBitFlip then - * - * @note: use a reference for num_bit, thus you may change and recall without having to re-instantiate. */ - eoDetSingleBitFlip(const unsigned& _num_bit = 1): num_bit(_num_bit) {} + eoDetSingleBitFlip(const unsigned _num_bit = 1): num_bit(_num_bit) {} /// The class name. virtual std::string className() const { return "eoDetSingleBitFlip"; } @@ -138,6 +136,7 @@ class eoDetSingleBitFlip: public eoMonOp } // Flip at first indices + assert(num_bit <= chrom.size()); for(unsigned i=0; i } } + void number_bits(const unsigned _num_bit) + { + num_bit = _num_bit; + } + protected: - const unsigned& num_bit; + unsigned num_bit; }; From 7ca5b6c0d0b298e16b82f62899a36983eb2c8501 Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Thu, 8 Oct 2020 15:26:07 +0200 Subject: [PATCH 29/42] remove FastGA foundry last evals, more logs, fix some typos --- eo/src/eoAlgoFoundryFastGA.h | 9 ++++++--- eo/src/eoAlgoRestart.h | 2 ++ eo/src/eoEvalFoundryFastGA.h | 2 +- eo/src/eoFastGA.h | 4 ++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/eo/src/eoAlgoFoundryFastGA.h b/eo/src/eoAlgoFoundryFastGA.h index 3766b8a44..5125d4c95 100644 --- a/eo/src/eoAlgoFoundryFastGA.h +++ b/eo/src/eoAlgoFoundryFastGA.h @@ -138,7 +138,7 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry 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()); + assert( offspring_sizes.size() > 0); assert(this->at( offspring_sizes.index()) < offspring_sizes.size()); // Objective function calls counter eoEvalCounterThrowException eval(_eval, _max_evals); @@ -167,10 +167,13 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry try { restart(pop); } catch(eoMaxEvalException e) { +#ifndef NDEBUG + eo::log << eo::debug << "Reached maximum evaluations: " << eval.getValue() << " / " << _max_evals << std::endl; +#endif // In case some solutions were not evaluated when max eval occured. // FIXME can this even be considered legal? - eoPopLoopEval pop_last_eval(_eval); - pop_last_eval(pop,pop); + // eoPopLoopEval pop_last_eval(_eval); + // pop_last_eval(pop,pop); } } diff --git a/eo/src/eoAlgoRestart.h b/eo/src/eoAlgoRestart.h index 690a27ccb..ebea3aec5 100644 --- a/eo/src/eoAlgoRestart.h +++ b/eo/src/eoAlgoRestart.h @@ -147,7 +147,9 @@ public: virtual void operator()(eoPop & pop) { do { +#ifndef NDEBUG eo::log << eo::debug << "Restart" << std::endl; +#endif _reseter(pop); _algo(pop); } while( _continue(pop) ); diff --git a/eo/src/eoEvalFoundryFastGA.h b/eo/src/eoEvalFoundryFastGA.h index b85561d1a..349fa6aad 100644 --- a/eo/src/eoEvalFoundryFastGA.h +++ b/eo/src/eoEvalFoundryFastGA.h @@ -189,7 +189,7 @@ public: sol.fitness( pop.best_element().fitness() ); } else { - eo::log << eo::warnings << "WARNING: encoded algo is out of bounds" << std::endl; + eo::log << eo::warnings << "WARNING: encoded algo is out of bounds, penalize to: " << _penalization << std::endl; sol.fitness( _penalization ); // penalization } } diff --git a/eo/src/eoFastGA.h b/eo/src/eoFastGA.h index ac38f2532..bf4374d87 100644 --- a/eo/src/eoFastGA.h +++ b/eo/src/eoFastGA.h @@ -101,8 +101,8 @@ public: EOT sol1 = _select_cross(pop); EOT sol2 = _select_cross(pop); - // If the operator returns true, - // olutions have been altered. + // If the operator returns true, + // solutions have been altered. if(_crossover(sol1, sol2)) { sol1.invalidate(); sol2.invalidate(); From 39ff028e571a01735558dd7c22fbfc7bea2ea052 Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Thu, 8 Oct 2020 15:26:51 +0200 Subject: [PATCH 30/42] refactor out eval foundry, useless in irace/fastga --- eo/contrib/irace/fastga.cpp | 41 ++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index 410b1aaa4..52b8b3cbf 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -24,7 +24,8 @@ eoAlgoFoundryFastGA& make_foundry( ) { // 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_onemax, max_evals, /*max_restarts=*/1); + auto& foundry = store.pack< eoAlgoFoundryFastGA >(init, eval_onemax, max_evals); /***** Continuators ****/ foundry.continuators.add< eoGenContinue >(generations); @@ -272,9 +273,9 @@ int main(int argc, char* argv[]) exit(NO_ERROR); } - const size_t generations = static_cast(std::floor( - static_cast(max_evals) / static_cast(pop_size))); - + // const size_t generations = static_cast(std::floor( + // static_cast(max_evals) / static_cast(pop_size))); + const size_t generations = std::numeric_limits::max(); // Problem configuration code. @@ -354,13 +355,18 @@ int main(int argc, char* argv[]) logger.track_problem(w_model_om); eoEvalIOHproblem onemax_pb(w_model_om, logger); - eoPopLoopEval onemax_eval(onemax_pb); + + eoEvalFuncCounter eval_count(onemax_pb); + + // eoPopLoopEval onemax_eval(onemax_pb); + eoPopLoopEval onemax_eval(eval_count); /***** Instanciate and run the algo *****/ eoUniformGenerator ugen(0, 1); eoInitFixedLength onemax_init(/*bitstring size=*/dimension, ugen); - auto& foundry = make_foundry(store, onemax_init, onemax_pb, max_evals, generations); + // auto& foundry = make_foundry(store, onemax_init, onemax_pb, max_evals, generations); + auto& foundry = make_foundry(store, onemax_init, eval_count, max_evals, generations); Ints encoded_algo(foundry.size()); @@ -379,15 +385,20 @@ int main(int argc, char* argv[]) foundry.select(encoded_algo); std::clog << foundry.name() << std::endl; - // Evaluation of a forged encoded_algo on the sub-problem - eoEvalFoundryFastGA eval_foundry( - foundry, pop_size, - onemax_init, onemax_eval, - /*penalization=*/ dimension, // Worst case penalization. - /*normalized=*/ false); // Use direct integer encoding. + // // Evaluation of a forged encoded_algo on the sub-problem + // eoEvalFoundryFastGA eval_foundry( + // foundry, pop_size, + // onemax_init, onemax_eval, + // /*penalization=*/ dimension, // Worst case penalization. + // /*normalized=*/ false); // Use direct integer encoding. + // + // // Actually instanciate and run the algorithm. + // eval_foundry(encoded_algo); - // Actually instanciate and run the algorithm. - eval_foundry(encoded_algo); + eoPop pop; + pop.append(pop_size, onemax_init); + onemax_eval(pop,pop); + foundry(pop); // Actually run the selected algorithm. /***** IOH perf stats *****/ IOHprofiler_ecdf_sum ecdf_sum; @@ -400,6 +411,8 @@ int main(int argc, char* argv[]) << ", check the bounds or the algorithm." << std::endl; } + std::clog << "After " << eval_count.getValue() << " / " << max_evals << " evaluations" << std::endl; + // Output std::cout << -1 * perf << std::endl; From da4118142f53e7e2cd06a611575eb3f932d13e4a Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 9 Oct 2020 13:33:43 +0200 Subject: [PATCH 31/42] add some missing className --- eo/src/eoRandomSelect.h | 8 ++++++++ eo/src/ga/eoStandardBitMutation.h | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/eo/src/eoRandomSelect.h b/eo/src/eoRandomSelect.h index 1b15bbffa..4fd4dbb18 100644 --- a/eo/src/eoRandomSelect.h +++ b/eo/src/eoRandomSelect.h @@ -48,6 +48,9 @@ template class eoRandomSelect: public eoSelectOne { return _pop[eo::rng.random(_pop.size())] ; } + + virtual std::string className() const {return "eoRandomSelect";} + }; /** eoBestSelect: a selection method that always return the best @@ -64,6 +67,8 @@ template class eoBestSelect: public eoSelectOne { return _pop.best_element() ; } + + virtual std::string className() const {return "eoBestSelect";} }; /** eoNoSelect: returns all individual in order WITHOUT USING FITNESS!!! @@ -86,6 +91,9 @@ template class eoNoSelect: public eoSelectOne current++; return _pop[current-1] ; } + + virtual std::string className() const {return "eoNoSelect";} + private: unsigned current; }; diff --git a/eo/src/ga/eoStandardBitMutation.h b/eo/src/ga/eoStandardBitMutation.h index 50ad7873e..a2f7f12aa 100644 --- a/eo/src/ga/eoStandardBitMutation.h +++ b/eo/src/ga/eoStandardBitMutation.h @@ -28,6 +28,8 @@ class eoStandardBitMutation : public eoMonOp return _bitflip(chrom); } + virtual std::string className() const {return "eoStandardBitMutation";} + protected: double _rate; unsigned _nb; @@ -58,6 +60,8 @@ class eoUniformBitMutation : public eoMonOp return _bitflip(chrom); } + virtual std::string className() const {return "eoUniformBitMutation";} + protected: double _rate; unsigned _nb; @@ -93,6 +97,8 @@ class eoConditionalBitMutation : public eoStandardBitMutation // thus one don't need to re-instantiate. return this->_bitflip(chrom); } + + virtual std::string className() const {return "eoConditionalBitMutation";} }; /** Shifted standard bit mutation with mutation rate p: @@ -125,6 +131,8 @@ class eoShiftedBitMutation : public eoStandardBitMutation // thus one don't need to re-instantiate. return this->_bitflip(chrom); } + + virtual std::string className() const {return "eoShiftedBitMutation";} }; /** Mutation which size is sample in a gaussian. @@ -163,6 +171,8 @@ class eoNormalBitMutation : public eoStandardBitMutation return this->_bitflip(chrom); } + virtual std::string className() const {return "eoNormalBitMutation";} + protected: double _variance; }; @@ -196,6 +206,8 @@ class eoFastBitMutation : public eoStandardBitMutation return this->_bitflip(chrom); } + virtual std::string className() const {return "eoFastBitMutation";} + protected: double powerlaw(unsigned n, double beta) From 3d6821a97cdb016412aab126aab8fda7aacffd37 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 9 Oct 2020 14:09:45 +0200 Subject: [PATCH 32/42] fix: add template to eoBooleanGenerator In order to be able to generate boolean within int types. --- eo/src/utils/eoRndGenerators.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/eo/src/utils/eoRndGenerators.h b/eo/src/utils/eoRndGenerators.h index 14cb8f822..e1168dcd2 100644 --- a/eo/src/utils/eoRndGenerators.h +++ b/eo/src/utils/eoRndGenerators.h @@ -115,15 +115,16 @@ inline bool eoUniformGenerator::operator()(void) to easily generate random booleans with a specified bias \ingroup bitstring */ -class eoBooleanGenerator : public eoRndGenerator +template +class eoBooleanGenerator : public eoRndGenerator { - public : - eoBooleanGenerator(float _bias = 0.5, eoRng& _rng = rng) : bias(_bias), gen(_rng) {} + public : + eoBooleanGenerator(float _bias = 0.5, eoRng& _rng = rng) : bias(_bias), gen(_rng) {} - bool operator()(void) { return gen.flip(bias); } - private : - float bias; - eoRng& gen; + T operator()(void) { return gen.flip(bias); } + private : + float bias; + eoRng& gen; }; /** From 08b826c81b383af9e55b62c2cac9b57fef038e36 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 9 Oct 2020 14:21:12 +0200 Subject: [PATCH 33/42] feat: more useful FastGA foundry name() --- eo/src/eoAlgoFoundryFastGA.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/eo/src/eoAlgoFoundryFastGA.h b/eo/src/eoAlgoFoundryFastGA.h index 5125d4c95..99b778f2a 100644 --- a/eo/src/eoAlgoFoundryFastGA.h +++ b/eo/src/eoAlgoFoundryFastGA.h @@ -182,16 +182,16 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry std::string name() { std::ostringstream name; - name << this->at( crossover_rates.index()) << " (" << this-> crossover_rate() << ") + "; - name << this->at( crossover_selectors.index()) << " (" << this-> crossover_selector().className() << ") + "; - name << this->at(aftercross_selectors.index()) << " (" << this->aftercross_selector().className() << ") + "; - name << this->at( crossovers.index()) << " (" << this-> crossover().className() << ") + "; - name << this->at( mutation_rates.index()) << " (" << this-> mutation_rate() << ") + "; - name << this->at( mutation_selectors.index()) << " (" << this-> mutation_selector().className() << ") + "; - name << this->at( mutations.index()) << " (" << this-> mutation().className() << ") + "; - name << this->at( replacements.index()) << " (" << this-> replacement().className() << ") + "; - name << this->at( continuators.index()) << " (" << this-> continuator().className() << ") + "; - name << this->at( offspring_sizes.index()) << " (" << this-> offspring_size() << ")"; + name << "crossover_rates: " << this->at( crossover_rates.index()) << " (" << this-> crossover_rate() << ") + "; + name << "crossover_selectors: " << this->at( crossover_selectors.index()) << " (" << this-> crossover_selector().className() << ") + "; + name << "aftercross_selector: " << this->at(aftercross_selectors.index()) << " (" << this->aftercross_selector().className() << ") + "; + name << "crossovers: " << this->at( crossovers.index()) << " (" << this-> crossover().className() << ") + "; + name << "mutation_rates: " << this->at( mutation_rates.index()) << " (" << this-> mutation_rate() << ") + "; + name << "mutation_selectors: " << this->at( mutation_selectors.index()) << " (" << this-> mutation_selector().className() << ") + "; + name << "mutations: " << this->at( mutations.index()) << " (" << this-> mutation().className() << ") + "; + name << "replacements: " << this->at( replacements.index()) << " (" << this-> replacement().className() << ") + "; + name << "continuators: " << this->at( continuators.index()) << " (" << this-> continuator().className() << ") + "; + name << "offspring_sizes: " << this->at( offspring_sizes.index()) << " (" << this-> offspring_size() << ")"; return name.str(); } From 34eadef7a290b22a08ad739d3a429b9696449311 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 9 Oct 2020 14:53:53 +0200 Subject: [PATCH 34/42] feat: add eoEvalPrint --- eo/src/eo | 1 + eo/src/eoEvalPrint.h | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 eo/src/eoEvalPrint.h diff --git a/eo/src/eo b/eo/src/eo index b77e9bf2c..55c070857 100644 --- a/eo/src/eo +++ b/eo/src/eo @@ -85,6 +85,7 @@ #include "eoEvalKeepBest.h" #include "eoEvalTimeThrowException.h" #include "eoEvalUserTimeThrowException.h" +#include "eoEvalPrint.h" // Continuators - all include eoContinue.h #include "eoCombinedContinue.h" diff --git a/eo/src/eoEvalPrint.h b/eo/src/eoEvalPrint.h new file mode 100644 index 000000000..7b151b8fc --- /dev/null +++ b/eo/src/eoEvalPrint.h @@ -0,0 +1,23 @@ + +template< class EOT> +class eoEvalPrint: public eoEvalFunc +{ + protected: + std::ostream& _out; + eoEvalFunc& _eval; + std::string _sep; + + public: + + eoEvalPrint(eoEvalFunc& eval, std::ostream& out=std::cout, std::string sep="\n") : + _out(out), + _eval(eval), + _sep(sep) + {} + + void operator()( EOT& sol ) + { + _eval(sol); + _out << sol << _sep; + } +}; From 0665cc02f5c2967db024d5a67e30866e769630e5 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 9 Oct 2020 16:15:44 +0200 Subject: [PATCH 35/42] fix: do not count two times the evaluations in eoEvalCounterThrowException --- eo/src/eoEvalCounterThrowException.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/eo/src/eoEvalCounterThrowException.h b/eo/src/eoEvalCounterThrowException.h index b83699916..a17982a43 100644 --- a/eo/src/eoEvalCounterThrowException.h +++ b/eo/src/eoEvalCounterThrowException.h @@ -64,20 +64,18 @@ public : // bypass already evaluated individuals if (eo.invalid()) { - // increment the value of the self parameter - // (eoEvalFuncCounter inherits from @see eoValueParam) - value()++; + // evaluate + this->eoEvalFuncCounter::operator()(eo); + // No need to increment value(), it is done in the superclass. + // increment t // if we have reached the maximum - if ( value() >= _threshold ) { + if ( this->value() >= _threshold ) { // go back through the stack until catched throw eoMaxEvalException(_threshold); } - // evaluate - this->eoEvalFuncCounter::operator()(eo); - } // if invalid } From 0f4dbf3a13d957467f05706a5f13676b9eee8265 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 9 Oct 2020 16:17:49 +0200 Subject: [PATCH 36/42] fix template change of eoBooleanGenerator --- eo/src/ga/make_genotype_ga.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eo/src/ga/make_genotype_ga.h b/eo/src/ga/make_genotype_ga.h index 93cab894d..3a1afaa84 100644 --- a/eo/src/ga/make_genotype_ga.h +++ b/eo/src/ga/make_genotype_ga.h @@ -68,7 +68,7 @@ eoInit & do_make_genotype(eoParser& _parser, eoState& _state, EOT, float _b // Then we can built a bitstring random initializer // based on boolean_generator class (see utils/rnd_generator.h) - eoBooleanGenerator * gen = new eoBooleanGenerator(_bias); + eoBooleanGenerator * gen = new eoBooleanGenerator(_bias); _state.storeFunctor(gen); eoInitFixedLength* init = new eoInitFixedLength(theSize, *gen); // store in state From 6d465c6c2f898f4898efcb29f11b8232262157b0 Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 9 Oct 2020 16:19:04 +0200 Subject: [PATCH 37/42] fix FastGA mutation invalidation --- eo/src/eoFastGA.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/eo/src/eoFastGA.h b/eo/src/eoFastGA.h index bf4374d87..f157377f1 100644 --- a/eo/src/eoFastGA.h +++ b/eo/src/eoFastGA.h @@ -82,6 +82,7 @@ public: // Set lambda to the pop size // if it was not set up at construction. if(_offsprings_size == 0) { + // eo::log << eo::debug << "Set offspring size to: " << pop.size() << std::endl; _offsprings_size = pop.size(); } @@ -89,8 +90,10 @@ public: eoPop offsprings; for(size_t i=0; i < _offsprings_size; ++i) { + // eo::log << eo::xdebug << "\tOffspring #" << i << std::endl; if(eo::rng.flip(_rate_crossover)) { + // eo::log << eo::xdebug << "\t\tDo crossover" << std::endl; // Manual setup of eoSelectOne // (usually they are setup in a // wrapping eoSelect). @@ -118,6 +121,7 @@ public: // Additional mutation (X)OR the crossed/cloned solution. if(eo::rng.flip(_rate_mutation)) { + // eo::log << eo::xdebug << "\t\tDo mutation" << std::endl; if(_mutation(sol3)) { sol3.invalidate(); } @@ -125,9 +129,12 @@ public: offsprings.push_back(sol3); } else { // If not crossing, always mutate. + // eo::log << eo::xdebug << "\t\tNo crossover, do mutation" << std::endl; _select_mut.setup(pop); EOT sol3 = _select_mut(pop); - _mutation(sol3); + if(_mutation(sol3)) { + sol3.invalidate(); + } offsprings.push_back(sol3); } } @@ -136,6 +143,8 @@ public: _pop_eval(pop, offsprings); _replace(pop, offsprings); + // eo::log << eo::xdebug << "\tEnd of generation" << std::endl; + } while(_continuator(pop)); #ifndef NDEBUG assert(pop.size() > 0); From 70e79aba3dcf12135968a531bf0eae26cfd489be Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 9 Oct 2020 16:32:42 +0200 Subject: [PATCH 38/42] fix fastga: eval minus pop_size for init --- eo/contrib/irace/fastga.cpp | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index 52b8b3cbf..cc67a43bd 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -24,8 +24,7 @@ eoAlgoFoundryFastGA& make_foundry( ) { // 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_onemax, max_evals); + auto& foundry = store.pack< eoAlgoFoundryFastGA >(init, eval_onemax, generations, max_evals, /*max_restarts=*/1); /***** Continuators ****/ foundry.continuators.add< eoGenContinue >(generations); @@ -36,7 +35,7 @@ eoAlgoFoundryFastGA& make_foundry( // foundry.continuators.add< eoSteadyFitContinue >(10,i); // } - for(double i=0.1; i<1.0; i+=0.2) { + for(double i=0.0; i<1.0; i+=0.2) { foundry.crossover_rates.add(i); foundry.mutation_rates.add(i); } @@ -164,7 +163,7 @@ int main(int argc, char* argv[]) const size_t problem = problem_p.value(); - auto pop_size_p = parser.getORcreateParam(5, + auto pop_size_p = parser.getORcreateParam(1, "pop-size", "Population size", 'P', "Operator Choice", /*required=*/false); const size_t pop_size = pop_size_p.value(); @@ -273,14 +272,14 @@ int main(int argc, char* argv[]) exit(NO_ERROR); } - // const size_t generations = static_cast(std::floor( - // static_cast(max_evals) / static_cast(pop_size))); - const size_t generations = std::numeric_limits::max(); - + const 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; // Problem configuration code. struct Problem { - double dummy; + double dummy; size_t epistasis; size_t neutrality; size_t ruggedness; @@ -356,17 +355,16 @@ int main(int argc, char* argv[]) eoEvalIOHproblem onemax_pb(w_model_om, logger); + // eoEvalPrint eval_print(onemax_pb, std::clog, "\n"); eoEvalFuncCounter eval_count(onemax_pb); - // eoPopLoopEval onemax_eval(onemax_pb); eoPopLoopEval onemax_eval(eval_count); /***** Instanciate and run the algo *****/ - eoUniformGenerator ugen(0, 1); - eoInitFixedLength onemax_init(/*bitstring size=*/dimension, ugen); - // auto& foundry = make_foundry(store, onemax_init, onemax_pb, max_evals, generations); - auto& foundry = make_foundry(store, onemax_init, eval_count, max_evals, generations); + eoBooleanGenerator bgen; + eoInitFixedLength onemax_init(/*bitstring size=*/dimension, bgen); + auto& foundry = make_foundry(store, onemax_init, eval_count, max_evals - pop_size, generations); Ints encoded_algo(foundry.size()); @@ -411,7 +409,7 @@ int main(int argc, char* argv[]) << ", check the bounds or the algorithm." << std::endl; } - std::clog << "After " << eval_count.getValue() << " / " << max_evals << " evaluations" << std::endl; + // std::clog << "After " << eval_count.getValue() << " / " << max_evals << " evaluations" << std::endl; // Output std::cout << -1 * perf << std::endl; From 48430567b06152fad4e91f63cb4ed12e5e0bc59c Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 9 Oct 2020 16:35:27 +0200 Subject: [PATCH 39/42] declutch log in target-runner --- eo/contrib/irace/irace-config/target-runner | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/eo/contrib/irace/irace-config/target-runner b/eo/contrib/irace/irace-config/target-runner index e09729eb2..9ca4f824a 100755 --- a/eo/contrib/irace/irace-config/target-runner +++ b/eo/contrib/irace/irace-config/target-runner @@ -41,8 +41,10 @@ shift 11 || error "Not enough parameters" INSTANCE_PARAMS=$* -STDOUT=c${CONFIG_ID}_i${INSTANCE_ID}_s${SEED}.stdout -STDERR=c${CONFIG_ID}_i${INSTANCE_ID}_s${SEED}.stderr +# STDOUT=c${CONFIG_ID}_i${INSTANCE_ID}_s${SEED}.stdout +# STDERR=c${CONFIG_ID}_i${INSTANCE_ID}_s${SEED}.stderr +STDOUT="/dev/null" +STDERR="/dev/null" if [ ! -x "${EXE}" ]; then error "${EXE}: not found or not executable (pwd: $(pwd))" From ffafaa5b40ca65ff141660655634abfb3a8ab4ae Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 9 Oct 2020 16:39:18 +0200 Subject: [PATCH 40/42] better target-runner and run_irace.sh --- eo/contrib/irace/irace-config/target-runner | 5 +++-- eo/contrib/irace/run_irace.sh | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/eo/contrib/irace/irace-config/target-runner b/eo/contrib/irace/irace-config/target-runner index 9ca4f824a..6d6e39dd7 100755 --- a/eo/contrib/irace/irace-config/target-runner +++ b/eo/contrib/irace/irace-config/target-runner @@ -23,6 +23,7 @@ error() { EXE="./fastga" +LOG_DIR="irace_logs" FIXED_PARAMS="--problem=0" @@ -41,8 +42,8 @@ shift 11 || error "Not enough parameters" INSTANCE_PARAMS=$* -# STDOUT=c${CONFIG_ID}_i${INSTANCE_ID}_s${SEED}.stdout -# STDERR=c${CONFIG_ID}_i${INSTANCE_ID}_s${SEED}.stderr +# STDOUT=${LOG_DIR}/c${CONFIG_ID}_i${INSTANCE_ID}_s${SEED}.stdout +# STDERR=${LOG_DIR}/c${CONFIG_ID}_i${INSTANCE_ID}_s${SEED}.stderr STDOUT="/dev/null" STDERR="/dev/null" diff --git a/eo/contrib/irace/run_irace.sh b/eo/contrib/irace/run_irace.sh index 1f852b7f9..17c79e88d 100755 --- a/eo/contrib/irace/run_irace.sh +++ b/eo/contrib/irace/run_irace.sh @@ -15,5 +15,5 @@ cp ../irace-config/default.instances . # Generate the parameter list file. ./fastga -h > fastga.param 2>/dev/null -/usr/lib/R/site-library/irace/bin/irace --scenario example.scen +/usr/lib/R/site-library/irace/bin/irace --scenario example.scen 2>&1 | tee irace.log From 5cb7bfd3171bedcb79f8d938dfc805b2c4ca035d Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 9 Oct 2020 16:40:38 +0200 Subject: [PATCH 41/42] declutch restart in FastGA foundry --- eo/contrib/irace/fastga.cpp | 2 +- eo/src/eoAlgoFoundryFastGA.h | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/eo/contrib/irace/fastga.cpp b/eo/contrib/irace/fastga.cpp index cc67a43bd..919231eb7 100644 --- a/eo/contrib/irace/fastga.cpp +++ b/eo/contrib/irace/fastga.cpp @@ -24,7 +24,7 @@ eoAlgoFoundryFastGA& make_foundry( ) { // FIXME using max_restarts>1 does not allow to honor max evals. - auto& foundry = store.pack< eoAlgoFoundryFastGA >(init, eval_onemax, generations, max_evals, /*max_restarts=*/1); + auto& foundry = store.pack< eoAlgoFoundryFastGA >(init, eval_onemax, max_evals, /*max_restarts=*/1); /***** Continuators ****/ foundry.continuators.add< eoGenContinue >(generations); diff --git a/eo/src/eoAlgoFoundryFastGA.h b/eo/src/eoAlgoFoundryFastGA.h index 99b778f2a..ed766ff88 100644 --- a/eo/src/eoAlgoFoundryFastGA.h +++ b/eo/src/eoAlgoFoundryFastGA.h @@ -142,6 +142,7 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry // Objective function calls counter eoEvalCounterThrowException eval(_eval, _max_evals); + eo::log << eo::xdebug << "Evaluations: " << eval.value() << " / " << _max_evals << std::endl; eoPopLoopEval pop_eval(eval); // Algorithm itself @@ -160,12 +161,13 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry ); // Restart wrapper - eoAlgoPopReset reset_pop(_init, pop_eval); - eoGenContinue restart_cont(_max_restarts); - eoAlgoRestart restart(eval, algo, restart_cont, reset_pop); + // eoAlgoPopReset reset_pop(_init, pop_eval); + // eoGenContinue restart_cont(_max_restarts); + // eoAlgoRestart restart(eval, algo, restart_cont, reset_pop); try { - restart(pop); + // restart(pop); + algo(pop); } catch(eoMaxEvalException e) { #ifndef NDEBUG eo::log << eo::debug << "Reached maximum evaluations: " << eval.getValue() << " / " << _max_evals << std::endl; @@ -182,16 +184,16 @@ class eoAlgoFoundryFastGA : public eoAlgoFoundry std::string name() { std::ostringstream name; - name << "crossover_rates: " << this->at( crossover_rates.index()) << " (" << this-> crossover_rate() << ") + "; + name << "crossover_rates: " << this->at( crossover_rates.index()) << " (" << this-> crossover_rate() << ") + "; name << "crossover_selectors: " << this->at( crossover_selectors.index()) << " (" << this-> crossover_selector().className() << ") + "; name << "aftercross_selector: " << this->at(aftercross_selectors.index()) << " (" << this->aftercross_selector().className() << ") + "; - name << "crossovers: " << this->at( crossovers.index()) << " (" << this-> crossover().className() << ") + "; - name << "mutation_rates: " << this->at( mutation_rates.index()) << " (" << this-> mutation_rate() << ") + "; - name << "mutation_selectors: " << this->at( mutation_selectors.index()) << " (" << this-> mutation_selector().className() << ") + "; - name << "mutations: " << this->at( mutations.index()) << " (" << this-> mutation().className() << ") + "; - name << "replacements: " << this->at( replacements.index()) << " (" << this-> replacement().className() << ") + "; - name << "continuators: " << this->at( continuators.index()) << " (" << this-> continuator().className() << ") + "; - name << "offspring_sizes: " << this->at( offspring_sizes.index()) << " (" << this-> offspring_size() << ")"; + name << "crossovers: " << this->at( crossovers.index()) << " (" << this-> crossover().className() << ") + "; + name << "mutation_rates: " << this->at( mutation_rates.index()) << " (" << this-> mutation_rate() << ") + "; + name << "mutation_selectors: " << this->at( mutation_selectors.index()) << " (" << this-> mutation_selector().className() << ") + "; + name << "mutations: " << this->at( mutations.index()) << " (" << this-> mutation().className() << ") + "; + name << "replacements: " << this->at( replacements.index()) << " (" << this-> replacement().className() << ") + "; + name << "continuators: " << this->at( continuators.index()) << " (" << this-> continuator().className() << ") + "; + name << "offspring_sizes: " << this->at( offspring_sizes.index()) << " (" << this-> offspring_size() << ")"; return name.str(); } From a227e071f97e8a459a7d05270e486f32017ac58a Mon Sep 17 00:00:00 2001 From: nojhan Date: Fri, 9 Oct 2020 16:41:16 +0200 Subject: [PATCH 42/42] count eval after calling the objective function --- eo/src/eoEvalFuncCounter.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/eo/src/eoEvalFuncCounter.h b/eo/src/eoEvalFuncCounter.h index 0641250fa..a30e6e088 100644 --- a/eo/src/eoEvalFuncCounter.h +++ b/eo/src/eoEvalFuncCounter.h @@ -45,8 +45,9 @@ template class eoEvalFuncCounter : public eoEvalFunc, public eoV { if (_eo.invalid()) { - value()++; func(_eo); + value()++; + eo::log << eo::xdebug << "eoEvalFuncCounter: " << value() << std::endl; } }