package ZhiXinGeGe.ServiceImpl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TSP {
public static final int m=100; //蚂蚁总量
public static final int n=31; //城市总数
public static final int NC_max=100; //最大迭代次数
public static final double Alpha=1; //象征信息素重要程度的参数
public static final double Beta=5; //象征启发式因子重要程度的参数
public static final double Rho=0.1; //信息素蒸发系数
public static final double Q=100; //信息素增加强度系数(另一种翻译为信息素总量)
public static final double C[][] //城市经纬度存储
=new double[][]{
{ 1304, 2312 },
{ 3639, 1315 },
{ 4177, 2244 },
{ 3712, 1399 },
{ 3488, 1535 },
{ 3326, 1556 },
{ 3238, 1229 },
{ 4196, 1004 },
{ 4312, 790 },
{ 4386, 570 },
{ 3007, 1970 },
{ 2562, 1756 },
{ 2788, 1491 },
{ 2381, 1676 },
{ 1332, 695 },
{ 3715, 1678 },
{ 3918, 2179 },
{ 4061, 2370 },
{ 3780, 2212 },
{ 3676, 2578 },
{ 4029, 2838 },
{ 4263, 2931 },
{ 3429, 1908 },
{ 3507, 2367 },
{ 3394, 2643 },
{ 3439, 3201 },
{ 2935, 3240 },
{ 3140, 3550 },
{ 2545, 2357 },
{ 2778, 2826 },
{ 2370, 2975 }
};
static double D[][]=new double[n][n]; //表示完全图的邻接矩阵
static double Eta[][]=new double[n][n]; //表示启发式因子,为D中的距离的倒数
static double DeltaTau[][]=new double[n][n]; //表示启发式因子的变化量
static double Tau[][]=new double[n][n]; //路径上面信息素的浓度
static int Tabu[][]=new int[m][n]; //禁忌表,存储走过的路径,一维存第几只蚂蚁,二维存该蚂蚁已经走过的路
static double L_best[]=new double[NC_max]; //存储每次迭代的路径的最短长度
static double L_ave[]=new double[NC_max]; //存储每次迭代的路径的平均长度
static int R_best[][]=new int[NC_max][n]; //存储每次迭代的最佳路线
public static void ValueInit(){ //初始化各个参数
for (int i=0;i<n;i++){ //初始化D:表示完全图的邻接矩阵
for (int j=0;j<n;j++){
if (i!=j)
D[i][j]=Math.pow(Math.pow((C[i][0]-C[j][0]),2)+Math.pow((C[i][1]-C[j][1]),2),0.5);//勾股定理
else
D[i][j]=0.000000000000000000001;//应该为0,但后面要取倒数
}
}
for (int i=0;i<n;i++) //初始化Eta:表示启发式因子,为D中距离的倒数
for (int j=0;j<n;j++)
Eta[i][j]=1.0/D[i][j];
for (int i=0;i<n;i++) //初始化DeltaTau:表示启发式因子的变化量
for (int j=0;j<n;j++)
DeltaTau[i][j]=0;
for (int i=0;i<n;i++) //初始化Tau:表示路径上的信息素浓度
for (int j=0;j<n;j++)
Tau[i][j]=1.0;
for (int i=0;i<m;i++) //初始化Tabu:禁忌表
for (int j=0;j<n;j++)
Tabu[i][j]=0;
}
/**
void ValueDisplayTabu(int p[][]){ //禁忌表显示函数
for (int i=0;i<m;i++)
for (int j=0;j<n;j++)
System.out.println();
}
*/
/**
void ValueDisplayTau(int p[][]){ //信息素浓度显示函数
for (int i=0;i<m;i++)
for (int j=0;j<n;j++)
System.out.println();
}
*/
public static double rnd(double lower,double uper){ //生成lower和uper之间的一个double类型的随机数
int max=100,min=1;
long randomNum = System.currentTimeMillis(); //方法返回从1970年1月1日0时0分0秒(这与UNIX系统有关)到现在的一个long型的毫秒数,取模之后即可得到所需范围内的随机数。
int ran = (int) (randomNum%(max-min)+min);
return (ran/(double)max)*(uper-lower)+lower;
}
public static void main(String[] args){
ValueInit(); //第一步:进行变量的初始化
int NC=0; //初始化迭代次数、
while (NC<NC_max){
List<Integer> temp=new ArrayList<>(); //第二步:将m只蚂蚁随机的放在n个城市上
for (int i=0;i<Math.ceil((double)m/(double)n);i++)
for (int j=0;j<n;j++)
temp.add(j); //从后部插入
Collections.shuffle(temp); //打乱list里的元素次序
for (int i=0;i<m;i++)
Tabu[i][0]=temp.get(i); //禁忌表,记录每只蚂蚁出生城市
for(int j=1;j<n;j++){ //因为出生在一个城市,所以j从1开始到n
for (int i=0;i<m;i++){
List<Integer> visited=new ArrayList<>();//第i只蚂蚁已访问过的城市
List<Integer> J=new ArrayList<>(); //第i只蚂蚁待访问的城市
List<Double> P=new ArrayList<>(); //第i只蚂蚁带访问的城市的概率
double Psum=0.0; //概率值和
double rate=0.0; //随机数
double choose=0.0; //轮盘赌算法累加值
int to_visit; //下一个要去的城市
for (int k=0;k<j;k++)
visited.add(Tabu[i][k]); //初始化visited
for (int k=0;k<n;k++){
if (visited.indexOf(k)==-1){ //在visited里查找k有没有被访问,若没有返回-1
J.add(k); //J初始化
P.add(0.0); //P初始化
}
}
for (int k=0;k<P.size();k++){ //计算去下一个城市的概率
P.set(k,Math.pow(Tau[visited.get(visited.size()-1)][J.get(k)],Alpha)*Math.pow(Eta[visited.get(visited.size()-1)][J.get(k)],Beta));
Psum+=P.get(k);
}
rate=rnd(0.0,Psum); //使用轮盘赌算法,挑选下一个要去的城市
to_visit=-1; //解除java报警
for (int k=0;k<P.size();k++){
choose+=P.get(k);
if (choose>rate){
to_visit=J.get(k);
break;
}
}
if (to_visit==-1)
System.out.println("to_visit未被赋值");
else
Tabu[i][j]=to_visit; //更新禁忌表
}
}
//第四步:记录本次迭代蚂蚁行走的路线数据
double L[]=new double[m]; //记录本代每只蚂蚁走的路程,并初始化
for (int i=0;i<n;i++){
L[i]=0.0;
}
for (int i=0;i<m;i++){
for (int j=0;j<n-1;j++){
L[i]+=D[Tabu[i][j]][Tabu[i][j+1]];
}
L[i]+=D[Tabu[i][0]][Tabu[i][n-1]]; //最后终点到起点
}
double min_value=L[0]; //声明本代所有蚂蚁行走距离最小值的临时变量
double sum_value=L[0]; //声明本代所有蚂蚁行走距离总值的临时变量
int min_index=0; //记录本代所有蚂蚁行走距离最小值的下标
for (int i=1;i<m;i++){
sum_value+=L[i];
if (L[i]<min_value){
min_value=L[i];
min_index=i;
}
}
L_best[NC]=min_value; //每代路径的最短长度
L_ave[NC]=sum_value/m; //每代路径的平均长度
for (int i=0;i<n;i++){
R_best[NC][i]=Tabu[min_index][i]; //记录每代最短的路径数据
}
System.out.println(NC+":L_best is "+L_best[NC]+" L_ave is "+L_ave[NC]);
NC++; //迭代继续
//第五步:更新信息素
for (int i=0;i<m;i++){
for (int j=0;j<n-1;j++){
DeltaTau[Tabu[i][j]][Tabu[i][j+1]]+=Q/L[i];//此次循环在整个路径上的信息素增量
}
DeltaTau[Tabu[i][n-1]][Tabu[i][0]]+=Q/L[i];
}
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
Tau[i][j]=(1-Rho)*Tau[i][j]+DeltaTau[i][j];//考虑信息素挥发,更新后的信息素
}
}
for (int i=0;i<m;i++) //禁忌表清空
for (int j=0;j<n;j++)
Tabu[i][j]=0;
}
//第六步:输出结果
double min_L=L_best[0];
int min_L_index=0;
int Shortest_Route[]=new int[n];
for (int i=0;i<NC;i++){
if (L_best[i]<min_L){
min_L=L_best[i];
min_L_index=i;
}
}
System.out.println( "The length of the shortest route is " + min_L );
System.out.println("The number of iteration is " + min_L_index);
System.out.println("The Shortest route is: ");
System.out.print("start");
for (int i=0;i<n;i++){
Shortest_Route[i]=R_best[min_L_index][i];
System.out.print("->"+Shortest_Route[i]);
}
}
}
蚁群算法求解TSP问题
最新推荐文章于 2023-05-28 21:21:55 发布