遗传算法实现旅行商问题求解

同步:https://zhufn.fun/archives/yichuansuanfa/我们选择遗传算法的经典案例——旅行商问题来介绍遗传算法的具体实现。旅行商问题给定一系列城市和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路。我们将给每个城市设定一个坐标,以此来求得每对城市之间的距离。对于图上问题,可使用Floyd算法对图进行处理,以获得每对城市之间的最短路。全局常量、变量定义const int SIZE = 1000, CNT = 1000;//种群大小和最大代数usi
摘要由CSDN通过智能技术生成

同步:https://zhufn.fun/archives/yichuansuanfa/

我们选择遗传算法的经典案例——旅行商问题来介绍遗传算法的具体实现。

旅行商问题

给定一系列城市和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路。

我们将给每个城市设定一个坐标,以此来求得每对城市之间的距离。对于图上问题,可使用Floyd算法对图进行处理,以获得每对城市之间的最短路。

全局常量、变量定义

const int SIZE = 1000, CNT = 1000;//种群大小和最大代数
using Pos = pair<double, double>;//坐标类型
using Rst = vector<int>;//染色体类型
vector<Pos> a;//城市坐标数组
double ans = 1e9;//全局最优解,初始化为一个不可能达到的大的长度
Rst ans_rst;//该解对应的染色体
double notans = 1e9;//当前种群最优解,(所以不是答案)
double geneSum = 0;//当前种群的参与二元锦标赛的所有解的和
int geneCnt = 0;//当前种群参与二元锦标赛的个体数量,好像不会变
//以上两行用来求种群平均解,用来观察种群变化

工具函数

//取随机浮点数,0~1
double randf() {
   
    return static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
}
//两点距离
double getDis(Pos p1, Pos p2) {
   
    return sqrt(pow(p1.first - p2.first, 2) + pow(p1.second - p2.second, 2));
}

主要过程

  1. 从标准输入读取城市数量和所有城市坐标。
  2. 重复使用randGene函数产生共SIZE个随机的染色体
  3. 重复CNT次:
    1. 初始化notans为1e9,geneSum和geneCnt为0。
    2. 创建一个空的种群。
    3. 重复CNT/2次
      1. 用选择算子choose函数随机选择两个亲代
      2. 尝试交叉(oxCross函数)(概率20%)。
      3. 尝试变异(bianYi函数)(概率1%)。
      4. 把得到的子代插入新的种群。
    4. 输出本轮更新的全局最优解和种群平均解。
  4. 输出最优解及其染色体。
int main() {
   
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
   
        double tx, ty;
        scanf("%lf%lf", &tx, &ty);
        a.push_back(make_pair(tx, ty));
    }
    //以上为数据输入部分
    //整个种群
    vector<Rst> pool; 
    //生成随机染色体
    for (int i = 1; i <= SIZE; ++i)
        pool.push_back(randGene(n));
    //进行CNT代繁衍
    for (int i = 1; i <= CNT; ++i) {
   
        //初始化本轮统计数据
        notans = 1e9;
        geneSum = 0;
        geneCnt = 0;
        printf("%d ", i);
        //适应度数组
        vector<double> score;
        //新的种群
        vector<Rst> new_pool;
        for (int i = 1; i <= CNT / 2; ++i) {
   
            //选择两个亲代
            auto win1 = choose(pool);
            auto win2 = choose(pool);
            //20%的概率进行交叉
            if (randf() < 0.2) {
   
                auto children = oxCross(win1, win2);
                win1 = children.first;
                win2 = children.second;
            }
            //尝试变异,1%的概率变异
            bianYi(win1);
            bianYi(win2);
            //插入新的种群
            new_pool.pus
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值