【优化】遗传算法

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. 改进方向

  • 自适应参数调整
  • 混合算法(与局部搜索结合)
  • 多目标遗传算法
  • 并行遗传算法
  • 免疫遗传算法
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值