TSP-禁忌搜索算法求解

1、禁忌搜索算法
(1)概念
禁忌搜索(Tabu Search或Taboo Search,简称TS)是对局部搜索(LS)的一种扩展,是一种全局寻优算法,其特点是采用禁忌技术,即用一个禁忌表记录下已经到达过的局部最优点及求解过程,在下一次搜索中,利用禁忌表中的信息不再或有选择地搜索这些点,以此来跳出局部最优点。该算法可以克服爬山算法全局搜索能力不强的弱点。
(2)思路
TSP-禁忌搜索算法求解_第1张图片
TSP-禁忌搜索算法求解_第2张图片
(3)相关术语
评价函数:评价函数是用来评价邻域中的邻居、判断其优劣的衡量指标。大多数情况下,评价函数为目标函数(或目标函数的倒数)。但自定义的形式也可存在,算法也可使用多个评价函数,以提高解的分散性(区分度)。

邻域移动:邻域移动是进行解转移的关键,又称“算子”,邻域移动需要根据不同的问题特点来自定义

禁忌表:禁忌表记录被禁止的变化,以防出现搜索循环、陷入局部最优。对其的设计中最关键的因素是禁忌对象(禁忌表限定的对象)和禁忌步长(对象的禁忌在多少次迭代后失效)。

邻居选择策略:选择最佳邻域移动的规则。目前最广泛采用的是“最好解优先策略”及“第一个改进解优先策略”。前者需比较所有邻域,耗时较久,但解的收敛更有效;后者在发现第一个改进解就进行转移,耗时较少,但收敛效率弱于前者,对于邻域解空间较大的问题往往比较适合。

破禁准则:破禁准则是对于禁忌表的适度放松。防止了因为禁忌表的存在,而错过优异解的情况出现。(如设置禁忌步长)

停止规则:禁忌搜索中停止规则的设计多种多样,如最大迭代数、算法运行时间、给定数目的迭代内不能改进解或组合策略等等。
(4)图解
TSP-禁忌搜索算法求解_第3张图片
TSP-禁忌搜索算法求解_第4张图片
(5)流程图
TSP-禁忌搜索算法求解_第5张图片
2、求解TSP
同样是求解att48实例(最优解为10628)
代码结构:
TSP-禁忌搜索算法求解_第6张图片
其中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 final int MAX_GEN=1000;//最大的迭代次数
	public static final int N=200;//每次搜索领域的个数
	public static final int ll=20;//禁忌长度
	public static int cityNum=48;//城市数量,手动设置
	public static int jinji[][]=new int[ll][cityNum];//禁忌表
	public static int[]Ghh=new int[cityNum];//初始路径编码
	public static int bestGh[]=new int[cityNum];//最好的路径编码
	public static int[]LocalGh=new int[cityNum];//当前最好路径编码
	public static int[]tempGh=new int[cityNum];//存放临时编码
	public static int bestT;//最佳的迭代次数
	public static int bestEvaluation;
	public static int LocalEvaluation;
	public static int tempEvaluation;
	public static int point[][]=new int[cityNum][2];//每个城市的坐标
	public static int dist[][]=new int[cityNum][cityNum];//距离矩阵
	public static int t;//当前迭代
	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;
		
		t=0;
		bestT=0;
		bestEvaluation=Integer.MAX_VALUE;
		LocalEvaluation=Integer.MAX_VALUE;
		tempEvaluation=Integer.MAX_VALUE;
		random=new Random(System.currentTimeMillis());
	}
}

Tabu类是算法的主体

package com.chb.Tabu;

import java.io.FileNotFoundException;

public class Tabu {
	//初始化编码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 int panduan(int[]tempGh) {
		int i,j;
		int flag=0;
		for (i = 0; i <Data.ll; i++) {
			flag=0;
			for ( j = 0; j < Data.cityNum; j++) {
				if(Data.tempGh[j]!=Data.jinji[i][j]) {
					flag=1;//不相同
					break;
				}
			}
			if(flag==0) {	//相同,返回存在相同
			break;
			}
		}
		if(i==Data.ll) {
			return 0;//不存在
		}else {
			return 1;//存在
		}
	}
	//解禁忌与加入禁忌
	public static void jiejinji(int[]tempGh) {
		int i,j,k;
		//删除禁忌表第一个编码,后面编码往前移动
		for (i = 0; i < Data.ll-1; i++) {
			for (j = 0; j < Data.cityNum; j++) {
				Data.jinji[i][j]=Data.jinji[i+1][j];
			}
		}
		//新的编码加入禁忌表
		for (k = 0; k < Data.cityNum; k++) {
			Data.jinji[Data.ll-1][k]=tempGh[k];
		}
	}
	public static void solve() {
		int nn;
		//初始化编码Ghh
		initGroup();
		copyGh(Data.Ghh,Data.bestGh);//复制当前编码Ghh到最好编码bestGh
		Data.bestEvaluation=evaluate(Data.Ghh);
		
		while(Data.t<Data.MAX_GEN) {
			nn=0;
			Data.LocalEvaluation=Integer.MAX_VALUE;
			while(nn<Data.N) {
				Linju(Data.Ghh,Data.tempGh);//得到当前编码Ghh到邻居编码tempGh
				if(panduan(Data.tempGh)==0) {//判断是否在禁忌表中
					//不在
					Data.tempEvaluation=evaluate(Data.tempGh);
					if(Data.tempEvaluation<Data.LocalEvaluation) {
						copyGh(Data.tempGh,Data.LocalGh);
						Data.LocalEvaluation=Data.tempEvaluation;
					}
					nn++;
				}
			}
			if(Data.LocalEvaluation<Data.bestEvaluation) {
				Data.bestT=Data.t;
				copyGh(Data.LocalGh,Data.bestGh);
				Data.bestEvaluation=Data.LocalEvaluation;
			}
			copyGh(Data.LocalGh,Data.Ghh);
			
			//解禁忌表,LocalGh加入禁忌表
			jiejinji(Data.LocalGh);
			Data.t++;
		}
		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");
		Tabu.solve();
	}
}

运行结果:
TSP-禁忌搜索算法求解_第7张图片
:本文提炼、转载自
[1]https://blog.csdn.net/wangqiuyun/article/details/8816463

[2]https://mp.weixin.qq.com/s?__biz=MzU0NzgyMjgwNg==&mid=2247484694&idx=1&sn=b09a92f9b7ec72bed02f32061a2f5887&chksm=fb49c8afcc3e41b908a883d3a6af9fed5634e129bab737c920392ef1440d8dfb5704a6c42e5b&mpshare=1&scene=1&srcid=0820sm6hZg5AZrunq04ehZ7u&sharer_sharetime=1566296373732&sharer_shareid=054592193644de509623829748e83807&key=3d1acede8a6f96ceec7df98e65027292db9913797f9d8e595e93417756877580cd9d9e238aec9df5339f8c457603de4c5c66ad82cda2fb2099085cc585db108ae02d0ecec1b50b6e61e419b9d0655f8e&ascene=1&uin=MjYzMDA1MzAyMQ%3D%3D&devicetype=Windows+10&version=62060834&lang=zh_CN&pass_ticket=S1H0JqHzRjaxKhgJm2o4YKtsaLy7Ycnxh5iXKAukXDfCdwogEmMEpLcVJHu59EQo

你可能感兴趣的:(TSP,算法基础)