旅行商问题

旅行推销员问题(英语:Travelling salesman problemTSP)是这样一个问题:给定一系列城市和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路。它是组合优化中的一个NP难问题,在运筹学和理论计算机科学中非常重要。

——百度百科

禁忌搜索算法

禁忌搜索(Tabu Search,TS,又称禁忌搜寻法)是一种现代启发式算法,由美国科罗拉多大学教授Fred Glover在1986年左右提出的,是一个用来跳脱局部最优解的搜索方法。其先创立一个初始化的方案;基于此,算法“移动”到一相邻的方案。经过许多连续的移动过程,提高解的质量。

——百度百科

效果展示

初始解

最终解

代码实现

TSPoint

public class TSPoint{public double X { get; set; }public double Y { get; set; }public TSPoint(){}public TSPoint(double _x, double _y){X=_x;Y=_y;}/// <summary>/// 计算欧式距离/// </summary>/// <param name="point"></param>/// <returns></returns>public double DistanceTo(TSPoint point){return Math.Sqrt((point.X - X) * (point.X - X) + (point.Y - Y) * (point.Y - Y));}public override bool Equals(object? obj){TSPoint point = obj as TSPoint;return (point.X==X)&&(point.Y==Y);}public override int GetHashCode(){TSPoint point = this as TSPoint;return point.GetHashCode();}public override string ToString(){return string.Format("({0}, {1})", X, Y);}}

TabuSearch

public class TabuSearch{/// <summary>/// 禁忌表/// </summary>private int[][] tabulist;/// <summary>/// 禁忌表长度/// </summary>private int neighbour_size;/// <summary>/// 禁忌代数/// </summary>public int tabu_size = 10;/// <summary>/// 迭代次数/// </summary>public int count = 100;/// <summary>/// 无穷大/// </summary>private readonly int INF = int.MaxValue;/// <summary>/// 城市距离表/// </summary>private double[][] distMap;/// <summary>/// 城市坐标/// </summary>public List<TSPoint> points;/// <summary>/// /// </summary>/// <param name="_points"></param>public TabuSearch(List<TSPoint> _points){points  = _points;}/// <summary>/// /// </summary>public void Run(){InitDist();int n = points.Count;// 禁忌表的长度neighbour_size = n*(n-1)/2;// 预生成所有可能的领域,0、1两列是要交换的点,第2列是这种交换下的路径长度,第三列是禁忌长度tabulist = TabuListInit(tabulist, points);List<int> sol_best = new List<int>();double best_val = INF;// 生成初始解,求出n个最终解,找到最优for (int i = 0; i < 20; i++){List<int> sol_current = CreateRandSol(points);// 计算路径长度(目标函数)double sol_val = CalObjFunValue(sol_current);// 开始求解// 0:禁忌表中的下标;1:路径总距离(目标函数值)for (int j = 0; j < count; j++){int[] tabu_mindist = new int[2];// 保存特赦的解int[] tabu_curBest = new int[2];// 保存禁忌表中最好的解tabu_mindist[0] = tabu_mindist[1] = tabu_curBest[0] = tabu_curBest[1] = INF;// 更新禁忌表tabulist = UpdateTabulist(tabulist, sol_current, ref tabu_mindist);// 遍历领域求得此代最佳tabu_curBest = GetBestSol(tabulist, tabu_curBest);// 特赦的(所有对象都被禁忌/该解优于前面任一个解)if(tabu_curBest[0] == INF|| tabu_mindist[1]<sol_val){tabu_curBest[0]=tabu_mindist[0];tabu_curBest[1]=tabu_mindist[1];}// 更新此代最优if (tabu_curBest[1]<sol_val){int best_index = tabu_curBest[0];sol_val = tabu_curBest[1];tabulist[best_index][3] = tabu_size;Swap(tabulist[best_index][0], tabulist[best_index][1], sol_current);}// 更新禁忌长度tabulist = UpdateTabuSize(tabulist);}// 更新全局最优if (sol_val<best_val){best_val = sol_val;sol_best = CopySol(sol_current);}Draw(sol_best, "best"+i+"-"+sol_val);}Draw(sol_best, "final" + best_val);}/// <summary>/// 更新禁忌长度/// </summary>/// <param name="tabulist"></param>/// <returns></returns>private int[][] UpdateTabuSize(int[][] tabulist){for (int i = 0; i < neighbour_size; i++){if (tabulist[i][3]>0)tabulist[i][3]--;}return tabulist;}/// <summary>/// 交换城市位置/// </summary>/// <param name="ind1"></param>/// <param name="ind2"></param>/// <param name="obj"></param>private List<int> Swap(int ind1, int ind2, List<int> obj){int  temp = obj[ind1];obj[ind1] = obj[ind2];obj[ind2] = temp;return obj;}/// <summary>/// 在禁忌表中找到最好的解/// </summary>/// <param name="tabulist"></param>/// <param name="tabu_curBest"></param>/// <returns></returns>private int[] GetBestSol(int[][] tabulist, int[] tabu_curBest){for (int i = 0; i < neighbour_size; i++){// 禁忌长度为0if(tabulist[i][3] == 0&& tabulist[i][2]<tabu_curBest[1]){tabu_curBest[0] = i;tabu_curBest[1] = tabulist[i][2];}}return tabu_curBest;}/// <summary>/// 更新禁忌表/// </summary>/// <param name="tabulist"></param>/// <param name="obj"></param>/// <param name="sol_mindist"></param>/// <returns></returns>private int[][] UpdateTabulist(int[][] tabulist, List<int> obj, ref int[] sol_mindist){// 禁忌表每个交换选择都试一次,选出交换之后最好的那个解for (int i = 0; i < neighbour_size; i++){// 交换邻域int ind1 = tabulist[i][0];int ind2 = tabulist[i][1];obj = Swap(ind1, ind2, obj);int dist = CalObjFunValue(obj);// 如果新的解在禁忌表中,就只存特赦相关信息if(tabulist[i][3] > 3){tabulist[i][2] = INF;if (dist<sol_mindist[1]){sol_mindist[0] = i;sol_mindist[1] = dist;}}else{tabulist[i][2]=dist;}// 再换回去保持原状obj = Swap(ind2, ind1, obj);}return tabulist;}/// <summary>/// 复制/// </summary>/// <param name="obj"></param>/// <returns></returns>private List<int> CopySol(List<int> obj){List<int> res = new List<int>();res.AddRange(obj);return res;}/// <summary>/// 计算目标函数值/// </summary>/// <param name="obj"></param>/// <returns></returns>private int CalObjFunValue(List<int> obj){double res = 0;for (int i = 0; i < obj.Count; i++){res += distMap[obj[i]][obj[(i+1)%obj.Count]];}return (int)Math.Ceiling(res);}/// <summary>/// 产生随机解/// </summary>/// <param name="points"></param>/// <returns></returns>private List<int> CreateRandSol(List<TSPoint> points){List<int> res = new List<int>();Random rand = new Random();int n = points.Count;int[] vis = new int[n];for (int i = 0; i < n; i++){vis[i] = 1;}for (int i = 0; i < n; i++){int index = rand.Next(n);while (vis[index]==0){index = (index+1)%n;}res.Add(index);vis[index] = 0;}return res;}/// <summary>/// 预生成所有可能的邻域/// 0、1两列是要交换的点/// 第2列是这种交换下的路径长度(初始化无穷大)/// 第3列是禁忌长度 (n-1)*n/2/// </summary>/// <param name="tabulist">禁忌表</param>/// <param name="points">城市坐标</param>/// <returns></returns>private int[][] TabuListInit(int[][] tabulist, List<TSPoint> points){int n = points.Count;tabulist = new int[neighbour_size][];int i = 0;for (int j = 0; j < n-1; j++){for (int k = j + 1; k < n; k++){tabulist[i] = new int[4];tabulist[i][0] = j;tabulist[i][1] = k;tabulist[i][2] = INF;i++;}}return tabulist;}/// <summary>/// 计算城市距离并保存/// </summary>private void InitDist(){distMap = new double[points.Count][];for (int i = 0; i<points.Count; i++){distMap[i] = new double[points.Count];}for (int i = 0; i < points.Count - 1; i++){for (int j = i+1; j < points.Count; j++){double dist = i == j ? 0 : points[i].DistanceTo(points[j]);distMap[i][j] = dist;distMap[j][i] = dist;}}}/// <summary>/// 画图/// </summary>/// <param name="sol"></param>/// <param name="name"></param>private void Draw(List<int> sol, string name = "sol"){MapData mapData = new MapData(1);List<Line> lines = PointsToLines(sol);mapData.CreateMap(mapData.GetMaxBound(lines));mapData.AddLines(lines, (int)AstarType.Red);mapData.MapToBitmap(mapData.mapData, "E://" + name + ".bmp");}/// <summary>/// 点转线/// </summary>/// <param name="sol"></param>/// <returns></returns>private List<Line> PointsToLines(List<int> sol){int k = 10;List<Line> lines = new List<Line>();for (int i = 0; i < sol.Count; i++){TSPoint p1 = points[sol[i]];TSPoint p2 = points[sol[(i+1)%sol.Count]];lines.Add(new Line(new XYZ(p1.X * k, p1.Y * k, 0), new XYZ(p2.X * k, p2.Y * k, 0)));}return lines;}}

测试方法:

/// <summary>/// 测试禁忌搜索/// </summary>public void Test(){// 城市坐标List<TSPoint> points = new List<TSPoint>(){new TSPoint(37,52),new TSPoint(49,49),new TSPoint(52,64),new TSPoint(20,26),new TSPoint(40,30),new TSPoint(21,47),new TSPoint(17,63),new TSPoint(31,62),new TSPoint(52,33),new TSPoint(51,21),new TSPoint(42,41),new TSPoint(31,32),new TSPoint(5,25),new TSPoint(12,42),new TSPoint(36,16),new TSPoint(52,41),new TSPoint(27,23),new TSPoint(17,33),new TSPoint(13,13),new TSPoint(57,58),new TSPoint(62,42),new TSPoint(42,57),new TSPoint(16,57),new TSPoint(8,52),new TSPoint(7,38),new TSPoint(27,68),new TSPoint(30,48),new TSPoint(43,67),new TSPoint(58,48),new TSPoint(58,27),new TSPoint(37,69),new TSPoint(38,46),new TSPoint(46,10),new TSPoint(61,33),new TSPoint(62,63),new TSPoint(63,69),new TSPoint(32,22),new TSPoint(45,35),new TSPoint(59,15),new TSPoint(5,7),new TSPoint(10,17),new TSPoint(21,10),new TSPoint(5,64),new TSPoint(30,15),new TSPoint(39,10),new TSPoint(32,39),new TSPoint(25,32),new TSPoint(25,55),new TSPoint(48,28),new TSPoint(56,37),new TSPoint(30,40),};TabuSearch ts = new TabuSearch(points);ts.Run();}

其中Draw方法的依赖参考:

矢量点线转换成矩阵(MapDataConstruction)C#_Wonder-King的博客-CSDN博客我们有矢量的点和线,但是有些时候,我们需要将点和线变成矩阵进行一些操作,比如使用A*算法。下面的代码就是解决这个问题,将点线转换成矩阵,并打印成图片输出。https://blog.csdn.net/qq_42391248/article/details/123893913?spm=1001.2014.3001.5501我的算法仓库:

Algorithm: 简单算法小仓库https://gitee.com/imaginationWdq/algorithm

禁忌搜索算法解决旅行商问题相关推荐

  1. 【高级算法】禁忌搜索算法解决3SAT问题(C++实现)

    转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46440389 最近梳理,翻出了当年高级算法课程做的题目,禁忌搜索算法解决3SAT问 ...

  2. 禁忌搜索算法解决TSP问题

    禁忌搜索算法解决TSP问题 流程图 数据集 关键要素 代码 部分结果展示 流程图 数据集 att48.tsp.eil76.tsp.lin105.tsp[下载链接] 关键要素 初始解产生:采用基于最近邻 ...

  3. matlab最短路径问题(旅行商模型)—模拟退火算法、禁忌搜索算法解决中国省会间最短路径问题

    matlab最短路径问题(模拟退火算法.禁忌搜索算法) 模拟退火算法 禁忌搜索算法 模拟退火算法 %%% 模拟退火算法源程序 % 此题以中国31省会城市的最短旅行路径为例 % clear;clc; ...

  4. 领域搜索算法java_使用JAVA实现算法——禁忌搜索算法解决TSP问题

    packageBasePart;importjava.io.BufferedReader;importjava.io.FileInputStream;importjava.io.IOException ...

  5. 禁忌搜索算法(TABU)解决路线规划问题(CVRP)

    文章目录 禁忌搜索算法解决路线规划问题 问题定义 CVRP问题解决算法 禁忌搜索算法 局部搜索的两种策略 局部搜索的缺点 禁忌搜索算法的提出 禁忌搜索算法流程图 禁忌搜索算法伪码 算法结果 统计结果 ...

  6. 禁忌搜索算法(tabu search)解决TSP及其Matlab代码

    1.算法简介 禁忌搜索算法TS(Tabu search),顾名思义核心在于"禁忌",简单来说就是在某一个过程中把一些不太好的操作给禁止了,直到搜索到一个"最优秀" ...

  7. 禁忌搜索算法TS求解TSP问题

    目录 一.局部邻域搜索 二.禁忌搜索 三.禁忌搜索算法流程 四.算法求解例题 一.局部邻域搜索 局部邻域搜索是基于贪婪准则持续地在当前的邻域中进行搜索,虽然算法通用,易于实现,且容易理解,但其搜索性能 ...

  8. tsp问题的c语言编码,原创:TSP有关问题解决方案-禁忌搜索算法C实现

    1 /*****************************************************************************2 ** Copyright: NEW ...

  9. 基于禁忌搜索算法的三维装箱问题

    装箱问题 装箱问题是复杂的离散组合最优化问题.所谓组合优化,是指在离散的.有限的数学结构上,寻找一个满足给定条件,并使其目标函数值达到最大或最小的解.经典的装箱问题要求把一定数量的物品放入容量相同的一 ...

  10. 【优化规划】基于matlab禁忌搜索算法求解配电网无功补偿优化规划问题【含Matlab源码 1842期】

    一.基于禁忌搜索算法的无功优化参数选择及流程 禁忌搜索方法是Glover F在1986年首次提出的一种智能启发式算法.鉴于禁忌搜索算法是对局部邻域搜索的一种扩展,通过引入一个灵活的存储结构和相应的禁忌 ...

最新文章

  1. 136.二层交换机是哪一层的设备,与三层交换机之间的区别?
  2. docker 安装mysql 实战文档_docker 安装mysql
  3. java数据结构之快速排序
  4. Android开发,你应该知道的
  5. 吴恩达机器学习学习笔记第七章:逻辑回归
  6. 2015中国银联业务(武汉)面试经验(软件开发)
  7. 我与计算机的不解之缘
  8. matlab积分法求椭圆周长,用MATLAB计算椭圆周长和牛顿迭代MATLAB实现.doc
  9. 360wifi使用方法|360wifi使用教程
  10. 电脑下载了自动捆绑怎么办?一招秒杀!
  11. 秒杀活动,怎么设计全套技术方案
  12. <hr> 标签:定义水平线
  13. 缔元信:用户画像技术助推大数据落地
  14. CryptoNight
  15. linux回炉学习(七)
  16. JAVA网络爬爬学习之HttpClient+Jsoup
  17. 2022衢州江山农商银行春季招聘考前冲刺题及答案
  18. 你没有权限查看或编辑这个对象的权限设置 的解决方法
  19. WIN SECS .NET 2.7
  20. 在ROS Kinetic和Gazebo 8中使用智能汽车仿真演示

热门文章

  1. windows10鼠标指针_如何在Windows 10中更轻松地查看鼠标指针
  2. 第四届“传智杯”全国大学生IT技能大赛(决赛B组)
  3. android traceview工具,[Android]Android TraceView工具使用
  4. 数据库索引与视图实验
  5. 删除ubuntu后修复win7系统的引导
  6. 抽象代数学习笔记(抽象代数的历史、运算)
  7. 人工智能--遗传算法求解TSP问题
  8. ubuntu等linux系统如何阅读caj文档
  9. 计算机操作系统|汤小丹|第四版|习题答案(七)
  10. cydia未能联到服务器,cydia无法加载,小编教你cydia无法加载怎么解决