用遗传算法求解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问题 的相关文章

  • Python、Tkinter、更改标签颜色

    有没有一种简单的方法来更改按钮中文本的颜色 I use button text input text here 更改按下后按钮文本的内容 是否存在类似的颜色变化 button color red Use the foreground设置按钮
  • 将字符串转换为带有毫秒和时区的日期时间 - Python

    我有以下 python 片段 from datetime import datetime timestamp 05 Jan 2015 17 47 59 000 0800 datetime object datetime strptime t
  • 使用 openCV 对图像中的子图像进行通用检测

    免责声明 我是计算机视觉菜鸟 我看过很多关于如何在较大图像中查找特定子图像的堆栈溢出帖子 我的用例有点不同 因为我不希望它是具体的 而且我不确定如何做到这一点 如果可能的话 但我感觉应该如此 我有大量图像数据集 有时 其中一些图像是数据集的
  • 如何使用固定的 pandas 数据框进行动态 matplotlib 绘图?

    我有一个名为的数据框benchmark returns and strategy returns 两者具有相同的时间跨度 我想找到一种方法以漂亮的动画风格绘制数据点 以便它显示逐渐加载的所有点 我知道有一个matplotlib animat
  • 如何生成给定范围内的回文数列表?

    假设范围是 1 X 120 这是我尝试过的 gt gt gt def isPalindrome s check if a number is a Palindrome s str s return s s 1 gt gt gt def ge
  • 如何在android上的python kivy中关闭应用程序后使服务继续工作

    我希望我的服务在关闭应用程序后继续工作 但我做不到 我听说我应该使用startForeground 但如何在Python中做到这一点呢 应用程序代码 from kivy app import App from kivy uix floatl
  • DreamPie 不适用于 Python 3.2

    我最喜欢的 Python shell 是DreamPie http dreampie sourceforge net 我想将它与 Python 3 2 一起使用 我使用了 添加解释器 DreamPie 应用程序并添加了 Python 3 2
  • 导入错误:没有名为 _ssl 的模块

    带 Python 2 7 的 Ubuntu Maverick 我不知道如何解决以下导入错误 gt gt gt import ssl Traceback most recent call last File
  • 打破嵌套循环[重复]

    这个问题在这里已经有答案了 有没有比抛出异常更简单的方法来打破嵌套循环 在Perl https en wikipedia org wiki Perl 您可以为每个循环指定标签 并且至少继续一个外循环 for x in range 10 fo
  • 安装后 Anaconda 提示损坏

    我刚刚安装张量流GPU创建单独的后环境按照以下指示here https github com antoniosehk keras tensorflow windows installation 但是 安装后当我关闭提示窗口并打开新航站楼弹出
  • 在循环中每次迭代开始时将变量重新分配给原始值(在循环之前定义)

    在Python中 你使用 在每次迭代开始时将变量重新分配给原始值 在循环之前定义 时 也就是说 original 1D o o o for i in range 0 3 new original 1D revert back to orig
  • 在pyyaml中表示具有相同基类的不同类的实例

    我有一些单元测试集 希望将每个测试运行的结果存储为 YAML 文件以供进一步分析 YAML 格式的转储数据在几个方面满足我的需求 但测试属于不同的套装 结果有不同的父类 这是我所拥有的示例 gt gt gt rz shorthand for
  • Python:字符串不会转换为浮点数[重复]

    这个问题在这里已经有答案了 我几个小时前写了这个程序 while True print What would you like me to double line raw input gt if line done break else f
  • Python:尝试检查有效的电话号码

    我正在尝试编写一个接受以下格式的电话号码的程序XXX XXX XXXX并将条目中的任何字母翻译为其相应的数字 现在我有了这个 如果启动不正确 它将允许您重新输入正确的数字 然后它会翻译输入的原始数字 我该如何解决 def main phon
  • 循环中断打破tqdm

    下面的简单代码使用tqdm https github com tqdm tqdm在循环迭代时显示进度条 import tqdm for f in tqdm tqdm range 100000000 if f gt 100000000 4 b
  • Python - 按月对日期进行分组

    这是一个简单的问题 起初我认为很简单而忽略了它 一个小时过去了 我不太确定 所以 我有一个Python列表datetime对象 我想用图表来表示它们 x 值是年份和月份 y 值是此列表中本月发生的日期对象的数量 也许一个例子可以更好地证明这
  • 为美国东部以外地区的 Cloudwatch 警报发送短信?

    AWS 似乎没有为美国东部以外的 SNS 主题订阅者提供 SMS 作为协议 我想连接我的 CloudWatch 警报并在发生故障时接收短信 但无法将其发送到 SMS YES 经过一番挖掘后 我能够让它发挥作用 它比仅仅选择一个主题或输入闹钟
  • 如何从没有结尾的管道中读取 python 中的 stdin

    当管道来自 打开 时 不知道正确的名称 我无法从 python 中的标准输入或管道读取数据 文件 我有作为例子管道测试 py import sys import time k 0 try for line in sys stdin k k
  • glpk.LPX 向后兼容性?

    较新版本的glpk没有LPXapi 旧包需要它 我如何使用旧包 例如COBRA http opencobra sourceforge net openCOBRA Welcome html 与较新版本的glpk 注意COBRA适用于 MATL
  • Pandas 与 Numpy 数据帧

    看这几行代码 df2 df copy df2 1 df 1 df 1 values 1 df2 ix 0 0 我们的教练说我们需要使用 values属性来访问底层的 numpy 数组 否则我们的代码将无法工作 我知道 pandas Data

随机推荐

  • 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 遗传算法简介 关于遗传算法 首先看一段维基百科的解释 遗传算法是模仿自然界生物进化机制发展起来的随机全局搜索和优化方法 它借鉴了达尔