silly
parent
f983c0fb62
commit
46a22b520b
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(blt-gp VERSION 0.0.51)
|
project(blt-gp VERSION 0.0.52)
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
|
|
|
@ -108,13 +108,13 @@ int main()
|
||||||
|
|
||||||
blt::gp::crossover_t crossover;
|
blt::gp::crossover_t crossover;
|
||||||
|
|
||||||
auto& ind = pop.getIndividuals();
|
auto& ind = pop.get_individuals();
|
||||||
|
|
||||||
std::vector<float> pre;
|
std::vector<float> pre;
|
||||||
std::vector<float> pos;
|
std::vector<float> pos;
|
||||||
blt::size_t errors = 0;
|
blt::size_t errors = 0;
|
||||||
BLT_INFO("Pre-Crossover:");
|
BLT_INFO("Pre-Crossover:");
|
||||||
for (auto& tree : pop.getIndividuals())
|
for (auto& tree : pop.get_individuals())
|
||||||
{
|
{
|
||||||
auto f = tree.tree.get_evaluation_value<float>(nullptr);
|
auto f = tree.tree.get_evaluation_value<float>(nullptr);
|
||||||
pre.push_back(f);
|
pre.push_back(f);
|
||||||
|
@ -123,10 +123,10 @@ int main()
|
||||||
|
|
||||||
BLT_INFO("Crossover:");
|
BLT_INFO("Crossover:");
|
||||||
blt::gp::population_t new_pop;
|
blt::gp::population_t new_pop;
|
||||||
while (new_pop.getIndividuals().size() < pop.getIndividuals().size())
|
while (new_pop.get_individuals().size() < pop.get_individuals().size())
|
||||||
{
|
{
|
||||||
auto& random = program.get_random();
|
auto& random = program.get_random();
|
||||||
std::uniform_int_distribution dist(0ul, pop.getIndividuals().size() - 1);
|
std::uniform_int_distribution dist(0ul, pop.get_individuals().size() - 1);
|
||||||
blt::size_t first = dist(random);
|
blt::size_t first = dist(random);
|
||||||
blt::size_t second;
|
blt::size_t second;
|
||||||
do
|
do
|
||||||
|
@ -149,8 +149,8 @@ int main()
|
||||||
// results->child1.print(program, std::cout, print_literals, pretty_print, print_returns);
|
// results->child1.print(program, std::cout, print_literals, pretty_print, print_returns);
|
||||||
// BLT_TRACE("Child 2: %f", results->child2.get_evaluation_value<float>(nullptr));
|
// BLT_TRACE("Child 2: %f", results->child2.get_evaluation_value<float>(nullptr));
|
||||||
// results->child2.print(program, std::cout, print_literals, pretty_print, print_returns);
|
// results->child2.print(program, std::cout, print_literals, pretty_print, print_returns);
|
||||||
new_pop.getIndividuals().push_back({std::move(results->child1)});
|
new_pop.get_individuals().push_back({std::move(results->child1)});
|
||||||
new_pop.getIndividuals().push_back({std::move(results->child2)});
|
new_pop.get_individuals().push_back({std::move(results->child2)});
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
switch (results.error())
|
switch (results.error())
|
||||||
|
@ -163,8 +163,8 @@ int main()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
errors++;
|
errors++;
|
||||||
new_pop.getIndividuals().push_back(ind[first]);
|
new_pop.get_individuals().push_back(ind[first]);
|
||||||
new_pop.getIndividuals().push_back(ind[second]);
|
new_pop.get_individuals().push_back(ind[second]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ int main()
|
||||||
BLT_INFO("Mutation:");
|
BLT_INFO("Mutation:");
|
||||||
for (auto& tree : pop.for_each_tree())
|
for (auto& tree : pop.for_each_tree())
|
||||||
{
|
{
|
||||||
new_pop.getIndividuals().push_back({mutator.apply(program, generator, tree)});
|
new_pop.get_individuals().push_back({mutator.apply(program, generator, tree)});
|
||||||
}
|
}
|
||||||
BLT_INFO("Post-Mutation");
|
BLT_INFO("Post-Mutation");
|
||||||
for (auto& tree : new_pop.for_each_tree())
|
for (auto& tree : new_pop.for_each_tree())
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
static constexpr long SEED = 41912;
|
static constexpr long SEED = 41912;
|
||||||
|
|
||||||
|
|
||||||
blt::gp::type_provider type_system;
|
blt::gp::type_provider type_system;
|
||||||
blt::gp::gp_program program(type_system, std::mt19937_64{SEED}); // NOLINT
|
blt::gp::gp_program program(type_system, std::mt19937_64{SEED}); // NOLINT
|
||||||
|
|
||||||
|
@ -97,7 +96,7 @@ int main()
|
||||||
BLT_INFO("Mutation:");
|
BLT_INFO("Mutation:");
|
||||||
for (auto& tree : pop.for_each_tree())
|
for (auto& tree : pop.for_each_tree())
|
||||||
{
|
{
|
||||||
new_pop.getIndividuals().push_back({mutator.apply(program, generator, tree)});
|
new_pop.get_individuals().push_back({mutator.apply(program, generator, tree)});
|
||||||
}
|
}
|
||||||
BLT_INFO("Post-Mutation");
|
BLT_INFO("Post-Mutation");
|
||||||
for (auto& tree : new_pop.for_each_tree())
|
for (auto& tree : new_pop.for_each_tree())
|
||||||
|
|
|
@ -319,10 +319,10 @@ namespace blt::gp
|
||||||
template<typename Return, typename Class, typename Container, typename Lambda = Return(Class::*)(tree_t, Container, blt::size_t) const>
|
template<typename Return, typename Class, typename Container, typename Lambda = Return(Class::*)(tree_t, Container, blt::size_t) const>
|
||||||
void evaluate_fitness(Lambda&& fitness_function, Container& result_storage)
|
void evaluate_fitness(Lambda&& fitness_function, Container& result_storage)
|
||||||
{
|
{
|
||||||
for (const auto& ind : blt::enumerate(current_pop.getIndividuals()))
|
for (const auto& ind : blt::enumerate(current_pop.get_individuals()))
|
||||||
ind.second.raw_fitness = static_cast<double>(fitness_function(ind.second.tree, result_storage, ind.first));
|
ind.second.raw_fitness = static_cast<double>(fitness_function(ind.second.tree, result_storage, ind.first));
|
||||||
double min = 0;
|
double min = 0;
|
||||||
for (auto& ind : current_pop.getIndividuals())
|
for (auto& ind : current_pop.get_individuals())
|
||||||
{
|
{
|
||||||
if (ind.raw_fitness < min)
|
if (ind.raw_fitness < min)
|
||||||
min = ind.raw_fitness;
|
min = ind.raw_fitness;
|
||||||
|
@ -335,10 +335,10 @@ namespace blt::gp
|
||||||
individual* worst = nullptr;
|
individual* worst = nullptr;
|
||||||
|
|
||||||
auto diff = -min;
|
auto diff = -min;
|
||||||
for (auto& ind : current_pop.getIndividuals())
|
for (auto& ind : current_pop.get_individuals())
|
||||||
{
|
{
|
||||||
ind.standardized_fitness = ind.raw_fitness + diff;
|
auto standardized_fitness = ind.raw_fitness + diff;
|
||||||
ind.adjusted_fitness = 1.0 / (1.0 + ind.standardized_fitness);
|
ind.adjusted_fitness = 1.0 / (1.0 + standardized_fitness);
|
||||||
|
|
||||||
if (ind.adjusted_fitness > worst_fitness)
|
if (ind.adjusted_fitness > worst_fitness)
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,6 +37,9 @@ namespace blt::gp
|
||||||
*/
|
*/
|
||||||
virtual tree_t& select(gp_program& program, population_t& pop, population_stats& stats) = 0;
|
virtual tree_t& select(gp_program& program, population_t& pop, population_stats& stats) = 0;
|
||||||
|
|
||||||
|
virtual void pre_process(gp_program&, population_t&, population_stats&)
|
||||||
|
{}
|
||||||
|
|
||||||
virtual ~selection_t() = default;
|
virtual ~selection_t() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,6 +79,8 @@ namespace blt::gp
|
||||||
class select_fitness_proportionate_t : public selection_t
|
class select_fitness_proportionate_t : public selection_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
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;
|
tree_t& select(gp_program& program, population_t& pop, population_stats& stats) final;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -114,8 +114,8 @@ namespace blt::gp
|
||||||
{
|
{
|
||||||
tree_t tree;
|
tree_t tree;
|
||||||
double raw_fitness = 0;
|
double raw_fitness = 0;
|
||||||
double standardized_fitness = 0;
|
|
||||||
double adjusted_fitness = 0;
|
double adjusted_fitness = 0;
|
||||||
|
double probability = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct population_stats
|
struct population_stats
|
||||||
|
@ -184,7 +184,7 @@ namespace blt::gp
|
||||||
blt::size_t pos;
|
blt::size_t pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<individual>& getIndividuals()
|
std::vector<individual>& get_individuals()
|
||||||
{
|
{
|
||||||
return individuals;
|
return individuals;
|
||||||
}
|
}
|
||||||
|
@ -193,6 +193,26 @@ namespace blt::gp
|
||||||
{
|
{
|
||||||
return population_tree_iterator{individuals, 0};
|
return population_tree_iterator{individuals, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto begin()
|
||||||
|
{
|
||||||
|
return individuals.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto end()
|
||||||
|
{
|
||||||
|
return individuals.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto begin() const
|
||||||
|
{
|
||||||
|
return individuals.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto end() const
|
||||||
|
{
|
||||||
|
return individuals.end();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<individual> individuals;
|
std::vector<individual> individuals;
|
||||||
|
|
|
@ -120,7 +120,7 @@ namespace blt::gp
|
||||||
population_t pop;
|
population_t pop;
|
||||||
|
|
||||||
for (auto i = 0ul; i < args.size; i++)
|
for (auto i = 0ul; i < args.size; i++)
|
||||||
pop.getIndividuals().push_back({grow.generate(args.to_gen_args())});
|
pop.get_individuals().push_back({grow.generate(args.to_gen_args())});
|
||||||
|
|
||||||
return pop;
|
return pop;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ namespace blt::gp
|
||||||
population_t pop;
|
population_t pop;
|
||||||
|
|
||||||
for (auto i = 0ul; i < args.size; i++)
|
for (auto i = 0ul; i < args.size; i++)
|
||||||
pop.getIndividuals().push_back({full.generate(args.to_gen_args())});
|
pop.get_individuals().push_back({full.generate(args.to_gen_args())});
|
||||||
|
|
||||||
return pop;
|
return pop;
|
||||||
}
|
}
|
||||||
|
@ -142,9 +142,9 @@ namespace blt::gp
|
||||||
for (auto i = 0ul; i < args.size; i++)
|
for (auto i = 0ul; i < args.size; i++)
|
||||||
{
|
{
|
||||||
if (args.program.choice())
|
if (args.program.choice())
|
||||||
pop.getIndividuals().push_back({full.generate(args.to_gen_args())});
|
pop.get_individuals().push_back({full.generate(args.to_gen_args())});
|
||||||
else
|
else
|
||||||
pop.getIndividuals().push_back({grow.generate(args.to_gen_args())});
|
pop.get_individuals().push_back({grow.generate(args.to_gen_args())});
|
||||||
}
|
}
|
||||||
|
|
||||||
return pop;
|
return pop;
|
||||||
|
@ -162,21 +162,21 @@ namespace blt::gp
|
||||||
for (auto i = 0ul; i < per_step; i++)
|
for (auto i = 0ul; i < per_step; i++)
|
||||||
{
|
{
|
||||||
if (args.program.choice())
|
if (args.program.choice())
|
||||||
pop.getIndividuals().push_back({full.generate({args.program, args.root_type, args.min_depth, depth})});
|
pop.get_individuals().push_back({full.generate({args.program, args.root_type, args.min_depth, depth})});
|
||||||
else
|
else
|
||||||
pop.getIndividuals().push_back({grow.generate({args.program, args.root_type, args.min_depth, depth})});
|
pop.get_individuals().push_back({grow.generate({args.program, args.root_type, args.min_depth, depth})});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto i = 0ul; i < remainder; i++)
|
for (auto i = 0ul; i < remainder; i++)
|
||||||
{
|
{
|
||||||
if (args.program.choice())
|
if (args.program.choice())
|
||||||
pop.getIndividuals().push_back({full.generate(args.to_gen_args())});
|
pop.get_individuals().push_back({full.generate(args.to_gen_args())});
|
||||||
else
|
else
|
||||||
pop.getIndividuals().push_back({grow.generate(args.to_gen_args())});
|
pop.get_individuals().push_back({grow.generate(args.to_gen_args())});
|
||||||
}
|
}
|
||||||
|
|
||||||
blt_assert(pop.getIndividuals().size() == args.size);
|
blt_assert(pop.get_individuals().size() == args.size);
|
||||||
|
|
||||||
return pop;
|
return pop;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
|
|
||||||
tree_t& select_best_t::select(gp_program&, population_t& pop, population_stats& stats)
|
tree_t& select_best_t::select(gp_program&, population_t& pop, population_stats&)
|
||||||
{
|
{
|
||||||
auto& first = pop.getIndividuals()[0];
|
auto& first = pop.get_individuals()[0];
|
||||||
double best_fitness = first.adjusted_fitness;
|
double best_fitness = first.adjusted_fitness;
|
||||||
tree_t* tree = &first.tree;
|
tree_t* tree = &first.tree;
|
||||||
for (auto& ind : pop.getIndividuals())
|
for (auto& ind : pop.get_individuals())
|
||||||
{
|
{
|
||||||
if (ind.adjusted_fitness < best_fitness)
|
if (ind.adjusted_fitness < best_fitness)
|
||||||
{
|
{
|
||||||
|
@ -37,12 +37,12 @@ namespace blt::gp
|
||||||
return *tree;
|
return *tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_t& select_worst_t::select(gp_program&, population_t& pop, population_stats& stats)
|
tree_t& select_worst_t::select(gp_program&, population_t& pop, population_stats&)
|
||||||
{
|
{
|
||||||
auto& first = pop.getIndividuals()[0];
|
auto& first = pop.get_individuals()[0];
|
||||||
double worst_fitness = first.adjusted_fitness;
|
double worst_fitness = first.adjusted_fitness;
|
||||||
tree_t* tree = &first.tree;
|
tree_t* tree = &first.tree;
|
||||||
for (auto& ind : pop.getIndividuals())
|
for (auto& ind : pop.get_individuals())
|
||||||
{
|
{
|
||||||
if (ind.adjusted_fitness > worst_fitness)
|
if (ind.adjusted_fitness > worst_fitness)
|
||||||
{
|
{
|
||||||
|
@ -53,23 +53,23 @@ namespace blt::gp
|
||||||
return *tree;
|
return *tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_t& select_random_t::select(gp_program& program, population_t& pop, population_stats& stats)
|
tree_t& select_random_t::select(gp_program& program, population_t& pop, population_stats&)
|
||||||
{
|
{
|
||||||
// TODO: use a more generic randomness solution.
|
// TODO: use a more generic randomness solution.
|
||||||
std::uniform_int_distribution dist(0ul, pop.getIndividuals().size());
|
std::uniform_int_distribution dist(0ul, pop.get_individuals().size());
|
||||||
return pop.getIndividuals()[dist(program.get_random())].tree;
|
return pop.get_individuals()[dist(program.get_random())].tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_t& select_tournament_t::select(gp_program& program, population_t& pop, population_stats& stats)
|
tree_t& select_tournament_t::select(gp_program& program, population_t& pop, population_stats&)
|
||||||
{
|
{
|
||||||
std::uniform_int_distribution dist(0ul, pop.getIndividuals().size());
|
std::uniform_int_distribution dist(0ul, pop.get_individuals().size());
|
||||||
|
|
||||||
auto& first = pop.getIndividuals()[dist(program.get_random())];
|
auto& first = pop.get_individuals()[dist(program.get_random())];
|
||||||
individual* ind = &first;
|
individual* ind = &first;
|
||||||
double best_guy = first.adjusted_fitness;
|
double best_guy = first.adjusted_fitness;
|
||||||
for (blt::size_t i = 0; i < selection_size - 1; i++)
|
for (blt::size_t i = 0; i < selection_size - 1; i++)
|
||||||
{
|
{
|
||||||
auto& sel = pop.getIndividuals()[dist(program.get_random())];
|
auto& sel = pop.get_individuals()[dist(program.get_random())];
|
||||||
if (sel.adjusted_fitness < best_guy)
|
if (sel.adjusted_fitness < best_guy)
|
||||||
{
|
{
|
||||||
best_guy = sel.adjusted_fitness;
|
best_guy = sel.adjusted_fitness;
|
||||||
|
@ -80,9 +80,29 @@ namespace blt::gp
|
||||||
return ind->tree;
|
return ind->tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.google.com/search?client=firefox-b-d&sca_esv=71668abf73626b35&sca_upv=1&biw=1916&bih=940&sxsrf=ADLYWIJehgPtkALJDoTgHCiO4GNeQppSeA:1720490607140&q=roulette+wheel+selection+pseudocode&uds=ADvngMgiq8uozSRb4WPAa_ESRaBJz-G_Xhk1OLU3QFjqc3o31P4ECuIkKJxHd-cR3WUe9U7VQGpI6NRaMgYiWTMd4wNofAAaNq6X4eHYpN8cR9HmTfTw0KgYC6gI4dgu-s-5mXivdsv4QxrkVAL7yMoXacJngsiMBg&udm=2&sa=X&ved=2ahUKEwig7Oj77piHAxU3D1kFHS1lAIsQxKsJegQIDBAB&ictx=0#vhid=6iCOymnPvtyy-M&vssid=mosaic
|
|
||||||
tree_t& select_fitness_proportionate_t::select(gp_program& program, population_t& pop, population_stats& stats)
|
tree_t& select_fitness_proportionate_t::select(gp_program& program, population_t& pop, population_stats& stats)
|
||||||
{
|
{
|
||||||
|
static std::uniform_real_distribution dist(0.0, 1.0);
|
||||||
|
auto choice = dist(program.get_random());
|
||||||
|
for (const auto& ind : blt::enumerate(pop))
|
||||||
|
{
|
||||||
|
if (ind.first == pop.get_individuals().size()-1)
|
||||||
|
return ind.second.tree;
|
||||||
|
if (choice > ind.second.probability && pop.get_individuals()[ind.first+1].probability < choice)
|
||||||
|
return ind.second.tree;
|
||||||
|
}
|
||||||
|
BLT_WARN("Unable to find individual with fitness proportionate. This should not be a possible code path!");
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
double sum_of_prob = 0;
|
||||||
|
for (auto& ind : pop)
|
||||||
|
{
|
||||||
|
ind.probability = sum_of_prob + (ind.adjusted_fitness / stats.overall_fitness);
|
||||||
|
sum_of_prob += ind.probability;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue