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

 


推荐阅读
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社区 版权所有