1. 遗传算法概述
遗传算法(Genetic Algorithm, GA)是一种模拟自然界生物进化过程的随机搜索优化算法,由美国密歇根大学的John Holland教授于20世纪70年代提出。它基于达尔文的自然选择理论和孟德尔的遗传学原理,通过模拟生物进化中的选择、交叉和变异等操作来求解优化问题。
1.1 基本思想
遗传算法将问题的解编码成"染色体"(通常为字符串形式),在解空间中形成一个"种群"。通过模拟自然进化过程,让适应度高的个体有更大的机会生存和繁殖,经过多代进化,种群逐渐向最优解收敛。
1.2 主要特点
- 全局搜索能力:通过群体搜索,避免陷入局部最优
- 无需梯度信息:适用于不可导、不连续的复杂函数
- 鲁棒性强:对问题形式要求低,适应性广
- 并行性好:易于并行化实现
2. 遗传算法基本流程
开始
↓
初始化种群
↓
计算适应度
↓
是否满足终止条件?→ 是 → 输出最优解 → 结束
↓ 否
选择操作
↓
交叉操作
↓
变异操作
↓
计算新种群适应度
↓
返回"是否满足终止条件"
3. 关键组成部分
3.1 编码方式
将问题的解表示为染色体,常用编码方式:
- 二进制编码:用0和1表示基因
- 实数编码:直接用实数表示
- 排列编码:用于排序问题
3.2 适应度函数
衡量个体优劣的指标,通常与目标函数相关:
- 最大化问题:f(x) = 目标函数值
- 最小化问题:f(x) = 1/(1 + 目标函数值) 或 f(x) = M - 目标函数值
3.3 选择操作
根据适应度选择优秀个体进行繁殖:
- 轮盘赌选择:适应度越高,被选中的概率越大
- 锦标赛选择:随机选择几个个体,选最优的
- 精英保留:保留最优个体直接进入下一代
3.4 交叉操作
模拟生物交配,产生新个体:
- 单点交叉:随机选择一个交叉点
- 多点交叉:选择多个交叉点
- 均匀交叉:每个基因位独立决定来源
3.5 变异操作
引入随机性,增加种群多样性:
- 位翻转变异:二进制编码中0变1,1变0
- 高斯变异:实数编码中加入高斯噪声
4. C++实现
下面是一个完整的遗传算法C++实现,用于求解函数最大值问题:
#include <iostream>
#include <vector>
#include <random>
#include <algorithm>
#include <cmath>
#include <iomanip>
class GeneticAlgorithm {
private:
// 参数设置
int populationSize; // 种群大小
int chromosomeLength; // 染色体长度
double crossoverRate; // 交叉概率
double mutationRate; // 变异概率
int maxGenerations; // 最大代数
// 随机数生成器
std::random_device rd;
std::mt19937 gen;
std::uniform_real_distribution<double> dis;
std::uniform_int_distribution<int> intDis;
// 种群结构
struct Individual {
std::vector<int> chromosome; // 染色体
double fitness; // 适应度
double value; // 对应的函数值
Individual(int length) : chromosome(length), fitness(0.0), value(0.0) {}
};
std::vector<Individual> population;
public:
// 构造函数
GeneticAlgorithm(int popSize = 100, int chromLength = 20,
double crossRate = 0.8, double mutRate = 0.01,
int maxGen = 1000)
: populationSize(popSize), chromosomeLength(chromLength),
crossoverRate(crossRate), mutationRate(mutRate), maxGenerations(maxGen),
gen(rd()), dis(0.0, 1.0), intDis(0, chromLength - 1) {
population.resize(populationSize, Individual(chromosomeLength));
initializePopulation();
}
// 初始化种群
void initializePopulation() {
for (auto& individual : population) {
for (int i = 0; i < chromosomeLength; i++) {
individual.chromosome[i] = (dis(gen) < 0.5) ? 0 : 1;
}
evaluateIndividual(individual);
}
}
// 解码染色体为实数
double decode(const std::vector<int>& chromosome, double minVal = -5.0, double maxVal = 5.0) {
int binaryValue = 0;
for (int i = 0; i < chromosomeLength; i++) {
if (chromosome[i] == 1) {
binaryValue += (1 << (chromosomeLength - 1 - i));
}
}
double range = maxVal - minVal;
return minVal + (double)binaryValue / (double)((1 << chromosomeLength) - 1) * range;
}
// 目标函数(这里以f(x) = x*sin(10πx) + 2 为例)
double objectiveFunction(double x) {
return x * std::sin(10 * M_PI * x) + 2;
}
// 计算个体适应度
void evaluateIndividual(Individual& individual) {
double x = decode(individual.chromosome);
individual.value = objectiveFunction(x);
individual.fitness = individual.value; // 直接使用函数值作为适应度
}
// 轮盘赌选择
int rouletteWheelSelection() {
double totalFitness = 0.0;
for (const auto& individual : population) {
totalFitness += individual.fitness;
}
double randFitness = dis(gen) * totalFitness;
double cumulativeFitness = 0.0;
for (int i = 0; i < populationSize; i++) {
cumulativeFitness += population[i].fitness;
if (cumulativeFitness >= randFitness) {
return i;
}
}
return populationSize - 1; // 默认返回最后一个
}
// 单点交叉
void crossover(Individual& parent1, Individual& parent2) {
if (dis(gen) > crossoverRate) return;
int crossoverPoint = intDis(gen);
for (int i = crossoverPoint; i < chromosomeLength; i++) {
std::swap(parent1.chromosome[i], parent2.chromosome[i]);
}
}
// 位翻转变异
void mutate(Individual& individual) {
for (int i = 0; i < chromosomeLength; i++) {
if (dis(gen) < mutationRate) {
individual.chromosome[i] = 1 - individual.chromosome[i];
}
}
}
// 进化主循环
void evolve() {
for (int generation = 0; generation < maxGenerations; generation++) {
// 创建新种群
std::vector<Individual> newPopulation;
newPopulation.reserve(populationSize);
// 精英保留:保留最优个体
auto bestIt = std::max_element(population.begin(), population.end(),
[](const Individual& a, const Individual& b) {
return a.fitness < b.fitness;
});
newPopulation.push_back(*bestIt);
// 生成剩余个体
while (newPopulation.size() < populationSize) {
// 选择两个父代
int parent1Idx = rouletteWheelSelection();
int parent2Idx = rouletteWheelSelection();
Individual child1(chromosomeLength);
Individual child2(chromosomeLength);
// 复制父代
child1.chromosome = population[parent1Idx].chromosome;
child2.chromosome = population[parent2Idx].chromosome;
// 交叉
crossover(child1, child2);
// 变异
mutate(child1);
mutate(child2);
// 评估
evaluateIndividual(child1);
evaluateIndividual(child2);
// 选择较好的子代
if (child1.fitness >= child2.fitness) {
newPopulation.push_back(child1);
} else {
newPopulation.push_back(child2);
}
}
// 更新种群
population = std::move(newPopulation);
// 输出当前最优解(每100代)
if (generation % 100 == 0 || generation == maxGenerations - 1) {
auto currentBest = std::max_element(population.begin(), population.end(),
[](const Individual& a, const Individual& b) {
return a.fitness < b.fitness;
});
double x = decode(currentBest->chromosome);
std::cout << "代数 " << std::setw(4) << generation
<< " | 最优解 x = " << std::fixed << std::setprecision(6) << x
<< " | f(x) = " << std::fixed << std::setprecision(6) << currentBest->value
<< std::endl;
}
}
}
// 获取最优解
std::pair<double, double> getBestSolution() {
auto bestIt = std::max_element(population.begin(), population.end(),
[](const Individual& a, const Individual& b) {
return a.fitness < b.fitness;
});
double x = decode(bestIt->chromosome);
return std::make_pair(x, bestIt->value);
}
};
// 主函数
int main() {
std::cout << "遗传算法求解函数最大值" << std::endl;
std::cout << "目标函数: f(x) = x * sin(10πx) + 2" << std::endl;
std::cout << "搜索区间: [-5, 5]" << std::endl;
std::cout << "================================" << std::endl;
// 创建遗传算法实例
GeneticAlgorithm ga(100, 20, 0.8, 0.01, 1000);
// 运行进化
ga.evolve();
// 输出最终结果
auto result = ga.getBestSolution();
std::cout << "================================" << std::endl;
std::cout << "最终结果:" << std::endl;
std::cout << "最优解 x = " << std::fixed << std::setprecision(6) << result.first << std::endl;
std::cout << "最大值 f(x) = " << std::fixed << std::setprecision(6) << result.second << std::endl;
return 0;
}
5. 算法参数调优
5.1 参数选择建议
- 种群大小:20-200,问题复杂度越高,种群越大
- 交叉概率:0.6-0.9,过高可能导致过早收敛
- 变异概率:0.001-0.1,过低缺乏多样性,过高变成随机搜索
- 染色体长度:根据精度要求确定,越长精度越高但计算量越大
5.2 终止条件
- 达到最大代数
- 最优解连续多代无明显改进
- 适应度方差小于阈值
- 找到满意解
6. 应用领域
遗传算法广泛应用于:
- 函数优化
- 组合优化(TSP问题、背包问题)
- 机器学习(神经网络结构优化)
- 工程设计(参数优化)
- 调度问题
- 图像处理
7. 算法优缺点
优点:
- 全局搜索能力强
- 适用范围广
- 并行性好
- 鲁棒性强
缺点:
- 计算量大
- 参数选择敏感
- 理论分析困难
- 可能收敛慢
8. 改进方向
- 自适应参数调整
- 混合算法(与局部搜索结合)
- 多目标遗传算法
- 并行遗传算法
- 免疫遗传算法
23万+

被折叠的 条评论
为什么被折叠?



