用遗传算法求解TSP问题

2023-11-05

原文链接: http://blog.5long.me/2015/genetic-algorithm-on-tsp/

遗传算法简介

关于遗传算法,首先看一段维基百科的解释:

遗传算法是模仿自然界生物进化机制发展起来的随机全局搜索和优化方法,它借鉴了达尔文的进化论和孟德尔的遗传学说。其本质是一种高效、并行、全局搜索的方法,它能在搜索过程中自动获取和积累有关搜索空间的知识,并自适应的控制搜索过程以求得最优解。遗传算法操作使用适者生存的原则,在潜在的解决方案种群中逐次产生一个近似最优解的方案,在遗传算法的每一代中,根据个体在问题域中的适应度值和从自然遗传学中借鉴来的再造方法进行个体选择,产生一个新的近似解。这个过程导致种群中个体的进化,得到的新个体比原来个体更能适应环境,就像自然界中的改造一样。
遗传算法是计算机科学人工智能领域中用于解决最优化的一种搜索启发式算法,是进化算法的一种。这种启发式通常用来生成有用的解决方案来优化和搜索问题。进化算法最初是借鉴了进化生物学中的一些现象而发展起来的,这些现象包括遗传、突变、自然选择以及杂交等。

概括来说遗传算法:

  • 模仿生物进化。
  • 可以找到一个近似最优解(不一定是全局最优解)。
  • 是计算机科学人工智能的一种算法。

遗传算法的基本步骤是:

  1. 初始化。随机选择一些个体组成最初的种群(Population),地球最原始的生命也是随机产生的。
  2. 评估。通过某种方法来评估个体的适应度。个体的生存能力。
  3. 选择。类似于自然选择,优良的基因(Gene)、生存能力强的被选择下来的概率要大。当然,也存在屌丝逆袭的情况。
  4. 交叉。产生后代,基因交叉,可以理解为有性繁殖,子代会分别从父母那得到部分基因。
  5. 变异。后代的基因可能会变异。变异在生物进化起了很大作用。

3-5步是产生新种群的步骤,新群体再进行评估,然后再选择、交叉、变异,一直循环2-5步,最终找到一个近似最优解。遗传算法的流程图如下;

遗传算法流程图

关于遗传算法的进一步解释请参考:经典算法研究系列:七、深入浅出遗传算法(http://blog.csdn.net/v_JULY_v/article/details/6132775)

TSP问题简介

TSP问题全称旅行商问题(Traveling Salesman Problem,TSP),别名旅行推销员问题、货郎担问题,与哈密顿回路问题有密切联系。且看维基百科的解释:

旅行推销员问题(Travelling Salesman Problem,又称为旅行商问题、货郎担问题、TSP问题)是一个多局部最优的最优化问题:有n个城市,一个推销员要从其中某一个城市出发,唯一走遍所有的城市,再回到他出发的城市,求最短的路线。也即求一个最短的哈密顿回路。

C-TSP问题就是中国旅行商问题(China Traveling Salesman Problem),求解中国34个一线城市的最优路线。给出中国34个城市的经纬度:

编号 城市名 东经 北纬 编号 城市名 东经 北纬
1 北京 116.46 39.92 18 南京 118.78 32.04
2 天津 117.2 39.13 19 合肥 117.27 31.86
3 上海 121.48 31.22 20 杭州 120.19 30.26
4 重庆 106.54 29.59 21 福州 119.3 26.08
5 拉萨 91.11 29.97 22 南昌 115.89 28.68
6 乌鲁木齐 87.68 43.77 23 长沙 113 28.21
7 银川 106.27 38.47 24 武汉 114.31 30.52
8 呼和浩特 111.65 40.82 25 广州 113.23 23.16
9 南宁 108.33 22.84 26 台北 121.5 25.05
10 哈尔滨 126.63 45.75 27 海口 110.35 20.02
11 长春 125.35 43.88 28 兰州 103.73 36.03
12 沈阳 123.38 41.8 29 西安 108.95 34.27
13 石家庄 114.48 38.03 30 成都 104.06 30.67
14 太原 112.53 37.87 31 贵阳 106.71 26.57
15 西宁 101.74 36.56 32 昆明 102.73 25.04
16 济南 117 36.65 33 香港 114.1 22.2
17 郑州 113.6 34.76 34 澳门 113.33 22.13

遗传算法应用于TSP问题

基因编码

n个城市的的基因编码方式为:

  1. 给每一个城市一个序号,如1->北京,2->上海,3->广州,。。。。,n->成都。
  2. 用包含n个城市的序号的数组序列表示一种路线(个体),数组元素的序号表示旅行的顺序,如{3, 1, 2,。。。。,n}表示的旅行顺序为:广州->北京->上海->。。。。->成都。
  3. 数值序列中值不重复,即每个城市只去一次。

初始化种群

随机生成m个基因编码序列作为初始种群。

评估适应度

TSP问题中路线越短越好,适应度取值为总距离的倒数,即1/distance。

产生新种群

产生新种群分为选择、交叉和变异。个体被选中的概率取决于该个体的适应度值,比如有5个个体,他们的适应度值为:

1 2 3 4 5
0.3 0.2 0.1 0.4 0.8

在[0.0, 1.8)随机产生一个浮点数,如0.8,则4号个体被选中。

随机选择两个个体后,以概率Pc交叉,子代分别继承父母的部分基因,且保持顺序与父代一致,如父代的基因序列:
父母基因序列

随机选取Parent1的部分基因,如678,与Parent2交叉,结果如下:
后代基因序列

交叉完后就是变异,变异以Pm的概率发生。在TSP问题中因为每个城市只经过一次,所以在变异的时候不能只是改变基因序列中的某一位的值(这会导致一个城市经过两次),应该随机交换两个位置的值,如:

突变

交换了3和8的位置。

实现代码

参考了用遗传算法解旅行商问题的代码,也是用Python实现的,总共有4个文件:

  1. Life.py。个体类。
  2. GA.py。遗传算法类。
  3. TSP_GA.py。TSP问题,命令行。
  4. TSP_GA_w.py。TSP问题,图形界面仿真。

其中TSP_GA_w.py是在TSP_GA.py增加了一个图形界面,以比较直观地方式来看结果。TSP_GA_w.pyTSP_GA.py任选一个运行即可。

代码已上传在GitHub上,下载地址:https://github.com/chaolongzhang/tsp

关键代码说明

GA.py中实现遗传算法的核心代码如下:

def next(self):
      """产生下一代"""
      self.judge()
      newLives = []
      newLives.append(self.best)
      while len(newLives) < self.lifeCount:
            newLives.append(self.newChild())
      self.lives = newLives
      self.generation += 1

def judge(self):
      """评估,计算每一个个体的适配值"""
      self.bounds = 0.0             #适配值之和,用于选择是计算概率
      self.best = self.lives[0]     #保存这一代中最好的个体
      for life in self.lives:
            life.score = self.matchFun(life)
            self.bounds += life.score
            if self.best.score < life.score:
                  self.best = life

def newChild(self):
      """产生新后代"""
      parent1 = self.getOne()
      rate = random.random()

      #按概率交叉
      if rate < self.croessRate:
            #交叉
            parent2 = self.getOne()
            gene = self.cross(parent1, parent2)
      else:
            gene = parent1.gene

      #按概率突变
      rate = random.random()
      if rate < self.mutationRate:
            gene = self.mutation(gene)

      return Life(gene)

def cross(self, parent1, parent2):
      """交叉"""
      index1 = random.randint(0, self.geneLenght - 1)
      index2 = random.randint(index1, self.geneLenght - 1)
      tempGene = parent2.gene[index1:index2]                            #交叉的基因片段
      newGene = []
      p1len = 0
      for g in parent1.gene:
            if p1len == index1:
                  newGene.extend(tempGene)                                        #插入基因片段
                  p1len += 1
            if g not in tempGene:
                  newGene.append(g)
                  p1len += 1
      self.crossCount += 1
      return newGene

以下是运行中的部分截图:

初始情况:

初始情况

786代的情况:

786代的情况

可以看出,结果比最初情况要好。

趋于稳定的情况:

稳定情况

另一个趋于稳定的情况:

稳定情况

从图中可看出,结果在向最优解发展。

结语

本文在参考前人的基础之上,介绍了遗传算法和TSP问题,并用Python实现了算法。刚接触遗传算法,实现的效果还有很多可以优化的地方。

参考

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用遗传算法求解TSP问题 的相关文章

随机推荐

  • r语言聚类分析_【SPSS数据分析】SPSS聚类分析(R型聚类)的软件操作与结果解读 ——【杏花开生物医药统计】...

    在上一讲中 我们讲述了针对样本进行聚类的分析方法 Q型聚类 今天我们将详细讲解针对变量数据进行的聚类分析 系统聚类之R型聚类 我们要将数据变量进行聚类 但不知道要分成几类 或者没有明确的分类指标的时候 就需要用到R型聚类 R型聚类分析不但可
  • 根据Sql生成ER图

    原文 https blog csdn net qq 17010367 article details 79212850 commentsedit 1 根据SQL文件生成ER图 首先准备好SQL文件 然后在PowerDesigner 里 点击
  • 字符串表达式校验&求值(C#实现) - 附代码

    一 参考文献 严蔚敏 数据结构 C语言版 二 功能演示 1 测试例子 2 测试结果 三 对表达式进行校验 怎么对输入的字符串表达式进行校验呢 1 对表达式按操作符进行拆分 返回一个字符串数组 代码 private static string
  • Oracle数据库删除重复数据

    Oracle数据库中如何删除重复数据 第一种情况 部分字段重复数据的删除 先查询出那些数据是重复的 select 字段1 字段2 count from 表名 group by 字段1 字段2 having count gt 1 将上面的大于
  • TIA博途S7-1200学习笔记——指令集

    目录 1 位逻辑运算操作 1 1 常开触点 1 2 常闭触点 1 3 取反触点 1 4 线圈 1 5 赋值取反 1 6 复位输出 1 7 置位输出 1 8 置位位域 1 9 复位位域 2 10 SR置位 复位触发器 1 11 RS复位 置位
  • 【activiti】网关

    activiti网关 网关是用来控制流程的走向的 1 排他网关 ExclusiveGateway 1 1 什么是排他网关 排他网关 用来在流程中实现决策 当执行到这个网关时 会根据判断条件去选择执行某一条分支 注意 排他网关只会选择一个为t
  • 5.5_数据的存储和排列

    文章目录 一 大小端模式 二 边界对齐 在这个小结中 我们要探讨的是 数据的存储和排列 一 大小端模式 首先来看一个之前提到过的问题 叫做大小端模式 我们在内存里经常会存储某一些多字节的数据 比如 c 语言里的 Int 型变量 在很多时候占
  • renren-fast 快速开发 Web 管理平台

    什么是 renren fast renren fast 是一个 Java 的开源项目 只需要对它进行简单修改 就能够应用到自己的项目中 大大简化开发流程 缩短开发周期 renren fast 是一个前后端分离开发的项目 前端基于 vue e
  • 算法之动态规划理论

    目录 前言 一个模型三个特征理论讲解 1 最优子结构 2 无后效性 3 重复子问题 一个模型三个特征实例剖析 两种动态规划解题思路总结 1 状态转移表法 2 状态转移方程法 四种算法思想比较分析 总结 参考资料 前言 本篇博文主要讲解动态规
  • 一步一步详解LSTM网络【从RNN到LSTM到GRU等,直至attention】

    一步一步详解LSTM网络 从RNN到LSTM到GRU等 直至attention 0 前言 1 Recurrent Neural Networks循环神经网络 2 The Problem of Long Term Dependencies长期
  • 直接理解转置卷积(Transposed convolution)的各种情况

    使用GAN生成图像必不可少的层就是上采样 其中最常用的就是转置卷积 Transposed Convolution 如果把卷积操作转换为矩阵乘法的形式 转置卷积实际上就是将其中的矩阵进行转置 从而产生逆向的效果 所谓效果仅仅在于特征图的形状
  • Word模板引擎poi-tl

    文章目录 方案对比 版本 特性 模板 数据 输出 数据模型 标签 1 文本 2 图片 3 表格 4 列表 5 嵌套 6 区块对 SpingEL 2 单系列图标 3 多系列图标 4 组合图表 配置 1 标签前后缀 2 标签类型 3 标签匹配值
  • vlc源码编译android最新版2020年9月份记录

    经过几天研究终于在2020 9 25早上编译出安卓版本的vlc for android的so文件了 此时源码指定gradle是6 1 1版本的 主要参考都是百度上面的 你们也能百度到 这里就不引用了 重点 1 参考vlc官方编译过程 htt
  • 激光扫描测量点模拟(Matlab源码)

    本文提供了一个模拟环境 模拟激光束打到物体表面上的点及地面点 可以设置激光范围 分辨率 物体位置 大小及旋转 近期需要分析激光扫描仪在物体的背景上产生的遮挡 没找到合适的环境 自己用Matlab写了一个 原理不难 但细节的东西挺多 本以为一
  • 【达内课程】DataInputStream、DataOutputStream用法

    文章目录 简介 DataOutputStream DataInputStream 栗子1 写入数据 栗子2 读取 栗子3 保存学生信息 简介 在 io 包中 提供了两个与平台无关的数据操作流 数据输出流 DataOutputStream 数
  • C语言语法笔记

    C语言语法笔记 C 语言教程 网道 wangdoc com C 语言教程 菜鸟教程 runoob com 文章目录 C语言语法笔记 一 关键字 32 二 预编译指令 三 流程控制 3 1 顺序结构 3 2 循环结构 3 3 条件结构 四 变
  • OpenStack--镜像制作

    通过 KVM 安装虚 Centos 和 Windwos 2008 R2 x86 64 操作系统步骤并将磁盘文件作为镜像上传到 openstack glance 作为批量创建虚拟机的镜像文件 其中 windowsn 2008 安装 virti
  • 产品开发项目中文档的重要性

    现在 很多人认为写文档是一件苦差使 特别是研发人员 觉得写文档是一种浪费 和产品开发工作没有太大关系 更愿意把写文档的时间用来写代码画图纸 实际上 一个成功完整的产品开发项目 最终产出的不只是可交付的实际产品 还包括产品开发过程中的文档 以
  • Slim-neck by GSConv:自动驾驶车辆检测器架构的更好设计范式(文末附代码)

    Slim neck by GSConv 自动驾驶车辆检测器架构的更好设计范式 摘要 引言 相关工作 本文方法 GSConv的优势在于轻量级检测器 这些检测器通过添加DSC层和Shuffle来增加非线形表达能力 但是 如果GSConv在模型的
  • 用遗传算法求解TSP问题

    原文链接 http blog 5long me 2015 genetic algorithm on tsp 遗传算法简介 关于遗传算法 首先看一段维基百科的解释 遗传算法是模仿自然界生物进化机制发展起来的随机全局搜索和优化方法 它借鉴了达尔