pulsatrix
Loading...
Searching...
No Matches
evolutionary_loop.hpp
Go to the documentation of this file.
1
20#pragma once
21
22#include <future>
23#include <utility>
24#include <vector>
25
28
29namespace pulsatrix {
30
39template <typename Genotype, typename FitnessT, typename FitnessFn>
41 FitnessFn& fitness_fn, DataThreadPool* thread_pool) {
42 if (thread_pool == nullptr) {
43 for (auto& ind : population) {
44 ind.fitness = fitness_fn(ind.genes);
45 }
46 return;
47 }
48
49 std::vector<std::future<FitnessT>> futures;
50 futures.reserve(population.size());
51 for (auto& ind : population) {
52 Genotype genes_copy = ind.genes; // copied into the task -- avoids a dangling
53 // reference to population while other threads run
54 futures.push_back(
55 thread_pool->submit([&fitness_fn, genes_copy]() { return fitness_fn(genes_copy); }));
56 }
57 for (size_t i = 0; i < population.size(); ++i) {
58 population[i].fitness = futures[i].get();
59 }
60}
61
79template <typename Genotype, typename FitnessT, typename FitnessFn, typename OffspringFn,
80 typename SurvivorFn>
81std::vector<Individual<Genotype, FitnessT>> RunEvolutionaryLoop(
82 std::vector<Individual<Genotype, FitnessT>> population, size_t num_generations,
83 size_t lambda_size, FitnessFn fitness_fn, OffspringFn produce_offspring_genotype,
84 SurvivorFn survivor_selector, DataThreadPool* thread_pool = nullptr) {
85 const size_t mu = population.size();
86 EvaluatePopulation(population, fitness_fn, thread_pool);
87
88 for (size_t generation = 0; generation < num_generations; ++generation) {
89 std::vector<Individual<Genotype, FitnessT>> offspring;
90 offspring.reserve(lambda_size);
91 for (size_t i = 0; i < lambda_size; ++i) {
92 offspring.push_back(Individual<Genotype, FitnessT>{produce_offspring_genotype(population),
93 FitnessT{}});
94 }
95 EvaluatePopulation(offspring, fitness_fn, thread_pool);
96 population = survivor_selector(population, std::move(offspring), mu);
97 }
98 return population;
99}
100
101} // namespace pulsatrix
Minimal, generic thread pool for CPU-side data pipeline work (fetch, decode, transform,...
Definition data_thread_pool.hpp:29
auto submit(F &&task) -> std::future< std::invoke_result_t< F > >
Enqueues a task for execution by a worker thread.
Definition data_thread_pool.hpp:45
Minimal generic thread pool for CPU-side data pipeline work.
A genetic-algorithm candidate solution: a genotype paired with its fitness.
Definition acquisition_functions.hpp:16
std::vector< Individual< Genotype, FitnessT > > RunEvolutionaryLoop(std::vector< Individual< Genotype, FitnessT > > population, size_t num_generations, size_t lambda_size, FitnessFn fitness_fn, OffspringFn produce_offspring_genotype, SurvivorFn survivor_selector, DataThreadPool *thread_pool=nullptr)
Runs num_generations of the shared evolutionary-loop skeleton: evaluate -> produce lambda_size offspr...
Definition evolutionary_loop.hpp:81
void EvaluatePopulation(std::vector< Individual< Genotype, FitnessT > > &population, FitnessFn &fitness_fn, DataThreadPool *thread_pool)
Evaluates (or re-evaluates) every individual's fitness in place via fitness_fn.
Definition evolutionary_loop.hpp:40
A single candidate solution in a genetic algorithm population.
Definition individual.hpp:25