热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用粒子群优化算法(PSO)解决旅行商问题(TSP)

 简介         PSO(粒子群算法)是群智能算法的一种,其他的群智能算法还有蚁群算法,遗传算法等。其他的智能算法还有模拟退火。之前看过一段
 简介        

       PSO(粒子群算法)是群智能算法的一种,其他的群智能算法还有蚁群算法,遗传算法等。其他的智能算法还有模拟退火。之前看过一段时间的PSO,商务智能课程最后的大作业便想用一下,刚好在github上看到有人用模拟退火解决TSP问题,而且效果不错,于是便萌生了利用PSO求解TSP问题的想法。

       TSP问题想必大家再熟悉不过了,它是一个NP-hard问题,难以用暴力枚举的算法进行计算。针对NP-hard问题,有许多方法可以求得其近似解,而且效果不错,进化计算算法和群智能算法便是其中之一。

       之前也在博客上看过其他人用PSO求解TSP问题,主要有一下几个问题

  1.  TSP问题的规模相对较小
  2.  对于规模较大的问题,结果并不算太好。

       一般而言,如果不考虑对TSP问题的额外的处理方式,直接用PSO算法,对于一些规模较小的问题(节点数量一般不超过20),PSO算法的效果还行,但是,当问题的规模变得比较大时(50及以上),PSO算法就无能为力。一个重要的原因在于当节点数量增加时,问题的复杂度会变得很大,PSO算法会陷入局部最优,而且这个局部最优往往离最优解很远。这个时候,有两种选择,一是改进PSO算法本身,这个基本很难,我尝试过,效果并不太好,PSO算法的模式基本都是固定的,如果只改变速度中的权重或是简单的调参,收效甚微;二是改变对TSP问题的编码以及粒子速度与位置的定义,使问题本身相对更加容易处理。我用的是第二种方法。

方法与过程

    1.粒子的定义

       1.位置

           对于TSP问题,我们一般将粒子的位置定义为一个位置点的序列。比如{1,2,3,4,5},它表示的是一条路径,即1->2, 2->3, 3->4, 4->5, 5->1(我选的TSP问题是一个环路,所以最后的路径会成环),路径的长度可以计算每一条边的长度并求和得到,边的距离是两点之间的欧氏距离(问题中的点都是二维的)。

       2.速度

           TSP问题中粒子的速度是粒子在当前解空间的运动速度,一般是与粒子当前位置和粒子群体的历史最好位置的差成正比(有时还要考虑粒子当前位置与粒子的历史最好位置的差)。

           在此问题中,粒子的速度被定义为一个二元组合,表示当前路径(即粒子的位置)的一个交换操作。比如(2,3),表示对当前粒子位置中节点2和3进行一次交换操作。粒子的速度可以与位置进行求和,例如,{1,2,3,4,5}+{(2,3)}={1,3,2,4,5}。{(1,2)}和{(2,1)}是两个相同的速度,交换不会考虑粒子的先后顺序。速度的长度定义为元组的个数。

      3.运算规则

           a. 位置-位置=速度

               位置相减会得到一个速度,即一个元组序列。例如,{1,2,3,4,5}-{1,2,4,3,5}={(3,4)},我们可以这样看,两个速度的差别在于3,4两个节点的位置不同,只需将第二个速度进行一次节点的交换便可得到第一个速度。

           b. 速度+速度=速度

               两个速度相加会得到一个新的速度。比如{(1,2)}+{(3,4)}={(1,2),(3,4)}。如果有重复的元组,则会去掉相应的重复项(因为两个相同的交换操作会相互抵消)。{(1,2)}+{(2,1)}={(1,2)}。

           c. 速度*常数=速度

             速度乘以常数会得到一个速度,只不过这个速度的长度和新的速度长度不同。

              speed_1*c=speed_2, 则{length(speed_1)*c]=length(speed_2), 左边是向下取整。例如,{(1,2),(4,5)}*0.5={(1,2)}。

           d. 位置+速度=位置

               位置和速度相加会得到一个新的位置。比如,{1,2,3,4,5}+{(1,2)}={2,1,3,4,5}。按照速度中的元组对位置进行相应变换即可。

           e.滑动运算

             滑动操作是对粒子的位置进行操作。假定速度X={x1,x2,x3,...xm}, SL(X,k)={x(1+k)%m, x(2+k)%m,....,x(m+k)%m}。这里定义这个运算的原因在于粒子速度的等价性。比如,{1,2,3,4,5}与{5,4,3,2,1},它们是两个相同的速度,但是表示不同,如果直接对其做差,相当于做了一次冒泡排序,但是事实上他们的差值应该为0。所以,我们在对速度进行做差时,会用速度的n-1个等义(相当于n-1次滑动运算的结果)表示进行做差,取其中长度最小的速度作为最后的结果。

           f.交叉消除

             这个运算可以说是这个问题的核心。我在用一般的PSO算法进行求解的时候,发现了一个问题,就是结果中的路径会有大量的交叉。

             如上图所示,而且我在博客上看很多人利用PSO算法求解TSP问题的时候也有同样的问题。这是一个很重要的原因,因为大多数的解空间都会有大量的不好的解,这些不好的解的原因在于它们存在大量的边的交叉。于是,我们定义了消除交叉的操作。具体请看下图

          这个算法不是简单的将两条边进行交换就完事了,我尝试过这种操作,效果很不好。它会将后面的边也进行交换。只改变了交叉的边的那一部分,对后面的操作没有影响。

结果分析

          最后的结果如下图:

 

          可以看到,与之前相比好了很多,而且与最优解非常接近,除了一些小的瑕疵。

          下面是我参考的一些资料。

          1.测试数据

          2.参考论文

 


推荐阅读
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 本文介绍了游戏开发中的人工智能技术,包括定性行为和非定性行为的分类。定性行为是指特定且可预测的行为,而非定性行为则具有一定程度的不确定性。其中,追逐算法是定性行为的具体实例。 ... [详细]
  • 2018年人工智能大数据的爆发,学Java还是Python?
    本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • PHP设置MySQL字符集的方法及使用mysqli_set_charset函数
    本文介绍了PHP设置MySQL字符集的方法,详细介绍了使用mysqli_set_charset函数来规定与数据库服务器进行数据传送时要使用的字符集。通过示例代码演示了如何设置默认客户端字符集。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 给定一个二维平面上的一些点,通过计算曼哈顿距离,求连接所有点的最小总费用。只有任意两点之间有且仅有一条简单路径时,才认为所有点都已连接。给出了几个示例并给出了对应的输出。 ... [详细]
  • 本文介绍了如何将CIM_DateTime解析为.Net DateTime,并分享了解析过程中可能遇到的问题和解决方法。通过使用DateTime.ParseExact方法和适当的格式字符串,可以成功解析CIM_DateTime字符串。同时还提供了关于WMI和字符串格式的相关信息。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
author-avatar
mobiledu2502908023
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有