add new selection, think there is a bug in elitsm
parent
fcd2d67852
commit
2081dd3e5f
|
@ -1,5 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.25)
|
||||
project(blt-gp VERSION 0.0.79)
|
||||
project(blt-gp VERSION 0.0.80)
|
||||
|
||||
include(CTest)
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@ namespace blt::gp
|
|||
double crossover_chance = 0.8;
|
||||
// percent chance that we will do mutation
|
||||
double mutation_chance = 0.1;
|
||||
// percent chance we will do reproduction (copy individual)
|
||||
double reproduction_chance = 0;
|
||||
// everything else will just be selected
|
||||
|
||||
blt::size_t elites = 0;
|
||||
|
@ -51,8 +53,8 @@ namespace blt::gp
|
|||
blt::size_t threads = std::thread::hardware_concurrency();
|
||||
// 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;
|
||||
|
||||
// default config (ramped half-and-half init) or for buildering
|
||||
|
||||
// default config (ramped half-and-half init) or for buildering
|
||||
prog_config_t();
|
||||
|
||||
// default config with a user specified initializer
|
||||
|
@ -143,6 +145,12 @@ namespace blt::gp
|
|||
evaluation_size = s;
|
||||
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);
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -38,15 +38,9 @@ namespace blt::gp
|
|||
random_t& random;
|
||||
};
|
||||
|
||||
template<typename Crossover, typename Mutation, typename Reproduction>
|
||||
constexpr inline auto default_next_pop_creator = [](
|
||||
selector_args&& args, Crossover&& crossover_selection, Mutation&& mutation_selection, Reproduction&& reproduction_selection) {
|
||||
constexpr inline auto perform_elitism = [](const selector_args& 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)
|
||||
{
|
||||
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++)
|
||||
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)
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue