change default function to be more in line with koza's description of a gp

thread
Brett 2024-07-15 18:18:13 -04:00
parent 2081dd3e5f
commit 34a3343a89
3 changed files with 47 additions and 39 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25)
project(blt-gp VERSION 0.0.80)
project(blt-gp VERSION 0.0.81)
include(CTest)

View File

@ -283,7 +283,7 @@ namespace blt::gp
* NOTE: 0 is considered the best, in terms of standardized fitness
*/
template<typename FitnessFunc>
void generate_population(type_id root_type, FitnessFunc& fitness_function)
void generate_population(type_id root_type, FitnessFunc& fitness_function, bool eval_fitness_now = true)
{
current_pop = config.pop_initializer.get().generate(
{*this, root_type, config.population_size, config.initial_min_tree_size, config.initial_max_tree_size});
@ -351,7 +351,8 @@ namespace blt::gp
});
thread_helper.thread_function_condition.notify_all();
}
evaluate_fitness_internal();
if (eval_fitness_now)
evaluate_fitness_internal();
}
void next_generation()

View File

@ -52,7 +52,7 @@ namespace blt::gp
{
for (blt::size_t i = 0; i < config.elites; i++)
{
// BLT_INFO("%lf >= %lf? // %lf", ind.second.fitness.adjusted_fitness, values[i].second, ind.second.fitness.raw_fitness);
//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;
@ -74,7 +74,7 @@ namespace blt::gp
};
template<typename Crossover, typename Mutation, typename Reproduction>
constexpr inline auto default_next_pop_creator = [](
constexpr inline auto proportionate_next_pop_creator = [](
const selector_args& args, Crossover crossover_selection, Mutation mutation_selection, Reproduction reproduction_selection) {
auto& [program, next_pop, current_pop, current_stats, config, random] = args;
@ -132,7 +132,7 @@ namespace blt::gp
};
template<typename Crossover, typename Mutation, typename Reproduction>
constexpr inline auto non_deterministic_next_pop_creator = [](
constexpr inline auto default_next_pop_creator = [](
const blt::gp::selector_args& args, Crossover crossover_selection, Mutation mutation_selection, Reproduction reproduction_selection) {
auto& [program, next_pop, current_pop, current_stats, config, random] = args;
@ -140,39 +140,46 @@ namespace blt::gp
while (next_pop.get_individuals().size() < config.population_size)
{
// everyone gets a chance once per loop.
if (random.choice(config.crossover_chance))
{
// crossover
auto& p1 = crossover_selection.select(program, current_pop, current_stats);
auto& p2 = crossover_selection.select(program, current_pop, current_stats);
auto results = config.crossover.get().apply(program, p1, p2);
// if crossover fails, we can check for mutation on these guys. otherwise straight copy them into the next pop
if (results)
{
next_pop.get_individuals().emplace_back(std::move(results->child1));
// annoying check
if (next_pop.get_individuals().size() < config.population_size)
next_pop.get_individuals().emplace_back(std::move(results->child2));
}
}
if (next_pop.get_individuals().size() >= config.population_size)
break;
if (random.choice(config.mutation_chance))
{
// mutation
auto& p = mutation_selection.select(program, current_pop, current_stats);
next_pop.get_individuals().emplace_back(std::move(config.mutator.get().apply(program, p)));
}
if (next_pop.get_individuals().size() >= config.population_size)
break;
if (config.reproduction_chance > 0 && random.choice(config.reproduction_chance))
{
// reproduction
auto& p = reproduction_selection.select(program, current_pop, current_stats);
next_pop.get_individuals().push_back(individual{p});
int sel = random.get_i32(0, 3);
switch (sel){
case 0:
// everyone gets a chance once per loop.
if (random.choice(config.crossover_chance))
{
// crossover
auto& p1 = crossover_selection.select(program, current_pop, current_stats);
auto& p2 = crossover_selection.select(program, current_pop, current_stats);
auto results = config.crossover.get().apply(program, p1, p2);
// if crossover fails, we can check for mutation on these guys. otherwise straight copy them into the next pop
if (results)
{
next_pop.get_individuals().emplace_back(std::move(results->child1));
// annoying check
if (next_pop.get_individuals().size() < config.population_size)
next_pop.get_individuals().emplace_back(std::move(results->child2));
}
}
break;
case 1:
if (random.choice(config.mutation_chance))
{
// mutation
auto& p = mutation_selection.select(program, current_pop, current_stats);
next_pop.get_individuals().emplace_back(std::move(config.mutator.get().apply(program, p)));
}
break;
case 2:
if (config.reproduction_chance > 0 && random.choice(config.reproduction_chance))
{
// reproduction
auto& p = reproduction_selection.select(program, current_pop, current_stats);
next_pop.get_individuals().push_back(individual{p});
}
break;
default:
BLT_ABORT("This is not possible!");
}
}
};