template<typename Gene>
class GeneticAlgorithm {
private:
struct Individual {
vector<Gene> chromosome;
double fitness;
bool operator<(const Individual& other) const {
return fitness > other.fitness;
}
};
function<void(vector<Gene>&)> initFunc;
function<double(const vector<Gene>&)> fitnessFunc;
function<void(const vector<Gene>&, const vector<Gene>&,
vector<Gene>&, vector<Gene>&)> crossoverFunc;
function<void(vector<Gene>&)> mutateFunc;
vector<Individual> population;
int popSize;
int maxGen;
double crossRate;
double mutateRate;
Individual select() {
int k = 3;
Individual best = population[rand() % popSize];
for (int i = 1; i < k; i++) {
Individual candidate = population[rand() % popSize];
if (candidate.fitness > best.fitness) {
best = candidate;
}
}
return best;
}
public:
GeneticAlgorithm(int ps, int mg, double cr, double mr)
: popSize(ps), maxGen(mg), crossRate(cr), mutateRate(mr) {}
void setFunctions(
function<void(vector<Gene>&)> init,
function<double(const vector<Gene>&)> fitness,
function<void(const vector<Gene>&, const vector<Gene>&,
vector<Gene>&, vector<Gene>&)> cross,
function<void(vector<Gene>&)> mutate
) {
initFunc = init;
fitnessFunc = fitness;
crossoverFunc = cross;
mutateFunc = mutate;
}
vector<Gene> solve() {
population.resize(popSize);
for (auto& ind : population) {
initFunc(ind.chromosome);
ind.fitness = fitnessFunc(ind.chromosome);
}
for (int gen = 0; gen < maxGen; gen++) {
vector<Individual> newPop;
newPop.reserve(popSize);
while (newPop.size() < popSize) {
Individual parent1 = select();
Individual parent2 = select();
vector<Gene> child1, child2;
if ((double)rand() / RAND_MAX < crossRate) {
crossoverFunc(parent1.chromosome, parent2.chromosome,
child1, child2);
} else {
child1 = parent1.chromosome;
child2 = parent2.chromosome;
}
if ((double)rand() / RAND_MAX < mutateRate) {
mutateFunc(child1);
}
if ((double)rand() / RAND_MAX < mutateRate) {
mutateFunc(child2);
}
Individual ind1 = {child1, fitnessFunc(child1)};
Individual ind2 = {child2, fitnessFunc(child2)};
newPop.push_back(ind1);
if (newPop.size() < popSize) {
newPop.push_back(ind2);
}
}
population = newPop;
}
return max_element(population.begin(), population.end())
->chromosome;
}
};