热门标签 | 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.参考论文

 


推荐阅读
  • 使用Numpy实现无外部库依赖的双线性插值图像缩放
    本文介绍如何仅使用Numpy库,通过双线性插值方法实现图像的高效缩放,避免了对OpenCV等图像处理库的依赖。文中详细解释了算法原理,并提供了完整的代码示例。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • 深入理解OAuth认证机制
    本文介绍了OAuth认证协议的核心概念及其工作原理。OAuth是一种开放标准,旨在为第三方应用提供安全的用户资源访问授权,同时确保用户的账户信息(如用户名和密码)不会暴露给第三方。 ... [详细]
  • 本文介绍如何解决在 IIS 环境下 PHP 页面无法找到的问题。主要步骤包括配置 Internet 信息服务管理器中的 ISAPI 扩展和 Active Server Pages 设置,确保 PHP 脚本能够正常运行。 ... [详细]
  • Python 异步编程:深入理解 asyncio 库(上)
    本文介绍了 Python 3.4 版本引入的标准库 asyncio,该库为异步 IO 提供了强大的支持。我们将探讨为什么需要 asyncio,以及它如何简化并发编程的复杂性,并详细介绍其核心概念和使用方法。 ... [详细]
  • 优化ASM字节码操作:简化类转换与移除冗余指令
    本文探讨如何利用ASM框架进行字节码操作,以优化现有类的转换过程,简化复杂的转换逻辑,并移除不必要的加0操作。通过这些技术手段,可以显著提升代码性能和可维护性。 ... [详细]
  • 本文总结了2018年的关键成就,包括职业变动、购车、考取驾照等重要事件,并分享了读书、工作、家庭和朋友方面的感悟。同时,展望2019年,制定了健康、软实力提升和技术学习的具体目标。 ... [详细]
  • 资源推荐 | TensorFlow官方中文教程助力英语非母语者学习
    来源:机器之心。本文详细介绍了TensorFlow官方提供的中文版教程和指南,帮助开发者更好地理解和应用这一强大的开源机器学习平台。 ... [详细]
  • 本文详细介绍了如何使用PHP检测AJAX请求,通过分析预定义服务器变量来判断请求是否来自XMLHttpRequest。此方法简单实用,适用于各种Web开发场景。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
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社区 版权所有