diff --git a/CMakeLists.txt b/CMakeLists.txt index cc8684f..8b8e8d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.0.59) +project(blt-gp VERSION 0.0.60) include(CTest) diff --git a/examples/gp_symbolic_regression_example.cpp b/examples/gp_symbolic_regression_example.cpp index 8751b1b..16803c6 100644 --- a/examples/gp_symbolic_regression_example.cpp +++ b/examples/gp_symbolic_regression_example.cpp @@ -110,7 +110,7 @@ int main() while (!program.should_terminate()) { - program.create_next_generation(blt::gp::select_fitness_proportionate_t{}, blt::gp::select_fitness_proportionate_t{}, blt::gp::select_fitness_proportionate_t{}); + program.create_next_generation(blt::gp::select_tournament_t{}, blt::gp::select_tournament_t{}, blt::gp::select_tournament_t{}); program.next_generation(); program.evaluate_fitness(); } @@ -125,6 +125,8 @@ int main() i.tree.print(program, std::cout); std::cout << "\n"; } + BLT_INFO(""); + // TODO: make stats helper return 0; } \ No newline at end of file diff --git a/include/blt/gp/selection.h b/include/blt/gp/selection.h index 46adcfc..6b4e4ea 100644 --- a/include/blt/gp/selection.h +++ b/include/blt/gp/selection.h @@ -58,8 +58,8 @@ namespace blt::gp { for (blt::size_t i = 0; i < config.elites; i++) { -// BLT_INFO("%lf < %lf? // %lf", ind.second.standardized_fitness, values[i].second, ind.second.raw_fitness); - if (ind.second.fitness.adjusted_fitness > values[i].second) +// BLT_INFO("%lf >= %lf? // %lf", ind.second.fitness.adjusted_fitness, values[i].second, ind.second.fitness.raw_fitness); + if (ind.second.fitness.adjusted_fitness >= values[i].second) { bool doesnt_contain = true; for (blt::size_t j = 0; j < config.elites; j++) @@ -76,8 +76,7 @@ namespace blt::gp for (blt::size_t i = 0; i < config.elites; i++) { -// BLT_DEBUG("%lf at %ld produces %lf", values[i].second, values[i].first, -// current_pop.get_individuals()[values[i].first].tree.get_evaluation_value(nullptr)); +// BLT_DEBUG("%lf at %ld", values[i].second, values[i].first); next_pop.get_individuals().push_back(current_pop.get_individuals()[values[i].first]); } } @@ -176,7 +175,7 @@ namespace blt::gp tree_t& select(gp_program& program, population_t& pop, population_stats& stats) final; private: - blt::size_t selection_size; + const blt::size_t selection_size; }; class select_fitness_proportionate_t : public selection_t @@ -185,8 +184,6 @@ namespace blt::gp void pre_process(gp_program& program, population_t& pop, population_stats& stats) final; tree_t& select(gp_program& program, population_t& pop, population_stats& stats) final; - private: - std::vector probabilities; }; } diff --git a/include/blt/gp/tree.h b/include/blt/gp/tree.h index 95730f6..452c1c5 100644 --- a/include/blt/gp/tree.h +++ b/include/blt/gp/tree.h @@ -150,6 +150,7 @@ namespace blt::gp // these will never be null unless your pop is not initialized / fitness eval was not called! individual* best_individual = nullptr; individual* worst_individual = nullptr; + std::vector normalized_fitness; }; class population_t diff --git a/src/selection.cpp b/src/selection.cpp index 9ac667c..779cb5e 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -77,29 +77,29 @@ namespace blt::gp return ind->tree; } - tree_t& select_fitness_proportionate_t::select(gp_program& program, population_t& pop, population_stats&) + tree_t& select_fitness_proportionate_t::select(gp_program& program, population_t& pop, population_stats& stats) { auto choice = program.get_random().get_double(); for (const auto& ind : blt::enumerate(pop)) { - if (ind.first == 0) + if (ind.first == 0 && choice <= stats.normalized_fitness[ind.first]) return ind.second.tree; - if (choice >= probabilities[ind.first] && choice >= probabilities[ind.first - 1]) + if (choice > stats.normalized_fitness[ind.first - 1] && choice <= stats.normalized_fitness[ind.first]) return ind.second.tree; } - BLT_WARN("Unable to find individual with fitness proportionate. This should not be a possible code path!"); + BLT_WARN("Unable to find individual with fitness proportionate. This should not be a possible code path! (%lf)", choice); return pop.get_individuals()[0].tree; //BLT_ABORT("Unable to find individual"); } void select_fitness_proportionate_t::pre_process(gp_program&, population_t& pop, population_stats& stats) { - probabilities.clear(); + stats.normalized_fitness.clear(); double sum_of_prob = 0; for (auto& ind : pop) { auto prob = (ind.fitness.adjusted_fitness / stats.overall_fitness); - probabilities.push_back(sum_of_prob + prob); + stats.normalized_fitness.push_back(sum_of_prob + prob); sum_of_prob += prob; } }