#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); } /***** 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) { 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 *****/ 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 >(); 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; } 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"; if(slot_size -1 <= 0) { out << "\t(0)"; } else { out << "\t(0," << slot_size-1 << ")"; } out << std::endl; } int main(int argc, char* argv[]) { /***** Global parameters. *****/ enum { NO_ERROR = 0, ERROR_USAGE = 100 }; eoFunctorStore store; 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", "Stopping criterion", 'o', "Operator Choice", /*required=*/true); const size_t continuator = continuator_p.value(); auto crossover_rate_p = parser.getORcreateParam(0, "crossover-rate", "", 'C', "Operator Choice", /*required=*/true); const size_t crossover_rate = crossover_rate_p.value(); auto crossover_selector_p = parser.getORcreateParam(0, "cross-selector", "How to selects candidates for cross-over", 's', "Operator Choice", /*required=*/true); const size_t crossover_selector = crossover_selector_p.value(); auto crossover_p = parser.getORcreateParam(0, "crossover", "", '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', "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', "Operator Choice", /*required=*/true); const size_t mutation = mutation_p.value(); auto replacement_p = parser.getORcreateParam(0, "replacement", "", '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); if(parser.userNeedsHelp()) { // 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); 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 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_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; exit(NO_ERROR); } const size_t generations = static_cast(std::floor( static_cast(max_evals) / static_cast(pop_size))); /***** 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(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); 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 << foundry.name() << 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 long perf = ecdf_sum(logger.data()); // Output std::cout << -1 * perf << std::endl; assert(0 < perf and perf <= buckets*buckets); }