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

packageBasePart;importjava.io.BufferedReader;importjava.io.FileInputStream;importjava.io.IOException;importjava.io.InputStreamReader;importjava.util.Random;/*** 禁忌搜索算法用于解决对称TSP问题

* 参考csdn博客主wangqiuyun博文

* 《基于禁忌搜索算法求解TSP问题(JAVA)》2013-04-17 22:38*/

public classTabu {//城市数量

private intcityNum;//禁忌长度

private intII;//搜索邻居限制

private intN;//最大迭代次数

private intMAX_GEN;//成本单元

private int[][] distance;//初始,最佳,临时,当前编码表,成本总量

private int[] initGhh;private int[] bestGhh;private int[] tempGhh;private int[] localGhh;private intinitEvaluate;private intbestEvaluate;private inttempEvaluate;private intlocalEvaluate;//禁忌表,说明:本程序中的禁忌表为目标

private int[][] jinji;//用于产生随机数的Random

privateRandom random;//当前迭代总数

private intt;//出现最佳结果时的迭代数

private intbestT;//无参构造器

publicTabu() {

}//含参构造器

public Tabu(int c,int ii,int m,intn){this.cityNum=c;this.II=ii;this.MAX_GEN=m;this.N=n;

}//初始化读取文件,生成distance数组,初始化成员变量

public void init(String fileName)throwsIOException{//分别储存x,y

int[] x;int[] y;//读取

String strbuff;

BufferedReader data=newBufferedReader(newInputStreamReader(newFileInputStream(fileName)));//初始化数组

x=new int[cityNum];

y=new int[cityNum];//逐行读取数组赋值

for(int i=0;i

strbuff=data.readLine();//生成字符串数组

String[] strs=strbuff.split(" ");//填入x,y中

x[i]=Integer.valueOf(strs[1]);

y[i]=Integer.valueOf(strs[2]);

}//得到坐标数组后利用循环计算任意两点间距离

/** 计算要求:任意俩俩之间都要赋值,对于其本身而言距离为0

* 计算技巧:对称的TSP问题ij与ji值相等计算一次赋值两次就可以

* 注意点: 1.for循环执行的步骤与过程(解释暂时省略)

* 2.对于平方开根号出现小数的处理

* 3.下面的计算方法会漏掉1个解需要补上*/distance=new int[cityNum][cityNum];for(int i=0;i

distance[i][i]=0;for(int j=i+1;j

double dij =Math.sqrt(

(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));/** 赋值分析:这里不采用4舍5入,采取有小数则进位*/

int Dij=(int) Math.round(dij);if(Dij

distance[i][j]=Dij+1;

}else{

distance[i][j]=Dij;

}//对称赋值

distance[j][i]=distance[i][j];

}

}//将上面漏掉的1个解补上

distance[cityNum-1][cityNum-1]=0;/**到目前为止,已经完成了坐标点的录入以成本单元数组的生成

*此方法用于程序的初始化,接下来将对剩余成员变量进行初始化*/initGhh=new int[cityNum];

bestGhh=new int[cityNum];

tempGhh=new int[cityNum];

localGhh=new int[cityNum];//目标找到最小解,所有初始化均为最大值

initEvaluate=Integer.MAX_VALUE;

bestEvaluate=Integer.MAX_VALUE;

tempEvaluate=Integer.MAX_VALUE;

localEvaluate=Integer.MAX_VALUE;

jinji=new int[II][cityNum];

bestT=0;

t=0;//使得结果不同

random=newRandom(System.currentTimeMillis());

}//用于初始化编码表

public voidinitGroup() {/** 生成数组initGhh

* 从0~cityNum互不重复

* 且随机排列*/

inti,j;/** 下面的语句用于生成0~cityNum之间的数,且随机性很大

* 先生成一个数的原因,为了顺利地前后比较*/

//65535是union表的最大value

initGhh[0]=random.nextInt(65535)%cityNum;//for不会成为死循环的写法

for(i=1;i

initGhh[i]=random.nextInt(65535)%cityNum;//与之前的每一个数进行比较,如果相同则退出循环重来

for(j=0;j

}if(i==j){

i++;

}

}

System.out.println("initGhh:");for (int k = 0; k < cityNum; k++) {

System.out.print(initGhh[k]+ ",");

}

}//用于数组数据的拷贝

public void copyGhh(int[]Gha,int[]Ghb){for(int i=0;i

Ghb[i]=Gha[i];

}

}//计算总成本量的方法

public int evaluate(int[] Ghh){int totalEvaluate=0;for(int i=0;i

totalEvaluate+=distance[Ghh[i]][Ghh[i+1]];

}//加上由终点返回起点的值

totalEvaluate+=distance[Ghh[cityNum-1]][Ghh[0]];returntotalEvaluate;

}//生成一个邻域子集

public void Linyu(int[] Ghh,int[]tempGhh){/**生成邻域子集 的步骤

*在原编码表中选出两个用于调换的不相同的位置

*处理tempGhh来进行调换*/copyGhh(Ghh,tempGhh);intran1,ran2 ;

ran1=random.nextInt(65535)%cityNum;

ran2=random.nextInt(65535)%cityNum;while(ran1==ran2){

ran2=random.nextInt(65535)%cityNum;

}int temp=tempGhh[ran1];

tempGhh[ran1]=tempGhh[2];

tempGhh[2]=temp;

}//禁忌表的处理

public void handlejinji(int[] tempGhh) {/** 同时进行的但是有先后顺序

* 解禁编码表

* 添加编码表*/

//首先解禁一个最前面的编码表,数据向前推一个单位

for(int i=1;i

for(int j=0;j

jinji[i-1][j]=jinji[i][j];

}

}//将一个新的编码表加入禁忌表的最后一列

for(int j=0;j

jinji[II-1][j]=tempGhh[j];

}

}//判断编码表是否在禁忌表中(方法等待优化)

public boolean isInJinji(int[]Ghh){//立一个flag每一次循环前刷新

inti,j;int flag=0;for(i=0;i

flag=0;for(j=0;j

flag=1;break;

}

}//如果循环结束flag没有被改变就说明数据列完全相同

if(flag==0){return true;

}

}return false;

}//处理业务逻辑

public voidsolve() {/*进行计算判断求解最优解等一系列事务

* 第一件事情:得到初始的起点

* 第二件事情:在允许的最大迭代次数内计算最优解*/

//用于记录邻居搜索数量

int nn = 0;

initGroup();//将初始方法当作最优解

copyGhh(initGhh,bestGhh);

bestEvaluate=evaluate(bestGhh);//bug等待排查//用t来记录当前迭代次数

while(t

nn=0;

localEvaluate=Integer.MAX_VALUE;while(nn

Linyu(initGhh, tempGhh);//使用当前的初始值来拓展

if(!isInJinji(initGhh)){

tempEvaluate=evaluate(tempGhh);if(tempEvaluate

copyGhh(tempGhh, localGhh);

localEvaluate=tempEvaluate;

}//仅当不在禁忌表中的时候才算是一个可行的邻域子集

nn++;

}

}if(localEvaluate

bestT=t;

copyGhh(localGhh, bestGhh);

bestEvaluate=localEvaluate;

}

copyGhh(localGhh, initGhh);//每次循环的localGhh都加禁止

t++;

}//输出结果:

System.out.println();

System.out.println("最佳长度出现代数:");

System.out.println(bestT);

System.out.println("最佳长度");

System.out.println(bestEvaluate);

System.out.println("最佳路径:");for (int i = 0; i < cityNum; i++) {

System.out.print(bestGhh[i]+ ",");

}

System.out.println("总迭代数"+t);

}public static void main(String[] args) throwsIOException {

System.out.println("开始读取文件");//Tabu(cityNum,II,MAX_GEN,N)

Tabu tabu=new Tabu(48,20,1000000,200);

tabu.init("data.txt");

tabu.solve();

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值