算法思想我就不介绍了,网上一搜一大把。
禁忌搜索比较依赖于初始解,所以我在外圈设了一个for,生成多个初始解以尽量避开这点,不过师兄告诉我说tsp算法,只要你的多样化做得足够好,其实跟初始解没什么关系。而且普遍的tsp的算法的终止条件是直到找不到最优为止,也就是while,但我这里的25次for-loop是有限次的。
另外,我在多样化时采用的方法是交换任意两个点。师兄后来告诉了我一种更好的思路,任取两个端点,完全颠倒这条子路径。当时一听到这个思想简直虎躯一震啊!为何之前写代码的时候没有在网上搜到过这种思路。。。
ok,以上就是还值得优化的两个地方,目前暂且贴一个粗糙版,什么时候有空了再优化。

这里用的都是以邻接矩阵为输入的tsp数据文件。
数据文件下载戳这里:
http://www.iwr.uni-heidelberg.de/groups/comopt/software/TSPLIB95/tsp/
下载下来跟代码放一个路径里直接就可以跑,记得把下面那个存路径的string改成你自己的。输入是0~9代表10个不同的tsp文件。


#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <list>
using namespace std;#define TABU_SIZE 10    //禁忌代数
#define SWAPSIZE 5      //对于每个点,都只选与它距离较小的前SWAPSIZE个与它交换
#define ITERATIONS 100
#define INF INT_MAX
int rowIndex;
double adj[60][60];
int ordered[60][60];
int city1[60], city2[60], path[60];
string filename[10] = {"gr17.tsp", "gr21.tsp", "gr24.tsp", "fri26.tsp", "bayg29.tsp", "bays29.tsp", "swiss42.tsp", "gr48.tsp", "hk48.tsp", "brazil58.tsp"};
int bestans[10] = {2085, 2707, 1272, 937, 1610, 2020, 1273, 5046, 11461, 25395};
int bestIteration;
int tabuList[2000][4];bool cmp(int a, int b);
double TabuSearch(const int & N);
double GetPathLen(int* city, const int & N);int main(){string absolute("C:\\");int CASE;srand(time(0));while (cin >> CASE && CASE < 10 && CASE > -1){memset(adj, 0, sizeof(adj));memset(city1, 0, sizeof(city1));memset(city2, 0, sizeof(city2));memset(tabuList, 0, sizeof(tabuList));memset(path, 0, sizeof(path));string relative = filename[CASE];string filepath = absolute+relative;ifstream infile(filepath.c_str());if (infile.fail()){cout << "Open failed!\n";}int n;infile >> n;for (int j = 0; j < n; j++){for (int k = 0; k < n; k++){infile >> adj[j][k];}}clock_t start, end;start = clock();int distance = TabuSearch(n);end = clock();double costTime = (end - start)*1.0/CLOCKS_PER_SEC;cout << "TSP file: " << filename[CASE] << endl;cout << "Optimal Soluton: " << bestans[CASE] << endl;cout << "Minimal distance: " << distance << endl;cout << "Error: " << (distance - bestans[CASE]) * 100 / bestans[CASE] << "%" << endl;cout << "Best iterations:  " << bestIteration << endl;cout << "Cost time:        " << costTime << endl; cout << "Path:\n";for (int i = 0; i < n; i++){cout << path[i] + 1 << " ";}cout << endl << endl;;infile.close();}return 0;
}//生成随机的城市序列
void CreateRandOrder(int* city, const int & N){for (int i = 0; i < N; i++){city[i] = rand() % N;for (int j = 0; j < i; j++){if (city[i] == city[j]){i--;break;}}}
}double GetPathLen(int* city, const int & N){double res = adj[city[N-1]][city[0]];int i;for (i = 1; i < N; i++){res += adj[city[i]][city[i-1]];}return res;
}void UpdateTabuList(int len){for (int i = 0; i < len; i++){if (tabuList[i][3] > 0)tabuList[i][3]--;}
}double TabuSearch(const int & N){int countI, countN, NEIGHBOUR_SIZE = N * (N - 1) / 2;double bestDis, curDis, tmpDis, finalDis = INF;bestIteration = 0; string bestCode, curCode, tmpCode;//预生成所有可能的邻域,0、1两列是要交换的点,第2列是这种交换下的路径长度,第3列是禁忌长度 int i = 0;for (int j = 0; j < N - 1; j++){for (int k = j + 1; k < N; k++){tabuList[i][0] = j;tabuList[i][1] = k;tabuList[i][2] = INF;i++;}}//生成初始解,25次用于跳出局部最优 for (int t = 0; t < 25; t++){CreateRandOrder(city1, N);bestDis = GetPathLen(city1, N);//开始求解 //迭代次数为ITERATIONS countI = ITERATIONS;int a, b;int pardon[2], curBest[2];while (countI--){countN = NEIGHBOUR_SIZE;pardon[0] = pardon[1] = curBest[0] = curBest[1] = INF;memcpy(city2, city1, sizeof(city2));//每次迭代搜索的邻域范围为NEIGHBOUR_SIZE while (countN--){//交换邻域 a = tabuList[countN][0];b = tabuList[countN][1];swap(city2[a], city2[b]);tmpDis = GetPathLen(city2, N);//如果新的解在禁忌表中,就只存特赦相关信息 if (tabuList[countN][3] > 0){ tabuList[countN][2] = INF; if (tmpDis < pardon[1]){pardon[0] = countN;pardon[1] = tmpDis;}}//否则,把距离存起来 else {tabuList[countN][2] = tmpDis;}swap(city2[a], city2[b]);//再换回去回复原状方便后面使用   }//遍历邻域求得此代最佳 for (int i = 0; i < NEIGHBOUR_SIZE; i++){if (tabuList[i][3] == 0 && tabuList[i][2] < curBest[1]){curBest[0] = i;curBest[1] = tabuList[i][2];}}//特赦的 if (curBest[0] == INF || pardon[1] < bestDis) {curBest[0] = pardon[0];curBest[1] = pardon[1];}//更新此代最优if (curBest[1] < bestDis){bestDis = curBest[1];tabuList[curBest[0]][3] = TABU_SIZE;bestIteration = ITERATIONS - countI;a = tabuList[curBest[0]][0];b = tabuList[curBest[0]][1];swap(city1[a], city1[b]);}UpdateTabuList(NEIGHBOUR_SIZE);}//更新全局最优if (bestDis < finalDis){finalDis = bestDis;memcpy(path, city1, sizeof(path));}}return finalDis;
}

禁忌搜索解TSP问题相关推荐

  1. 基于禁忌搜索的TSP问题求解仿真输出路线规划图和收敛曲线

    目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 禁忌搜索(Tabu Search或Taboo Search,简称TS)是对局部搜索(LS)的一种扩展 ...

  2. 局部搜索:禁忌搜索(Tabu Search)解决TSP问题的python案例

    禁忌搜索解决TSP问题的python案例 Tabu Search 禁忌(Tabu Search)算法是一种亚启发式(meta-heuristic)随机搜索算法,它从一个初始可行解出发,选择一系列的特定 ...

  3. 元启发式算法 | 禁忌搜索(Tabu Search)解决TSP问题(Python)

    [元启发式算法]禁忌搜索(Tabu Search)解决TSP问题(Python) 文章目录 [元启发式算法]禁忌搜索(Tabu Search)解决TSP问题(Python) 1.Tabu Search ...

  4. TSP问题禁忌搜索c++实现

    今天作业汇报完,直接开源! 1.数据准备: 1.1随机初始化版: 初始化城市数量以及维度: pair<int, int> initial::read_private_i() {cout & ...

  5. 智能算法浅介----模拟退火,遗传算法,禁忌搜索,神经网络等

    本文讲的过于笼统,如果想真正理解,请参考: 1模拟退火 2遗传算法 3禁忌搜索 智能算法浅介----By cooler 一个比方 在工程实践中,经常会接触到一些比较"新颖的算法"如 ...

  6. 禁忌搜索算法求解TSP旅行商问题Matlab实现

    一. 禁忌搜索算法 禁忌搜索算法是一种全局性邻域搜索算法,模拟人类具有记忆功能的寻优特征.它通过局部邻域搜索机制和相应的禁忌准则来避免迂回搜索,并通过破禁水平来释放一些被禁忌的优良状态,进而保证多样化 ...

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

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

  8. 遗传-粒子群算法遗传-禁忌搜索算法求解TSP问题

    1. 前言 上一篇博文[五种常见启发式算法求解TSP问题-总结篇]中,总结了五种常见启发式算法在求解TSP问题上的效果,其中遗传算法的求解质量最差,而粒子群算法和禁忌搜索算法的求解效果最佳,因此本文计 ...

  9. 禁忌搜索(Tabu Search或Taboo Search,简称TS)

    禁忌搜索(Tabu Search或Taboo Search,简称TS)的思想最早由Glover(1986)提出,它是对局部领域搜索的一种扩展,是一种全局逐步寻优算法,是对人类智力过程的一种模拟.TS算 ...

最新文章

  1. SCRM管理系统应具备的8大特点
  2. 基于谱减法的声音去噪
  3. c语言用正数的形式求最大值最小值,C语言-进制 - 盘盘的灰灰的个人空间 - OSCHINA - 中文开源技术交流社区...
  4. 160个Crackme022之故布疑阵
  5. windows下配置mysql数据库_mysql数据库1-windows下mysql安装及配置
  6. echarts如何获取后端的值_Echarts 获取后台数据 使用后台数据展示 柱形图
  7. 前端学习(2345):context api
  8. 易于使用的人工智能_通过AI使网络更易于访问
  9. 综述 | 万字长文带你入门近几年深度学习的重要研究成果
  10. ESX下修改时间和时区
  11. nodejs 密码加盐
  12. abort()和exit()的区别
  13. Linux 现在常用的图形化远控软件的大体介绍
  14. 音视频传输协议之 RTMP
  15. 国外服务器 ping值不稳定,服务器ping值不稳定是什么原因?
  16. 【第17周复盘】拿到红本本喽!
  17. java getdate和getday,jq里面,如何用getDate()和getDay()函数遍历出当月的所有日子和星期?...
  18. 《Java程序设计》公选课学习指南
  19. win10修改用户名_win7如何设置局域网共享无需输入用户名和密码
  20. bzoj2548[Cstc2002]灭鼠行动

热门文章

  1. EPLAN教程 | 易盼软件图形系统如何正确使用?
  2. 【c++】今夕何夕,见此良人
  3. 程序员月薪2万是什么水平,砥砺前行!
  4. MyBatis--总体框架设计
  5. HUST 1584 摆放餐桌
  6. 物流里程 | 使用EXCEL制作物流配送城市里程表
  7. 服务器连接mysql数据库,报错message from server: “Host xxx is not allowed to connect to this MySQL server“
  8. 【PySpark】<Big Data>Spark概述
  9. Softmax分类器基本实现
  10. SP公司新人培训教案