局部搜索、模拟退火和遗传算法求解TSP问题

模拟退火和遗传算法求解TSP问题

源代码传送门:GITHUB
数据传送门:TSPLIB

摘要

本实验使用局部搜索、模拟退火、遗传算法(C/C++实现),对TSP问题进行搜索求解。

在实现算法、适当调参后,在选用的5个TSP问题中皆搜索得到误差小于10%的路线。


1 导言

1.1 问题重述

选一个大于100个城市数的TSP问题:

  1. 局部搜索与模拟退火:

    1. 采用多种邻域操作的局部搜索local search策略求解;
    2. 在局部搜索策略的基础上,加入模拟退火simulated annealing策略,并比较两者的效果;
    3. 要求求得的解不要超过最优值的10%,并能够提供可视化图形界面,观察路径的变化和交叉程度。
  2. 用遗传算法求解TSP问题(问题规模等和模拟退火求解TSP实验同),要求:

    1. 设计较好的交叉操作,并且引入多种局部搜索操作(可替换通常遗传算法的变异操作)

    2. 和之前的模拟退火算法(采用相同的局部搜索操作)进行比较

    3. 得出设计高效遗传算法的一些经验,并比较单点搜索和多点搜索的优缺点。

1.2 TSP问题选择

本实验从TSPLIB中选择了5个不同的TSP问题,分别为:

TSP Name Comment DIMENSION Optimal Solution
kroC100 100-city problem C (Krolak/Felts/Nelson) 100 20749
ch150 150 city Problem (churritz) 150 6528
tsp225 A TSP problem (Reinelt) 225 3919
a280 drilling problem (Ludwig) 280 2579
pcb442 Drilling problem (Groetschel/Juenger/Reinelt) 442 50778

1.3 思路设计

在这里插入图片描述

主要思想即上图所示,详细算法内容将在之后的部分说明。


1.4 结果简览

以下实验结果以5次实验取平均值,详细结果分析将在之后的部分说明。

Summary

TSP Name LocalSearch Simulated Annealing Genetic Algorithm
kroC100 22792.88 (Loss 9.85%) 20851.4 (Loss 0.49%) 21903.34(Loss 5.56%)
ch150 7260.656 (Loss 11.22%) 6560.936 (Loss 0.50%) 7124.162 (Loss 9.13%)
tsp225 4308.558 (Loss 9.94%) 3968.232 (Loss 1.26%) 4236.946 (Loss 8.11%)
a280 2906.766 (Loss 12.7%) 2612.91 (Loss 1.31%) 2922.06 (Loss 13.3%)
pcb442 57557.38(Loss 13.35%) 51877.96 (Loss 2.17%) 57649.48 (Loss 13.5%)

在本次实验实现的三种算法中,可以看到模拟退火算法的表现极佳,遗传算法稍逊,局部搜索算法较次。

实验中的数据比较也进行了可视化处理,将在之后的实验结果中详细分析。


2 实验过程

2.1 TSPbase

TSPbase 是一个用于预处理TSP问题数据、为高级搜索方法提供API的基类。

这里给出头部文件的实例,详细实现可参见src/TSPbase.cpp

/****************************************************************
 *                  FileName : TSPbase.h                        *
 *                    Author : Karl                             *
 *              Created Date : June 5, 2020                     *
 *                   Updated : June 8, 2020 - Add Function      *
 *                             June 9, 2020 - Fix Bug           *
 *                             June 9, 2020 - Modify Perfomance *
 *                             June 22, 2020 - Last Check       *
 *==============================================================*
 * @Functions:                                                  *
 *   TSPbase::TSPbase(MAP_TYPE& origin) - Consructor.           *
 *   TSPbase::distance(COORD city1, COORD city2)                *
 *       - calculate EUC2D distance between city1 and city2.    *
 *   TSPbase::currentCost() - calculate cost of `private` path. *
 *   TSPbase::currentCost(vector<int> path)                     *
 *       - calculate cost of path.                              *
 *   TSPbase::roulette() - generate a random decimal in (0, 1). *
 *   TSPbase::generateRandomPath() - generate a random path.    *
 *   TSPbase::getOptCost() - return the best(least) cost so far.*
 *   TSPbase::updateOptCost(double new_dist)                    *
 *       - update current best cost with new_dist.              *
 *   TSPbase::backUp() - back up current path.                  *
 *   TSPbase::recover() - recover current path with backup.     *
 *==============================================================*/
class TSPbase {
   
public:
    ...
protected:
    int N;                             // Dimension
    MAP_TYPE citys;                    // Citys map
    double* dist_map;                  // Dists map
    double opt_cost;                   // Optimal cost(least distance)
    int* path;                         // Current path
    int* city2path;                    // Map a city to its position in path
    int* path_bak;                     // Path backup
    int* city2path_bak;                // Map backup
};

首先,对于一个TSP问题,分析需要考虑的内容:

  1. 城市总数,即问题的维度:N
  2. 每个城市编号以及对应坐标:citys
  3. 路径:path

在读入问题文件后,分析需要记录、预计算的内容:

  1. 城市间距离:dist_map

    在搜索过程中,会非常频繁地计算整条路径的长度(欧氏距离),如果每次都要进行运算,将大大影响我们程序的效率,因此,预计算城市之间距离,静态存到数组中,在计算路径长度时以查表代替计算,能有效提高效率。

  2. 最优解:opt_cost

  3. 城市编号到路径的映射:city2path

    在搜索过程中,可能涉及城市权重等需要按城市顺序存储的数据,因此,在选中一个城市后,想在O(1)时间内定位到它在路径中的位置,就需要建立一个从城市编号到路径位置的对应关系。

对每一次搜索进行备份:

类似于常见的搜索算法,当当前搜索结果并不如意,我们需要回溯到上一状态,这就要求TSPbase能够提供备份、恢复的功能。

  1. 路径的备份:path_bak
  2. 城市编号到路径的映射的备份:city2path_bak

注:

TSPbase提供的方法API在文件头部注释中有详细介绍,且命名是具有可读性的,在此不展开篇幅进行介绍。


2.2 LocalSearch

LocalSearch是基于TSPbase实现的局部搜索算法,为优化效果,加入了以下特性:

  1. 加入了满意度、活跃度机制
  2. 提前终止

以下对局部搜索算法进行详细介绍:

2.2.1 流程图

在这里插入图片描述

2.2.2 满意度、活跃度机制

该机制参考于论文《求解TSP问题的自适应领域搜索法及其扩展》

满意度

直观地,对每个城市而言,最佳位置是该城市和与之相距最近的两个城市相连。

选择城市的时候,我们自然希望所有城市尽可能在自己的最佳位置。为了判断一个城市所在位置是否足够令人满意,加入了满意度( f i f_i fi, 第i个城市的满意度)的定义:

城市i以及与之相连的城市j、k,以及距离城市i最近的两个城市s城市t
f i = e x p [ − ( d i j + d i k − d i s − d i t ) 2 2 δ 2 ] f i : 第 i 个 城 市 的 满 意 度 d X Y : 城 市 X 与 城 市 Y 之 间 的 距 离 δ : 参 数 f_i=exp[-\dfrac{(d_{ij}+d_{ik}-d_{is}-d_{it})^2}{2\delta^2}]\\ f_i:第i个城市的满意度\\ d_{XY}:城市X与城市Y之间的距离\\ \delta:参数 fi=exp[2δ2(dij+dikdisdit)2]fi

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值