43 std::unique_ptr<Selection<GeneType>> selection_m;
44 std::unique_ptr<Mutation<GeneType>> mutation_m;
45 std::unique_ptr<Crossover<GeneType>> crossover_m;
46 std::unique_ptr<DemeReplacer<GeneType>> deme_replacer_m;
47 std::unique_ptr<DemeSelector<GeneType>> deme_selector_m;
49 std::unique_ptr<internal::MigrationBuffer<GeneType>> migration_buffer_m;
50 std::unique_ptr<internal::Communicator<GeneType>> communicator_m;
51 std::unique_ptr<const Topology> topology_m;
52 std::unique_ptr<internal::Serializer<GeneType>> serializer_m;
59 const std::size_t population_size = population.
size();
60 const int n_threads = (config_m.
num_threads > 0) ?
static_cast<int>(config_m.
num_threads) : omp_get_max_threads();
62 #pragma omp parallel for schedule(dynamic) num_threads(n_threads)
63 for (std::size_t i = 0; i < population_size; ++i) {
64 double score = fitness_function_m.
evaluate(population[i].getGenotype());
65 population[i].setFitness(score);
70 const std::size_t population_size = current_population.
size();
71 std::size_t elitism_offset = 0;
72 const int n_threads = (config_m.
num_threads > 0) ?
static_cast<int>(config_m.
num_threads) : omp_get_max_threads();
79 #pragma omp parallel for schedule(static) num_threads(n_threads)
80 for (std::size_t i = elitism_offset; i < population_size; i += 2) {
81 thread_local static std::random_device tl_rd;
82 thread_local static std::mt19937_64 tl_gen(tl_rd());
83 thread_local static std::uniform_real_distribution<double> tl_dist(0.0, 1.0);
89 auto children = crossover_m->crossover(parent1, parent2);
90 new_population[i] = std::move(children.first);
91 if (i + 1 < population_size) {
92 new_population[i + 1] = std::move(children.second);
95 new_population[i] = parent1;
96 if (i + 1 < population_size) {
97 new_population[i + 1] = parent2;
101 mutation_m->mutate(new_population[i], config_m.
mutation_rate);
102 if (i + 1 < population_size) {
103 mutation_m->mutate(new_population[i + 1], config_m.
mutation_rate);
108 void initializeCommunication() {
109 communicator_m->startReceiving(*migration_buffer_m);
112 void finalizeCommunication() {
113 communicator_m->stopReceiving();
117 communicator_m->update();
119 std::vector<Individual<GeneType>> incoming_migrants;
121 migration_buffer_m->popAll(incoming_migrants);
122 if (incoming_migrants.empty())
return;
124 const std::size_t max_immigrants =
static_cast<std::size_t
>(
128 if (incoming_migrants.size() > max_immigrants) {
129 std::ranges::nth_element(
131 incoming_migrants.begin() + max_immigrants,
135 incoming_migrants.resize(max_immigrants);
138 deme_replacer_m->replaceDeme(population, std::move(incoming_migrants));
141 void handleOutgoingMigrants(
const Population<GeneType>& population,
const std::size_t generation_idx) {
144 auto outgoing_migrants = deme_selector_m->selectDeme(population, config_m.
migration_size);
146 const std::vector<std::size_t> neighbors = topology_m->getLinks(communicator_m->getRank()).neighbors_out;
149 communicator_m->broadcast(outgoing_migrants, neighbors);
156 population[0] = std::move(global_best);
186 std::unique_ptr<const Topology> topology,
189 const bool elitism =
true
190 ) : fitness_function_m(ff),
191 selection_m(std::move(sel)),
192 mutation_m(std::move(mu)),
193 crossover_m(std::move(cs)),
194 deme_replacer_m(std::move(replacer)),
195 deme_selector_m(std::move(selector)),
196 migration_buffer_m(std::move(buffer)),
197 communicator_m(std::move(comm)),
198 topology_m(std::move(topology)),
199 serializer_m(std::move(serializer)),
201 use_elitism_m(elitism) {}
213 if (population.
empty()) {
return; }
215 const std::size_t population_size = population.
size();
216 const std::size_t num_genes = population.
getNumGenes();
220 evaluatePopulation(population);
222 initializeCommunication();
224 for (std::size_t generation_idx = 0; generation_idx < config_m.
max_generations; ++generation_idx) {
227 handleIncomingMigrants(population);
229 generateNextGeneration(population, new_population);
231 std::swap(population, new_population);
233 evaluatePopulation(population);
235 handleOutgoingMigrants(population, generation_idx);
240 finalizeCommunication();
242 synchronizeGlobalBest(population);
IslandGA(FitnessFunction< GeneType > &ff, std::unique_ptr< Selection< GeneType > > sel, std::unique_ptr< Mutation< GeneType > > mu, std::unique_ptr< Crossover< GeneType > > cs, std::unique_ptr< DemeReplacer< GeneType > > replacer, std::unique_ptr< DemeSelector< GeneType > > selector, std::unique_ptr< internal::MigrationBuffer< GeneType > > buffer, std::unique_ptr< internal::Communicator< GeneType > > comm, std::unique_ptr< const Topology > topology, std::unique_ptr< internal::Serializer< GeneType > > serializer, const IslandGAParams &config, const bool elitism=true)
Constructs an IslandGA instance.