56 if (
params.num_islands < 0) {
60 if (
static_cast<size_t>(
params.num_islands) >
pop.island_indexes.size()) {
62 "params.num_islands is greater than pop.island_indexes size in calculate_stats");
65 for (
int island=0; island<
params.num_islands; ++island)
67 auto indices =
pop.island_indexes.at(island);
68 pop_size += indices.size();
71 ArrayXf scores(pop_size);
72 ArrayXf scores_v(pop_size);
81 for (
int island=0; island<
params.num_islands; ++island)
83 auto indices =
pop.island_indexes.at(island);
84 for (
unsigned int i=0; i<indices.size(); ++i)
86 const size_t population_index = indices[i];
87 if (population_index >= this->
pop.individuals.size()) {
89 "Invalid population index in island " +
to_string(island)
91 +
" (individuals size=" +
to_string(this->
pop.individuals.size()) +
")");
94 const auto& p = this->
pop.individuals.at(population_index);
100 float fitness_loss = 0.0f;
101 float fitness_loss_v = 0.0f;
102 unsigned individual_size = 0;
103 unsigned individual_complexity = 0;
105 fitness_loss = p->fitness.get_loss();
106 fitness_loss_v = p->fitness.get_loss_v();
107 individual_size = p->get_size();
108 individual_complexity = p->get_complexity();
109 }
catch (
const std::exception& e) {
111 "Failed to get fitness/size/complexity from individual at population index "
112 +
to_string(population_index) +
": " + e.what());
115 "Failed to get fitness/size/complexity from individual at population index "
116 +
to_string(population_index) +
": unknown error");
119 if (!std::isfinite(fitness_loss) || !std::isfinite(fitness_loss_v)) {
121 "Invalid non-finite fitness values at population index "
130 scores(index) = fitness_loss;
131 scores_v(index) = fitness_loss_v;
132 sizes(index) = individual_size;
133 complexities(index) = individual_complexity;
140 scores.conservativeResize(index);
141 scores_v.conservativeResize(index);
142 sizes.conservativeResize(index);
143 complexities.conservativeResize(index);
147 float best_score = index > 0 ? (scores*error_weight).maxCoeff()*error_weight : 0.0f;
148 float best_score_v = this->
best_ind.fitness.get_loss_v();
150 if (!std::isfinite(best_score_v)) {
151 HANDLE_ERROR_THROW(
"Invalid non-finite validation loss in best_ind while calculating stats");
154 float med_score = index > 0 ?
median(scores) : 0.0f;
155 float med_score_v = index > 0 ?
median(scores_v) : 0.0f;
156 unsigned med_size = index > 0 ?
median(sizes) : 0;
157 unsigned med_complexity = index > 0 ?
median(complexities) : 0;
158 unsigned max_size = index > 0 ? sizes.maxCoeff() : 0;
159 unsigned max_complexity = index > 0 ? complexities.maxCoeff() : 0;
163 timer.Elapsed().count(),
372 bool updated =
false;
375 vector<size_t> merged_islands(0);
376 for (
int j=0;j<
pop.num_islands; ++j)
378 auto indices =
pop.island_indexes.at(j);
379 for (
int i=0; i<indices.size(); ++i)
381 merged_islands.push_back(indices.at(i));
385 for (
int i=0; i < merged_islands.size(); ++i)
387 const auto& ind_ptr =
pop.individuals.at(merged_islands[i]);
393 const auto& ind = *ind_ptr;
398 for (
size_t j = 0; j < ind.fitness.get_wvalues().size(); ++j) {
399 if (ind.fitness.get_wvalues()[j] > this->best_ind.fitness.get_wvalues()[j]) {
403 if (ind.fitness.get_wvalues()[j] < this->best_ind.fitness.get_wvalues()[j]) {
435 if (
params.load_population !=
"") {
438 else if (this->
pop.individuals.size() == 0)
460 if (!
params.logfile.empty()) {
461 log.open(
params.logfile, std::ofstream::app);
462 if (!log.is_open()) {
473 threads = std::thread::hardware_concurrency();
474 else if (
params.n_jobs == 0)
475 threads =
params.num_islands;
479 tf::Executor executor(threads);
481 assert( (executor.num_workers() > 0) &&
"Invalid number of workers");
483 tf::Taskflow taskflow;
486 unsigned generation = 0;
487 unsigned stall_count = 0;
491 bool condition = ( (generation ==
params.max_gens)
492 || (
params.max_stall != 0 && stall_count >
params.max_stall)
501 vector<vector<size_t>> island_parents;
503 island_parents.clear();
504 island_parents.resize(
pop.num_islands);
506 for (
int i=0; i<
params.num_islands; i++){
507 size_t idx_start = std::floor(i*
params.pop_size/
params.num_islands);
508 size_t idx_end = std::floor((i+1)*
params.pop_size/
params.num_islands);
510 auto delta = idx_end - idx_start;
512 island_parents.at(i).clear();
513 island_parents.at(i).resize(
delta);
517 auto [
init, cond, body, back, done] = taskflow.emplace(
518 [&](tf::Subflow& subflow) {
522 auto fit_init_pop = subflow.emplace([&]() {
523 for (
int island = 0; island < this->
params.num_islands; ++island) {
529 auto find_init_best = subflow.emplace([&]() {
537 fit_init_pop.precede(find_init_best);
542 [&](tf::Subflow& subflow) {
543 auto prepare_gen = subflow.emplace([&]() {
544 params.set_current_gen(generation);
546 }).name(
"prepare generation");
553 auto run_generation = subflow.emplace([&]() {
554 for (
int island = 0; island < this->
params.num_islands; ++island) {
564 for (
int i=0; i< parents.size(); i++){
565 island_parents.at(island).at(i) = parents.at(i);
568 this->
pop.add_offspring_indexes(island);
570 }).name(
"runs one generation at each island in deterministic order");
572 auto update_pop = subflow.emplace([&]() {
575 for (
int island = 0; island < this->
params.num_islands; ++island) {
586 (generation>=
params.max_gens/2) || (stall_count ==
params.max_stall) || (generation==
params.max_gens-1)
600 this->
pop.update({survivor_indices});
602 }).name(
"update, migrate and disentangle indexes between islands");
604 auto finish_gen = subflow.emplace([&]() {
606 for (
int island = 0; island < this->
params.num_islands; ++island) {
616 fraction =
params.max_time == -1 ? ((generation+1)*1.0)/
params.max_gens :
625 else if(
params.verbosity == 1)
628 if (!
params.logfile.empty() && log.is_open())
631 if (generation == 0 || updated_best )
638 }).name(
"update best, update ss, log, archive, stall");
641 prepare_gen.precede(run_generation);
642 run_generation.precede(update_pop);
643 update_pop.precede(finish_gen);
648 [&](tf::Subflow& subflow) {
650 for (
int island = 0; island < this->
params.num_islands; ++island) {
657 if (
params.save_population !=
"")
663 if (!
params.logfile.empty() &&
params.inexact_simplification) {
664 std::ofstream log_simplification;
665 log_simplification.open(
params.logfile+
"_simplification_table", std::ofstream::app);
668 log_simplification.close();
683 cond.name(
"termination");
684 body.name(
"main loop");
687 taskflow.name(
"island_gp");
690 cond.precede(body, done);
694 executor.run(taskflow);
695 executor.wait_for_all();
void vary_and_update(Population< T > &pop, int island, const vector< size_t > &parents, const Dataset &data, Evaluation< T > &evaluator, bool do_simplification)
Varies a population and updates the selection strategy based on rewards.