1#ifndef ALGORITHM_BUILDER_H
2#define ALGORITHM_BUILDER_H
8#include <yaml-cpp/yaml.h>
53 template <
typename GeneType>
57 static constexpr double MUTATION_RATE = 0.05;
58 static constexpr double CROSSOVER_RATE = 0.8;
59 static constexpr std::size_t MAX_GENERATIONS = 100;
60 static constexpr bool USE_ELITISM =
true;
61 static constexpr std::size_t THREADS = 1;
68 static constexpr std::size_t
ROWS = 10;
69 static constexpr std::size_t
COLS = 10;
84 static constexpr const char*
TOPOLOGY =
"fully_connected";
102 static std::unique_ptr<Algorithm<GeneType>>
build(
103 const std::string& config_path,
105 MPI_Comm mpi_comm = MPI_COMM_NULL
108 static std::unique_ptr<Algorithm<GeneType>>
build(
109 const std::string& config_path,
113 YAML::Node full_config = YAML::LoadFile(config_path);
114 const auto node = full_config[
"algorithm"];
116 throw std::invalid_argument(
"Missing 'algorithm' section in config: " + config_path);
119 const auto type = node[
"type"].as<std::string>(
"standard");
120 std::unique_ptr<Algorithm<GeneType>> algo;
122 if (type ==
"standard") {
124 }
else if (type ==
"cellular") {
126 }
else if (type ==
"differential_evolution") {
128 }
else if (type ==
"island") {
132 throw std::runtime_error(
"Island GA requested but library was built without MPI support.");
135 throw std::invalid_argument(
"Unknown algorithm type: " + type);
139 if (full_config[
"output"]) {
140 const auto out = full_config[
"output"];
143 if (out[
"console"] && out[
"console"][
"enabled"].as<bool>(
false)) {
144 auto interval = out[
"console"][
"interval"].as<std::size_t>(1);
145 algo->enableConsoleLogging(interval);
149 if (out[
"file"] && out[
"file"][
"enabled"].as<bool>(
false)) {
150 auto path = out[
"file"][
"path"].as<std::string>(
"evolution.csv");
151 auto interval = out[
"file"][
"interval"].as<std::size_t>(1);
152 algo->enableFileLogging(path, interval);
166 const YAML::Node& config,
169 const auto node = config[
"algorithm"];
171 params.
mutation_rate = node[
"mutation_rate"].as<
double>(Defaults::MUTATION_RATE);
172 params.
crossover_rate = node[
"crossover_rate"].as<
double>(Defaults::CROSSOVER_RATE);
173 params.
max_generations = node[
"max_generations"].as<std::size_t>(Defaults::MAX_GENERATIONS);
174 params.
use_elitism = node[
"use_elitism"].as<
bool>(Defaults::USE_ELITISM);
175 params.
threads = node[
"threads"].as<std::size_t>(Defaults::THREADS);
178 if (node[
"standard"]) {
186#ifdef GALIB_WITH_CUDA
188 return std::make_unique<cuda::StandardGACUDA<GeneType>>(
190 std::move(selection),
192 std::move(crossover),
201 std::cerr <<
"[GALib] Warning: use_cuda=true but library was built without CUDA support."
202 " Falling back to StandardGA (CPU).\n";
206 return std::make_unique<StandardGA<GeneType>>(
208 std::move(selection),
210 std::move(crossover),
226 const YAML::Node& config,
229 const auto node = config[
"algorithm"];
231 params.
mutation_rate = node[
"mutation_rate"].as<
double>(Defaults::MUTATION_RATE);
232 params.
crossover_rate = node[
"crossover_rate"].as<
double>(Defaults::CROSSOVER_RATE);
233 params.
max_generations = node[
"max_generations"].as<std::size_t>(Defaults::MAX_GENERATIONS);
234 params.
threads = node[
"threads"].as<std::size_t>(Defaults::THREADS);
236 if (node[
"cellular"]) {
244 return std::make_unique<CellularGA<GeneType>>(
246 std::move(selection),
248 std::move(crossover),
264 const YAML::Node& config,
267 const auto node = config[
"algorithm"];
270 params.
max_generations = node[
"max_generations"].as<std::size_t>(Defaults::MAX_GENERATIONS);
271 params.
threads = node[
"threads"].as<std::size_t>(Defaults::THREADS);
273 if (node[
"differential_evolution"]) {
277 return std::make_unique<DifferentialEvolutionGA<GeneType>>(
295 const YAML::Node& config,
299 const auto node = config[
"algorithm"];
302 island_config.
mutation_rate = node[
"mutation_rate"].as<
double>(Defaults::MUTATION_RATE);
303 island_config.
crossover_rate = node[
"crossover_rate"].as<
double>(Defaults::CROSSOVER_RATE);
304 island_config.
num_threads = node[
"threads"].as<std::size_t>(0);
309 if (node[
"island"]) {
310 island_config.
migration_interval = node[
"island"][
"migration_interval"].as<std::size_t>(
322 std::unique_ptr<DemeReplacer<GeneType>> replacer;
323 if (node[
"island"] && node[
"island"][
"replacer"]) {
326 replacer = std::make_unique<WorstReplacer<GeneType>>();
329 std::unique_ptr<DemeSelector<GeneType>> selector;
330 if (node[
"island"] && node[
"island"][
"selector"]) {
333 selector = std::make_unique<ElitismSelector<GeneType>>();
336 auto serializer = std::make_unique<internal::BinarySerializer<GeneType>>();
337 std::size_t max_payload = serializer->getSerializedSize(island_config.
migration_size, ff.
size());
338 auto comm = std::make_unique<internal::MpiCommunicator<GeneType>>(*serializer, max_payload, mpi_comm);
339 auto buffer = std::make_unique<internal::CircularBuffer<GeneType>>(buffer_capacity, island_config.
migration_size);
341 std::unique_ptr<const Topology> topology;
343 MPI_Comm_size(mpi_comm, &world_size);
345 if (topology_type ==
"fully_connected") {
346 topology = std::make_unique<FullyConnectedTopology>(world_size);
347 }
else if (topology_type ==
"one_way_ring") {
348 topology = std::make_unique<OneWayRingTopology>(world_size);
349 }
else if (topology_type ==
"bidirectional_ring") {
350 topology = std::make_unique<BidirectionalRingTopology>(world_size);
352 throw std::invalid_argument(
"Unknown topology type: " + topology_type);
355 bool elitism = node[
"use_elitism"].as<
bool>(
true);
357 return std::make_unique<IslandGA<GeneType>>(
359 std::move(selection),
361 std::move(crossover),
367 std::move(serializer),
Abstract base class for objective functions to be minimized.
virtual GeneType getLowerBound(std::size_t dimension) const =0
Gets the lower bound for a specific dimension.
virtual GeneType getUpperBound(std::size_t dimension) const =0
Gets the upper bound for a specific dimension.
virtual std::size_t size() const =0
Returns the dimensionality of the optimization problem.
static std::unique_ptr< Crossover< GeneType > > buildCrossover(const YAML::Node &node)
Builds a crossover operator.
static std::unique_ptr< Mutation< GeneType > > buildMutation(const YAML::Node &node, GeneType lb=0, GeneType ub=0)
Builds a mutation operator.
static std::unique_ptr< DemeSelector< GeneType > > buildDemeSelector(const YAML::Node &node)
Builds a deme selector policy (for Island GA).
static std::unique_ptr< LocalSelection< GeneType > > buildLocalSelection(const YAML::Node &node)
Builds a local selection operator (for Cellular GA).
static std::unique_ptr< DemeReplacer< GeneType > > buildDemeReplacer(const YAML::Node &node)
Builds a deme replacer policy (for Island GA).
static std::unique_ptr< Selection< GeneType > > buildSelection(const YAML::Node &node)
Builds a selection operator.
A high-level factory for instantiating GA algorithms from YAML configurations.
static std::unique_ptr< Algorithm< GeneType > > build(const std::string &config_path, FitnessFunction< GeneType > &ff, MPI_Comm mpi_comm=MPI_COMM_NULL)
Unified entry point to build an algorithm from a config file.
static std::unique_ptr< Algorithm< GeneType > > buildCellularGA(const YAML::Node &config, FitnessFunction< GeneType > &ff)
Builds a CellularGA instance.
static std::unique_ptr< Algorithm< GeneType > > buildStandardGA(const YAML::Node &config, FitnessFunction< GeneType > &ff)
Builds a StandardGA instance.
static std::unique_ptr< Algorithm< GeneType > > buildDifferentialEvolutionGA(const YAML::Node &config, FitnessFunction< GeneType > &ff)
Builds a DifferentialEvolutionGA instance.
static std::unique_ptr< Algorithm< GeneType > > buildIslandGA(const YAML::Node &config, FitnessFunction< GeneType > &ff, MPI_Comm mpi_comm)
Builds an IslandGA instance.
double mutation_rate
Probability of mutation occurring for each individual [0.0, 1.0].
bool use_elitism
Whether to preserve the best individual across generations.
std::size_t max_generations
Maximum number of generations to evolve.
double crossover_rate
Probability of crossover between parents [0.0, 1.0].
std::size_t num_threads
Number of OpenMP threads to use. 0 means use system default (omp_get_max_threads).
Configuration parameters specific to the cellular genetic algorithm.
bool use_local_elitism
Keeps the best individual among the current cell and its offspring.
Parameters for the Differential Evolution Genetic Algorithm.
Parameters for the Island Model Genetic Algorithm.
std::size_t migration_size
Number of individuals to send per migration event.
double immigration_quota
Maximum fraction of the population that can be replaced by migrants in one step.
std::size_t migration_interval
Number of generations between migration events.
Parameters for the Standard (Generational) Genetic Algorithm.
static constexpr std::size_t COLS
static constexpr std::size_t ROWS
static constexpr bool USE_LOCAL_ELITISM
static constexpr double F_WEIGHT
static constexpr double CR_RATE
static constexpr double IMMIGRATION_QUOTA
static constexpr std::size_t MIGRATION_SIZE
static constexpr const char * TOPOLOGY
static constexpr std::size_t MAX_GENERATIONS
static constexpr std::size_t MIGRATION_INTERVAL
static constexpr std::size_t BUFFER_CAPACITY
static constexpr bool USE_CUDA