基于模拟退火算法求解TSP问题(JAVA)
转载http://blog.csdn.net/wangqiuyun/article/details/8918523
一、TSP问题
TSP问题(Travelling Salesman Problem)即旅行商问题,又译为旅行推销员问题、货郎担问题,是数学领域中著名问题之一。假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。
TSP问题是一个组合优化问题。该问题可以被证明具有NPC计算复杂性。TSP问题可以分为两类,一类是对称TSP问题(Symmetric TSP),另一类是非对称问题(Asymmetric TSP)。所有的TSP问题都可以用一个图(Graph)来描述:
V={c1, c2, …, ci, …, cn},i = 1,2, …, n,是所有城市的集合.ci表示第i个城市,n为城市的数目;
E={(r, s): r,s∈ V}是所有城市之间连接的集合;
C = {crs: r,s∈ V}是所有城市之间连接的成本度量(一般为城市之间的距离);
如果crs = csr, 那么该TSP问题为对称的,否则为非对称的。
一个TSP问题可以表达为:
求解遍历图G = (V, E, C),所有的节点一次并且回到起始节点,使得连接这些节点的路径成本最低。
二、模拟退火算法
模拟退火法是由 Metropolis 于1953 年提出的,是一种基于热力学原理的随机搜索算法,是局部搜索算法的拓展。它与局部搜索算法的不同之处在于:它以一定的概率选择邻域中目标函数值差的状态。
退火是一种物理过程,一种金属物体在加热至一定的温度后,它的所有分子在其状态空间中自由运动。随着温度的下降,这些分子逐渐停留在不同的状态。在温度最低时,分子重新以一定的结构排列。统计力学的研究表明,在同一个温度,分子停留在能量最小的状态的概率比停留在能量大的状态的概率要大。当温度相当高时,每个状态的概率基本相同,都接近平均值。当温度趋向0时,分子停留在最低能量状态的概率趋向于1。
模拟退火算法是一种基于上述退火原理建立的随机搜索算法。组合优化问题与金属物体的退火过程可进行如下类比:组合优化问题的解类似于金属物体的状态,组合优化问题的最优解类似于金属物体的能量最低的状态,组合优化问题的费用函数类似于金属物体的能量。
为了克服局部搜索算法极易陷入局部最优解的缺点,模拟退火算法使用基于概率的双方向随机搜索技术:当基于邻域的一次操作使当前解的质量提高时,模拟退火算法接受这个被改进的解作为新的当前解;在相反的情况下,算法以一定的概率exp(-ΔC/T)接受相对于当前解来说质量较差的解作为新的当前解,其中Δc为邻域操作前后解的评价值的差,T为退火过程的控制参数(即温度)。模拟退火算法已在理论上被证明是一种以概率1收敛于全局最优解的全局优化算法。
模拟退火算法的实施步:
三、模拟退火算法求解TSP问题
在该JAVA实现中我们选择使用tsplib上的数据att48,这是一个对称TSP问题,城市规模为48,其最优值为10628.其距离计算方法下图所示:
具体代码如下:
- package noah;
- import java.io.BufferedReader;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.util.Random;
- public class SA {
- private int cityNum; // 城市数量,编码长度
- private int N;// 每个温度迭代步长
- private int T;// 降温次数
- private float a;// 降温系数
- private float t0;// 初始温度
- private int[][] distance; // 距离矩阵
- private int bestT;// 最佳出现代数
- private int[] Ghh;// 初始路径编码
- private int GhhEvaluation;
- private int[] bestGh;// 最好的路径编码
- private int bestEvaluation;
- private int[] tempGhh;// 存放临时编码
- private int tempEvaluation;
- private Random random;
- public SA() {
- }
- /**
- * constructor of GA
- *
- * @param cn
- * 城市数量
- * @param t
- * 降温次数
- * @param n
- * 每个温度迭代步长
- * @param tt
- * 初始温度
- * @param aa
- * 降温系数
- *
- **/
- public SA(int cn, int n, int t, float tt, float aa) {
- cityNum = cn;
- N = n;
- T = t;
- t0 = tt;
- a = aa;
- }
- // 给编译器一条指令,告诉它对被批注的代码元素内部的某些警告保持静默
- @SuppressWarnings("resource")
- /**
- * 初始化Tabu算法类
- * @param filename 数据文件名,该文件存储所有城市节点坐标数据
- * @throws IOException
- */
- private void init(String filename) throws IOException {
- // 读取数据
- int[] x;
- int[] y;
- String strbuff;
- BufferedReader data = new BufferedReader(new InputStreamReader(
- new FileInputStream(filename)));
- distance = new int[cityNum][cityNum];
- x = new int[cityNum];
- y = new int[cityNum];
- for (int i = 0; i < cityNum; i++) {
- // 读取一行数据,数据格式1 6734 1453
- strbuff = data.readLine();
- // 字符分割
- String[] strcol = strbuff.split(" ");
- x[i] = Integer.valueOf(strcol[1]);// x坐标
- y[i] = Integer.valueOf(strcol[2]);// y坐标
- }
- // 计算距离矩阵
- // ,针对具体问题,距离计算方法也不一样,此处用的是att48作为案例,它有48个城市,距离计算方法为伪欧氏距离,最优值为10628
- for (int i = 0; i < cityNum - 1; i++) {
- distance[i][i] = 0; // 对角线为0
- for (int j = i + 1; j < cityNum; j++) {
- double rij = Math
- .sqrt(((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j])
- * (y[i] - y[j])) / 10.0);
- // 四舍五入,取整
- int tij = (int) Math.round(rij);
- if (tij < rij) {
- distance[i][j] = tij + 1;
- distance[j][i] = distance[i][j];
- } else {
- distance[i][j] = tij;
- distance[j][i] = distance[i][j];
- }
- }
- }
- distance[cityNum - 1][cityNum - 1] = 0;
- Ghh = new int[cityNum];
- bestGh = new int[cityNum];
- bestEvaluation = Integer.MAX_VALUE;
- tempGhh = new int[cityNum];
- tempEvaluation = Integer.MAX_VALUE;
- bestT = 0;
- random = new Random(System.currentTimeMillis());
- System.out.println(cityNum+","+N+","+T+","+a+","+t0);
- }
- // 初始化编码Ghh
- void initGroup() {
- int i, j;
- Ghh[0] = random.nextInt(65535) % cityNum;
- for (i = 1; i < cityNum;)// 编码长度
- {
- Ghh[i] = random.nextInt(65535) % cityNum;
- for (j = 0; j < i; j++) {
- if (Ghh[i] == Ghh[j]) {
- break;
- }
- }
- if (j == i) {
- i++;
- }
- }
- }
- // 复制编码体,复制编码Gha到Ghb
- public void copyGh(int[] Gha, int[] Ghb) {
- for (int i = 0; i < cityNum; i++) {
- Ghb[i] = Gha[i];
- }
- }
- public int evaluate(int[] chr) {
- // 0123
- int len = 0;
- // 编码,起始城市,城市1,城市2...城市n
- for (int i = 1; i < cityNum; i++) {
- len += distance[chr[i - 1]][chr[i]];
- }
- // 城市n,起始城市
- len += distance[chr[cityNum - 1]][chr[0]];
- return len;
- }
- // 邻域交换,得到邻居
- public void Linju(int[] Gh, int[] tempGh) {
- int i, temp;
- int ran1, ran2;
- for (i = 0; i < cityNum; i++) {
- tempGh[i] = Gh[i];
- }
- ran1 = random.nextInt(65535) % cityNum;
- ran2 = random.nextInt(65535) % cityNum;
- while (ran1 == ran2) {
- ran2 = random.nextInt(65535) % cityNum;
- }
- temp = tempGh[ran1];
- tempGh[ran1] = tempGh[ran2];
- tempGh[ran2] = temp;
- }
- public void solve() {
- // 初始化编码Ghh
- initGroup();
- copyGh(Ghh, bestGh);// 复制当前编码Ghh到最好编码bestGh
- bestEvaluation = evaluate(Ghh);
- GhhEvaluation = bestEvaluation;
- int k = 0;// 降温次数
- int n = 0;// 迭代步数
- float t = t0;
- float r = 0.0f;
- while (k < T) {
- n = 0;
- while (n < N) {
- Linju(Ghh, tempGhh);// 得到当前编码Ghh的邻域编码tempGhh
- tempEvaluation = evaluate(tempGhh);
- if (tempEvaluation < bestEvaluation)
- {
- copyGh(tempGhh, bestGh);
- bestT = k;
- bestEvaluation = tempEvaluation;
- }
- r = random.nextFloat();
- if (tempEvaluation < GhhEvaluation
- || Math.exp((GhhEvaluation - tempEvaluation) / t) > r) {
- copyGh(tempGhh, Ghh);
- GhhEvaluation = tempEvaluation;
- }
- n++;
- }
- t = a * t;
- k++;
- }
- System.out.println("最佳长度出现代数:");
- System.out.println(bestT);
- System.out.println("最佳长度");
- System.out.println(bestEvaluation);
- System.out.println("最佳路径:");
- for (int i = 0; i < cityNum; i++) {
- System.out.print(bestGh[i] + ",");
- if (i % 10 == 0 && i != 0) {
- System.out.println();
- }
- }
- }
- /**
- * @param args
- * @throws IOException
- */
- public static void main(String[] args) throws IOException {
- System.out.println("Start....");
- SA sa = new SA(48, 40, 400, 250.0f, 0.98f);
- sa.init("c://data.txt");
- sa.solve();
- }
- }
运行结果截图:
四、总结
模拟算法其特点是在开始搜索阶段解的质量提高比较缓慢,但是到了迭代后期,它的解的质量提高明显,所以如果在求解过程中,对迭代步数限制比较严格的话,模拟退火算法在有限的迭代步数内很难得到高质量的解。总体而言模拟退火算法比较适合用于有充足计算资源的问题求解。
(截止目前,关于TSP问题系列目前已经使用了爬山、禁忌、蚁群和退火四种算法来求解,计划还有一篇遗传算法的,敬请各位期待!)
注:本文部分内容来源于网络,但程序以及分析结果属于本人成果,转载请注明!
基于模拟退火算法求解TSP问题(JAVA)相关推荐
- 基于爬山算法求解TSP问题(JAVA实现)
一.TSP问题 TSP问题(Travelling Salesman Problem)即旅行商问题,又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选 ...
- 基于模拟退火算法的TSP算法
文章目录 一,理论基础 二,TSP问题介绍 三,思路和步骤 控制参数的设置 初始解 解变换生成新解 Metropolis准则 降温 四,MATLAB程序实现 五,结果分析 六,算法的改进 七,算法的局 ...
- 《MATLAB智能算法30个案例》:第19章 基于模拟退火算法的TSP算法
<MATLAB智能算法30个案例>:第19章 基于模拟退火算法的TSP算法 1. 前言 2. MATLAB 仿真示例 3. 小结 1. 前言 <MATLAB智能算法30个案例分析&g ...
- 用模拟退火算法求解TSP问题
模拟退火算法是一种基于MonteCarlo迭代求解策略的一种随机寻优算法.该算法从某一较高初温出发,伴随温度参数的不断下降,结合概率的突跳特性在解空间中随机寻找目标函数的全局最优解,即在局部最优解能概 ...
- 基于贪心算法求解TSP问题(JAVA)
前段时间在搞贪心算法,为了举例,故拿TSP来开刀,写了段求解算法代码以便有需之人,注意代码考虑可读性从最容易理解角度写,没有优化,有需要可以自行优化! 详细 代码下载:http://www.demod ...
- tsp java_基于贪心算法求解TSP问题(JAVA)
前段时间在搞贪心算法,为了举例,故拿TSP来开刀,写了段求解算法代码以便有需之人,注意代码考虑可读性从最容易理解角度写,没有优化,有需要可以自行优化! 一.TPS问题 TSP问题(Travelling ...
- java模拟多人爬山_基于爬山算法求解TSP问题(JAVA)
一.TSP问题 TSP问题(Travelling Salesman Problem)即旅行商问题,又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选 ...
- 模拟退火算法求解TSP问题
前言:模拟退火(simulated annealing)技术,在每一步都以一定的概率接受比当前结果更差的结果,从而有助于"跳出"局部极小.在每次迭代过程中,接受"次优解& ...
- 【路径优化】基于帝企鹅算法求解TSP问题(Matlab代码实现)
目录 1 帝企鹅算法 2 旅行商问题(TSP) 3 运行结果 4 参考文献 5 Matlab代码实现 1 帝企鹅算法 帝企鹅优化算法(emperor penguin optimizer,EPO)是Ga ...
- 【运筹优化】ACO蚁群算法求解TSP问题(Java实现)
文章目录 代码 Ant蚂蚁类 AntColonyOptimization_TSP蚁群算法类 运行结果 代码 Ant蚂蚁类 import lombok.Data;import java.util.Arr ...
最新文章
- 解析nginx负载均衡
- boost::polygon模块实现多边形集数据相关的测试程序
- 【NOIP2014】子矩阵
- 极光推送收费标准_刚刚,安卓统一推送又有进展了!华为率先...
- C++——已知a+b、 a+c、b+c、 a+b+c,求a、b、 c
- TFS2010 删除工作区(同时删除工作区中所有的目录映射)
- lightoj 1037 - Agent 47(状压dp)
- 线程同步--关键代码段(一)
- 5-17 汉诺塔的非递归实现 (25分)
- 利用c语言实现函数信号发生器,基于51单片机函数信号发生器完整论文下载 带源码 原理图...
- phpspider案例
- Js逆向教程-05明确js逆向的目标
- 浪潮信息服务器哪个好,华为服务器和浪潮服务器哪个好?
- JeecgBoot新增一个module
- 如何用电脑画平面坐标图_如何画平面直角坐标系
- AttributeError: module 'torch.nn.init' has no attribute 'zeros_'
- 集群并行效率测试软件,并行集群系统的Linpack性能测试分析
- 2021年中国光谱分析仪器市场趋势报告、技术动态创新及2027年市场预测
- python numpy读取数据_Python numpy数据的保存和读取
- ArcGIS教程:ArcGIS地质图矢量化技巧概要
热门文章
- ARM:让Mali带来更极致的移动VR体验
- svn 查看版本历史时。Item is not readable svn: 条目不可读
- spring3.0学习之环境搭建
- [asp.net控件]asp.net页面传值汇总
- 3-汇编语言中与内存访问相关的寄存器/操作(DS+数据段+SS/SP+栈相关操作)
- [导入]用Windows自带的媒体播放器抓视频截图
- jmeter学习指南之中文乱码
- java B2B2C 源码 多级分销Springcloud多租户电子商城系统-SpringCloud配置中心内容加密...
- weUI多页面切换效果
- iOS UIStepper使用方法的总结