1#ifndef STANDARD_GA_CUDA_H
2#define STANDARD_GA_CUDA_H
44template <
typename GeneType =
double>
69 ) : fitness_function_m(ff),
70 selection_m(std::move(sel)),
71 mutation_m(std::move(mu)),
72 crossover_m(std::move(cs)),
73 mutation_rate_m(m_rate),
74 crossover_rate_m(c_rate),
75 max_generations_m(max_gen),
76 use_elitism_m(elitism) {}
91 if (population.
empty())
return;
93 const int pop_size =
static_cast<int>(population.
size());
94 const int dims =
static_cast<int>(population.
getNumGenes());
97 std::vector<float> h_genes(
static_cast<std::size_t
>(pop_size) * dims);
98 for (
int i = 0; i < pop_size; ++i) {
99 const auto& g = population[i].getGenotype();
100 for (
int j = 0; j < dims; ++j)
101 h_genes[
static_cast<std::size_t
>(i) * dims + j] =
static_cast<float>(g[j]);
104 std::vector<float> h_fitness;
122 params.
sigma =
static_cast<float>(gm->getSigma());
130 std::vector<GeneType> phenotype(
static_cast<std::size_t
>(d));
131 for (
int j = 0; j < d; ++j)
132 phenotype[
static_cast<std::size_t
>(j)] =
static_cast<GeneType
>(genes[j]);
133 return fitness_function_m.evaluate(phenotype);
140 if ((gen + 1) % 50 == 0 || gen == 0) {
141 std::cout <<
"Generation " << (gen + 1)
142 <<
" | Best Fitness: " << best_fitness << std::endl;
147 std::cerr <<
"[GALib] CUDA evolution failed. Population unchanged.\n";
152 for (
int i = 0; i < pop_size; ++i) {
153 auto& ind = population[
static_cast<std::size_t
>(i)];
154 auto& g = ind.getGenotype();
155 for (
int j = 0; j < dims; ++j)
156 g[
static_cast<std::size_t
>(j)] =
157 static_cast<GeneType
>(h_genes[
static_cast<std::size_t
>(i) * dims + j]);
158 ind.setFitness(
static_cast<double>(h_fitness[
static_cast<std::size_t
>(i)]));
164 std::unique_ptr<Selection<GeneType>> selection_m;
165 std::unique_ptr<Mutation<GeneType>> mutation_m;
166 std::unique_ptr<Crossover<GeneType>> crossover_m;
168 double mutation_rate_m;
169 double crossover_rate_m;
170 std::size_t max_generations_m;
178 int population_size =
static_cast<int>(population.
size());
179 #pragma omp parallel for schedule(dynamic)
180 for (
int i = 0; i < population_size; ++i) {
181 double score = fitness_function_m.
evaluate(population[i].getGenotype());
182 population[i].setFitness(score);
Abstract base class for all optimization algorithms.
Interface for crossover (recombination) operators.
Abstract base class for objective functions to be minimized.
virtual double evaluate(const std::vector< GeneType > &phenotype) const =0
Evaluates the fitness of a candidate solution.
Performs Gaussian mutation.
Interface for mutation operators.
A container for a group of individuals in the genetic algorithm.
bool empty() const
Checks if the population is empty.
std::size_t getNumGenes() const
Returns the number of genes for individuals in this population.
std::size_t size() const
Returns the total number of individuals in the population.
Interface for selection operators.
Performs k-way tournament selection.
Generational GA with the same interface as StandardGA, built for CUDA-enabled builds.
StandardGACUDA(FitnessFunction< GeneType > &ff, std::unique_ptr< Selection< GeneType > > sel, std::unique_ptr< Mutation< GeneType > > mu, std::unique_ptr< Crossover< GeneType > > cs, double m_rate, double c_rate, std::size_t max_gen, bool elitism=true)
Constructs the algorithm with all required operators and parameters.
void run(Population< GeneType > &population) override
Runs the evolutionary optimisation loop.
bool runCUDAEvolution(CUDARunParams ¶ms, std::vector< float > &h_genes, std::vector< float > &h_fitness)
Runs the full GA evolution loop on the GPU.
Parameters for a full GPU-accelerated evolution run.
float sigma
Gaussian mutation standard deviation.
std::function< double(const float *, int)> fitness_callback
std::function< void(int, double)> progress_callback