Advertisement

TSP-模拟退火算法求解

阅读量:

1、模拟退火算法
(1)概念
是局部搜索算法的拓展。它与局部搜索算法的不同之处在于:它以一定的概率 选择邻域中目标函数值差的状态。
(2)思路
在这里插入图片描述
(3)伪代码
在这里插入图片描述
(4)图解
模拟退火算法在搜索到局部最优解B后,会以一定的概率接受向右的移动。也许经过几次这样的不是局部最优的移动后会到达BC之间的峰点D,这样一来便跳出了局部最优解B,继续往右移动就有可能获得全局最优解C
在这里插入图片描述
2、求解TSP
同样是求解att48实例(最优解为10628)
代码结构:
在这里插入图片描述
其中Data类 表示定义数据、变量初始化和读取数据的类

复制代码
    package com.chb.Tabu;
    
    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.util.Random;
    import java.util.Scanner;
    
    public class Data {
    	public static int cityNum=48;//城市数量,手动设置
    	public static final int N=40;//每个温度迭代的步长
    	public static final int T=400;//降温次数
    	public static final float a=0.98f;//降温系数
    	public static final float t0=250.0f;//初始温度
    	public static int bestT;//最佳的迭代次数
    	
    	public static int[]Ghh=new int[cityNum];//初始路径编码
    	public static int bestGh[]=new int[cityNum];//最好的路径编码
    	public static int[]tempGh=new int[cityNum];//存放临时编码
    	public static int bestEvaluation;
    	public static int GhhEvaluation;
    	public static int tempEvaluation;
    	
    	public static int point[][]=new int[cityNum][2];//每个城市的坐标
    	public static int dist[][]=new int[cityNum][cityNum];//距离矩阵
    	public static Random random;
    	
    
    	//读取数据并初始化
    	public static void read_data(String filepath) throws FileNotFoundException {
    		String line=null;
    		String substr[]=null;
    		Scanner cin=new Scanner(new BufferedReader(new FileReader(filepath)));
    		for (int i = 0; i < cityNum; i++) {
    			line=cin.nextLine();
    			line.trim();
    			substr=line.split(" ");
    			 point[i][0]=Integer.parseInt(substr[1]);//x坐标
    			 point[i][1]=Integer.parseInt(substr[2]);//y坐标
    		}
    		cin.close();
    		//计算距离矩阵,注意这里的计算方式,才用的是伪欧式距离
    		for (int i = 0; i < cityNum; i++) {
    			dist[i][i]=0;//对角线元素为0
    			for (int j = i+1; j < cityNum; j++) {
    				double rij=Math.sqrt((Math.pow(point[i][0]-point[j][0], 2)+
    						             Math.pow(point[i][1]-point[j][1], 2))/10.0);
    				//rij四舍五入取整
    				int tij=(int) Math.round(rij);
    				if(tij<rij) {
    					dist[i][j]=tij+1;
    					dist[j][i]=dist[i][j];
    				}else {
    					dist[i][j]=tij;
    					dist[j][i]=dist[i][j];
    				}
    			}
    		}
    		dist[cityNum-1][cityNum-1]=0;
    		
    		bestT=0;
    		bestEvaluation=Integer.MAX_VALUE;
    		GhhEvaluation=Integer.MAX_VALUE;
    		tempEvaluation=Integer.MAX_VALUE;
    		random=new Random(System.currentTimeMillis());
    	}
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    

SA类 是算法的主体

复制代码
    package com.chb.Tabu;
    
    import java.io.FileNotFoundException;
    
    public class SA {
    	//初始化编码Ghh
    	public static void initGroup() {
    		Data.Ghh[0]=Data.random.nextInt(65535)%Data.cityNum;
    		int i,j;
    		//使得产生的每个基因都不一样
    		for (i = 1; i < Data.cityNum;) {
    			Data.Ghh[i]=Data.random.nextInt(65535)%Data.cityNum;
    			for (j = 0; j < i; j++) {
    				if(Data.Ghh[i]==Data.Ghh[j]) {
    					break;
    				}
    			}
    			if(j==i) {
    				i++;
    			}
    		}
    	}
    	//复制操作,将Gha复制到Ghb
    	public static void copyGh(int[]Gha,int[]Ghb) {
    		for (int i = 0; i < Data.cityNum; i++) {
    			Ghb[i]=Gha[i];
    		}
    	}
    	//评价函数
    	public static int evaluate(int[] chr) {
    		int len=0;
    		for (int i = 1; i < Data.cityNum; i++) {
    			len+=Data.dist[chr[i-1]][chr[i]];
    		}
    		len+=Data.dist[chr[Data.cityNum-1]][chr[0]];
    		return len;
    	}
    	//领域交换,得到邻居
    	public static void Linju(int[]Gh,int[]tempGh) {
    		int i,temp;
    		int rand1,rand2;
    		//将Gh复制到tempGh
    		for (i = 0; i < Data.cityNum; i++) {
    			tempGh[i]=Gh[i];
    		}
    		rand1=Data.random.nextInt(65535)%Data.cityNum;
    		rand2=Data.random.nextInt(65535)%Data.cityNum;
    		while(rand1==rand2) {
    			rand2=Data.random.nextInt(65535)%Data.cityNum;
    		}
    		//交换
    		temp=tempGh[rand1];
    		tempGh[rand1]=tempGh[rand2];
    		tempGh[rand2]=temp;
    	}
    	public static void solve() {
    		initGroup();
    		copyGh(Data.Ghh, Data.bestGh);
    		Data.bestEvaluation=evaluate(Data.Ghh);
    		Data.GhhEvaluation=Data.bestEvaluation;
    		int k = 0;// 降温次数
    		int n = 0;// 迭代步数
    		float t = Data.t0;
    		float r = 0.0f;
    		while(k<Data.T) {
    			n = 0;
    			while(n<Data.N) {
    				Linju(Data.Ghh,Data.tempGh);
    				Data.tempEvaluation=evaluate(Data.tempGh);
    				if(Data.tempEvaluation<Data.bestEvaluation) {
    					copyGh(Data.tempGh, Data.bestGh);
                    Data.bestT = k;
                    Data.bestEvaluation = Data.tempEvaluation;
    				}
    				r = Data.random.nextFloat();
    				if (Data.tempEvaluation < Data.GhhEvaluation
    						|| Math.exp((Data.GhhEvaluation - Data.tempEvaluation) / t) > r) {
    					copyGh(Data.tempGh,Data.Ghh);
    					Data.GhhEvaluation = Data.tempEvaluation;
    			    }
    				n++;
    		    }
    			t = Data.a * t;
            k++;
     	}
    		System.out.println("最佳迭代次数:"+Data.bestT);
    		System.out.println("最佳长度为:"+Data.bestEvaluation);
    		System.out.println("最佳路径为:");
    		for (int i = 0; i < Data.cityNum; i++) {
    			System.out.print(Data.bestGh[i]+"-->");
    		}
    	}
    	public static void main(String[] args) throws FileNotFoundException {
    		Data.read_data("data/att48.txt");
    		SA.solve();
    	}
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    

data文件夹中的att48.txt是测试文件,可直接百度TSPLIB下载,或从https://pan.baidu.com/s/1Pc71mAN7WBbdxkzOkOK8gw处下载
运行结果:
在这里插入图片描述
注:本文提炼、转载自
[1]
[2]https://mp.weixin.qq.com/s?__biz=MzU0NzgyMjgwNg==&mid=2247484661&idx=1&sn=b96e68355fda7b374291c6ef9a4eb6a9&chksm=fb49c94ccc3e405a040857f5e77d625d2e98574a772910419a8f3a84634201c8dfbd2a4eafce&mpshare=1&scene=1&srcid=0820hOoq59gDC5GYxFEYl8hK&sharer_sharetime=1566289314182&sharer_shareid=054592193644de509623829748e83807&key=d4d627468bf29e7208985ab30b630fe4c5f88b43c632154bb9c1134e2458e00f259ee31d2829a939c2817c80202f04e4d9e319de27a6c3ffbc976fe648e377a49516c6eb120e857e88d8412b060892a9&ascene=1&uin=MjYzMDA1MzAyMQ%3D%3D&devicetype=Windows+10&version=62060834&lang=zh_CN&pass_ticket=S1H0JqHzRjaxKhgJm2o4YKtsaLy7Ycnxh5iXKAukXDfCdwogEmMEpLcVJHu59EQo

全部评论 (0)

还没有任何评论哟~