11#include "../rng/rng_factory.hpp"
22 m_rng(
mc::rng::make_engine(100))
26 m_func = std::move(func);
27 m_initialized =
false;
31 m_callback = std::move(cb);
35 if (lower.size() != upper.size()) {
36 throw std::invalid_argument(
"Lower and Upper bounds must have the same dimension.");
38 m_lower_bounds = lower;
39 m_upper_bounds = upper;
40 m_initialized =
false;
46 m_initialized =
false;
49 bool GA::isBetterFitness(
Real a,
Real b)
const {
53 void GA::evaluate(Individual& ind) {
54 ind.fitness = m_func(ind.genome);
59 for (
size_t i = 0; i < x.size(); ++i) {
60 if (x[i] < m_lower_bounds[i]) x[i] = m_lower_bounds[i];
61 else if (x[i] > m_upper_bounds[i]) x[i] = m_upper_bounds[i];
65 void GA::initialize() {
66 if (!m_func)
throw std::runtime_error(
"Objective function not set.");
67 if (m_lower_bounds.empty())
throw std::runtime_error(
"Bounds not set.");
68 if (m_config.
population_size == 0)
throw std::runtime_error(
"Population size must be > 0.");
70 throw std::runtime_error(
"Elitism count must be < population size.");
75 const size_t dim = m_lower_bounds.size();
76 std::uniform_real_distribution<Real> u01(0.0, 1.0);
82 for (
auto& ind : m_population) {
83 ind.genome.resize(
dim);
84 for (
size_t i = 0; i <
dim; ++i) {
85 Real span = m_upper_bounds[i] - m_lower_bounds[i];
86 ind.genome[i] = m_lower_bounds[i] + u01(m_rng) * span;
92 #pragma omp parallel for
93 for (
int i = 0; i < static_cast<int>(m_population.size()); ++i) {
94 evaluate(m_population[
static_cast<size_t>(i)]);
98 for (
const auto& ind : m_population) {
99 Solution sol{ind.genome, ind.fitness};
100 if (sol.isBetterThan(m_global_best, m_mode)) {
105 m_initialized =
true;
108 const GA::Individual& GA::tournamentSelect() {
109 std::uniform_int_distribution<size_t> pick(0, m_population.size() - 1);
111 const Individual* best =
nullptr;
113 const Individual& cand = m_population[pick(m_rng)];
114 if (!best || isBetterFitness(cand.fitness, best->fitness)) {
123 std::uniform_real_distribution<Real> u01(0.0, 1.0);
124 const size_t dim = p1.size();
129 for (
size_t i = 0; i <
dim; ++i) {
130 if (u01(m_rng) < 0.5) {
131 std::swap(c1[i], c2[i]);
137 std::uniform_real_distribution<Real> u01(0.0, 1.0);
138 std::normal_distribution<Real> n01(0.0, 1.0);
140 for (
size_t i = 0; i < x.size(); ++i) {
142 Real span = m_upper_bounds[i] - m_lower_bounds[i];
144 x[i] += n01(m_rng) * sigma;
151 if (!m_initialized) initialize();
153 std::sort(m_population.begin(), m_population.end(),
155 return isBetterFitness(a.fitness, b.fitness);
158 std::vector<Individual> next;
159 next.reserve(m_population.size());
162 next.push_back(m_population[i]);
165 std::uniform_real_distribution<Real> u01(0.0, 1.0);
168 while (next.size() < m_population.size()) {
180 mutateGaussian(c1.
genome);
181 mutateGaussian(c2.
genome);
184 next.push_back(std::move(c1));
186 if (next.size() < m_population.size()) {
188 next.push_back(std::move(c2));
194 #pragma omp parallel for
195 for (
int i =
static_cast<int>(start); i < static_cast<int>(next.size()); ++i) {
196 evaluate(next[
static_cast<size_t>(i)]);
199 m_population = std::move(next);
203 for (
const auto& ind : m_population) {
204 Solution sol{ind.genome, ind.fitness};
205 if (sol.isBetterThan(m_global_best, m_mode)) {
218 m_callback(m_global_best, gen);
221 return m_global_best;
225 return m_global_best;
Genetic Algorithm (GA) interface and data structures.
GA(const GAConfig &config=GAConfig{})
Construct a GA optimizer with the given configuration.
void setMode(OptimizationMode mode) override
Set optimization mode (minimize or maximize).
void setBounds(const Coordinates &lower, const Coordinates &upper) override
Set lower/upper bounds of the search hyper-rectangle.
Solution optimize() override
Run GA for max_generations.
Solution getBestSolution() const override
Get the best solution found so far.
void setCallback(StepCallback cb) override
Register a callback invoked after each generation.
void setObjectiveFunction(ObjectiveFunction func) override
Set the objective function to optimize.
void step() override
Perform one generation: selection, crossover, mutation, evaluation, and serial update of the global b...
std::function< void(const Solution ¤t_best, size_t iteration)> StepCallback
Callback invoked after each step/generation.
constexpr int dim
Default dimensionality for integration.
OptimizationMode
Optimization goal.
std::function< Real(const Coordinates &)> ObjectiveFunction
Objective function signature.
std::vector< Real > Coordinates
A point in the N-dimensional search space.
double Real
Scalar precision used across optimizers.
Configuration parameters for GA.
size_t elitism_count
Number of top individuals copied unchanged to next generation.
size_t tournament_k
Tournament size for selection (k >= 2).
Real mutation_rate
Per-gene mutation probability.
size_t population_size
Size of the population.
Real crossover_rate
Probability of performing crossover in reproduction.
Real mutation_sigma
Mutation magnitude (scaled by coordinate span).
size_t max_generations
Number of generations to evolve.
A single population member.
Coordinates genome
Encoded parameters (genome).
Real fitness
Fitness value for this genome.
Represents a candidate solution in the search space.
static Solution make_worst(OptimizationMode mode)
Helper to create a worst-case solution for initialization.