add new selection, think there is a bug in elitsm
parent
fcd2d67852
commit
2081dd3e5f
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(blt-gp VERSION 0.0.79)
|
project(blt-gp VERSION 0.0.80)
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ namespace blt::gp
|
||||||
double crossover_chance = 0.8;
|
double crossover_chance = 0.8;
|
||||||
// percent chance that we will do mutation
|
// percent chance that we will do mutation
|
||||||
double mutation_chance = 0.1;
|
double mutation_chance = 0.1;
|
||||||
|
// percent chance we will do reproduction (copy individual)
|
||||||
|
double reproduction_chance = 0;
|
||||||
// everything else will just be selected
|
// everything else will just be selected
|
||||||
|
|
||||||
blt::size_t elites = 0;
|
blt::size_t elites = 0;
|
||||||
|
@ -52,7 +54,7 @@ namespace blt::gp
|
||||||
// number of elements each thread should pull per execution. this is for granularity performance and can be optimized for better results!
|
// number of elements each thread should pull per execution. this is for granularity performance and can be optimized for better results!
|
||||||
blt::size_t evaluation_size = 4;
|
blt::size_t evaluation_size = 4;
|
||||||
|
|
||||||
// default config (ramped half-and-half init) or for buildering
|
// default config (ramped half-and-half init) or for buildering
|
||||||
prog_config_t();
|
prog_config_t();
|
||||||
|
|
||||||
// default config with a user specified initializer
|
// default config with a user specified initializer
|
||||||
|
@ -143,6 +145,12 @@ namespace blt::gp
|
||||||
evaluation_size = s;
|
evaluation_size = s;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prog_config_t& set_reproduction_chance(double chance)
|
||||||
|
{
|
||||||
|
reproduction_chance = chance;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,8 @@ namespace blt::gp
|
||||||
mutation_selection.pre_process(*this, current_pop, current_stats);
|
mutation_selection.pre_process(*this, current_pop, current_stats);
|
||||||
reproduction_selection.pre_process(*this, current_pop, current_stats);
|
reproduction_selection.pre_process(*this, current_pop, current_stats);
|
||||||
|
|
||||||
func(get_selector_args(), std::forward<Crossover>(crossover_selection), std::forward<Mutation>(mutation_selection),
|
auto args = get_selector_args();
|
||||||
|
func(args, std::forward<Crossover>(crossover_selection), std::forward<Mutation>(mutation_selection),
|
||||||
std::forward<Reproduction>(reproduction_selection));
|
std::forward<Reproduction>(reproduction_selection));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,15 +38,9 @@ namespace blt::gp
|
||||||
random_t& random;
|
random_t& random;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Crossover, typename Mutation, typename Reproduction>
|
constexpr inline auto perform_elitism = [](const selector_args& args) {
|
||||||
constexpr inline auto default_next_pop_creator = [](
|
|
||||||
selector_args&& args, Crossover&& crossover_selection, Mutation&& mutation_selection, Reproduction&& reproduction_selection) {
|
|
||||||
auto& [program, next_pop, current_pop, current_stats, config, random] = args;
|
auto& [program, next_pop, current_pop, current_stats, config, random] = args;
|
||||||
|
|
||||||
double total_prob = config.mutation_chance + config.crossover_chance;
|
|
||||||
double crossover_chance = config.crossover_chance / total_prob;
|
|
||||||
double mutation_chance = crossover_chance + config.mutation_chance / total_prob;
|
|
||||||
|
|
||||||
if (config.elites > 0)
|
if (config.elites > 0)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<std::size_t, double>> values;
|
std::vector<std::pair<std::size_t, double>> values;
|
||||||
|
@ -77,6 +71,18 @@ namespace blt::gp
|
||||||
for (blt::size_t i = 0; i < config.elites; i++)
|
for (blt::size_t i = 0; i < config.elites; i++)
|
||||||
next_pop.get_individuals().push_back(current_pop.get_individuals()[values[i].first]);
|
next_pop.get_individuals().push_back(current_pop.get_individuals()[values[i].first]);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Crossover, typename Mutation, typename Reproduction>
|
||||||
|
constexpr inline auto default_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;
|
||||||
|
|
||||||
|
double total_prob = config.mutation_chance + config.crossover_chance;
|
||||||
|
double crossover_chance = config.crossover_chance / total_prob;
|
||||||
|
double mutation_chance = crossover_chance + config.mutation_chance / total_prob;
|
||||||
|
|
||||||
|
perform_elitism(args);
|
||||||
|
|
||||||
while (next_pop.get_individuals().size() < config.population_size)
|
while (next_pop.get_individuals().size() < config.population_size)
|
||||||
{
|
{
|
||||||
|
@ -125,6 +131,52 @@ namespace blt::gp
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Crossover, typename Mutation, typename Reproduction>
|
||||||
|
constexpr inline auto non_deterministic_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;
|
||||||
|
|
||||||
|
perform_elitism(args);
|
||||||
|
|
||||||
|
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});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class selection_t
|
class selection_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in New Issue