1 import java.util.*;2 public classTsp {3 private String cityName[]={"北京","上海","天津","重庆","哈尔滨","长春","沈阳","呼和浩特","石家庄","太原","济南","郑州","西安","兰州","银川","西宁","乌鲁木齐","合肥","南京","杭州","长沙","南昌","武汉","成都","贵州","福建","台北","广州","海口","南宁","昆明","拉萨","香港","澳门"};4 //private String cityEnd[]=new String[34];
5 private int cityNum=cityName.length; //城市个数
6 private int popSize = 50; //种群数量
7 private int maxgens = 20000; //迭代次数
8 private double pxover = 0.8; //交叉概率
9 private double pmultation = 0.05; //变异概率
10 private long[][] distance = new long[cityNum][cityNum];11 private int range = 2000; //用于判断何时停止的数组区间
12 private classgenotype {13 int city[] = new int[cityNum]; //单个基因的城市序列
14 long fitness; //该基因的适应度
15 double selectP; //选择概率
16 double exceptp; //期望概率
17 int isSelected; //是否被选择
18 }19 private genotype[] citys = newgenotype[popSize];20 /**
21 * 构造函数,初始化种群22 */
23 publicTsp() {24 for (int i = 0; i < popSize; i++) {25 citys[i] = newgenotype();26 int[] num = new int[cityNum];27 for (int j = 0; j < cityNum; j++)28 num[j] =j;29 int temp =cityNum;30 for (int j = 0; j < cityNum; j++) {31 int r = (int) (Math.random() *temp);32 citys[i].city[j] =num[r];33 num[r] = num[temp - 1];34 temp--;35 }36 citys[i].fitness = 0;37 citys[i].selectP = 0;38 citys[i].exceptp = 0;39 citys[i].isSelected = 0;40 }41 initDistance();42 }43 /**
44 * 计算每个种群每个基因个体的适应度,选择概率,期望概率,和是否被选择。45 */
46 public voidCalAll(){47 for( int i = 0; i< popSize; i++){48 citys[i].fitness = 0;49 citys[i].selectP = 0;50 citys[i].exceptp = 0;51 citys[i].isSelected = 0;52 }53 CalFitness();54 CalSelectP();55 CalExceptP();56 CalIsSelected();57 }58 /**
59 * 填充,将多选的填充到未选的个体当中60 */
61 public voidpad(){62 int best = 0;63 int bad = 0;64 while(true){65 while(citys[best].isSelected <= 1 && best
79 * 交叉主体函数80 */
81 public voidcrossover() {82 intx;83 inty;84 int pop = (int)(popSize* pxover /2);85 while(pop>0){86 x = (int)(Math.random()*popSize);87 y = (int)(Math.random()*popSize);88 executeCrossover(x,y);//x y 两个体执行交叉
89 pop--;90 }91 }92 /**
93 * 执行交叉函数94 *@param个体x95 *@param个体y96 * 对个体x和个体y执行佳点集的交叉,从而产生下一代城市序列97 */
98 private void executeCrossover(int x,inty){99 int dimension = 0;100 for( int i = 0 ;i < cityNum; i++)101 if(citys[x].city[i] !=citys[y].city[i]){102 dimension ++;103 }104 int diffItem = 0;105 double[] diff = new double[dimension];106 for( int i = 0 ;i < cityNum; i++){107 if(citys[x].city[i] !=citys[y].city[i]){108 diff[diffItem] =citys[x].city[i];109 citys[x].city[i] = -1;110 citys[y].city[i] = -1;111 diffItem ++;112 }113 }114 Arrays.sort(diff);115 double[] temp = new double[dimension];116 temp =gp(x, dimension);117 for( int k = 0; k< dimension;k++)118 for( int j = 0; j< dimension; j++)119 if(temp[j] ==k){120 double item =temp[k];121 temp[k] =temp[j];122 temp[j] =item;123 item =diff[k];124 diff[k] =diff[j];125 diff[j] =item;126 }127 int tempDimension =dimension;128 int tempi = 0;129 while(tempDimension> 0){130 if(citys[x].city[tempi] == -1){131 citys[x].city[tempi] = (int)diff[dimension -tempDimension];132 tempDimension --;133 }134 tempi ++;135 }136 Arrays.sort(diff);137 temp =gp(y, dimension);138 for( int k = 0; k< dimension;k++)139 for( int j = 0; j< dimension; j++)140 if(temp[j] ==k){141 double item =temp[k];142 temp[k] =temp[j];143 temp[j] =item;144 item =diff[k];145 diff[k] =diff[j];146 diff[j] =item;147 }148 tempDimension =dimension;149 tempi = 0;150 while(tempDimension> 0){151 if(citys[y].city[tempi] == -1){152 citys[y].city[tempi] = (int)diff[dimension -tempDimension];153 tempDimension --;154 }155 tempi ++;156 }157 }158 /**
159 *@paramindividual 个体160 *@paramdimension 维数161 *@return佳点集 (用于交叉函数的交叉点) 在executeCrossover()函数中使用162 */
163 private double[] gp(int individual, intdimension){164 double[] temp = new double[dimension];165 double[] temp1 = new double[dimension];166 int p = 2 * dimension + 3;167 while(!isSushu(p))168 p++;169 for( int i = 0; i< dimension; i++){170 temp[i] = 2*Math.cos(2*Math.PI*(i+1)/p) * (individual+1);171 temp[i] = temp[i] - (int)temp[i];172 if( temp [i]< 0)173 temp[i] = 1+temp[i];174 }175 for( int i = 0; i< dimension; i++)176 temp1[i] =temp[i];177 Arrays.sort(temp1);178 //排序
179 for( int i = 0; i< dimension; i++)180 for( int j = 0; j< dimension; j++)181 if(temp[j]==temp1[i])182 temp[j] =i;183 returntemp;184 }185 /**
186 * 变异187 */
188 public voidmutate(){189 doublerandom;190 inttemp;191 inttemp1;192 inttemp2;193 for( int i = 0 ; i< popSize; i++){194 random =Math.random();195 if(random<=pmultation){196 temp1 = (int)(Math.random() *(cityNum));197 temp2 = (int)(Math.random() *(cityNum));198 temp =citys[i].city[temp1];199 citys[i].city[temp1] =citys[i].city[temp2];200 citys[i].city[temp2] =temp;201 }202 }203 }204 /**
205 * 打印当前代数的所有城市序列,以及其相关的参数206 */
207 public voidprint(){208 /**
209 * 初始化各城市之间的距离210 */
211 private voidinitDistance(){212 for (int i = 0; i < cityNum; i++) {213 for (int j = 0; j < cityNum; j++){214 distance[i][j] = Math.abs(i-j);215 }216 }217 }218 /**
219 * 计算所有城市序列的适应度220 */
221 private voidCalFitness() {222 for (int i = 0; i < popSize; i++) {223 for (int j = 0; j < cityNum - 1; j++)224 citys[i].fitness += distance[citys[i].city[j]][citys[i].city[j + 1]];225 citys[i].fitness += distance[citys[i].city[0]][citys[i].city[cityNum - 1]];226 }227 }228 /**
229 * 计算选择概率230 */
231 private voidCalSelectP(){232 long sum = 0;233 for( int i = 0; i< popSize; i++)234 sum +=citys[i].fitness;235 for( int i = 0; i< popSize; i++)236 citys[i].selectP = (double)citys[i].fitness/sum;237 }238 /**
239 * 计算期望概率240 */
241 private voidCalExceptP(){242 for( int i = 0; i< popSize; i++)243 citys[i].exceptp = (double)citys[i].selectP *popSize;244 }245 /**
246 * 计算该城市序列是否较优,较优则被选择,进入下一代247 */
248 private voidCalIsSelected(){249 int needSelecte =popSize;250 for( int i = 0; i< popSize; i++)251 if( citys[i].exceptp<1){252 citys[i].isSelected++;253 needSelecte --;254 }255 double[] temp = new double[popSize];256 for (int i = 0; i < popSize; i++) {257 //temp[i] = citys[i].exceptp - (int) citys[i].exceptp;258 //temp[i] *= 10;
259 temp[i] = citys[i].exceptp*10;260 }261 int j = 0;262 while (needSelecte != 0) {263 for (int i = 0; i < popSize; i++) {264 if ((int) temp[i] ==j) {265 citys[i].isSelected++;266 needSelecte--;267 if (needSelecte == 0)268 break;269 }270 }271 j++;272 }273 }274 /**
275 *@paramx276 *@return判断一个数是否是素数的函数277 */
278 private boolean isSushu( intx){279 if(x<2) return false;280 for(int i=2;i<=x/2;i++)281 if(x%i==0&&x!=2) return false;282 return true;283 }284 /**
285 *@paramx 数组286 *@returnx数组的值是否全部相等,相等则表示x.length代的最优结果相同,则算法结束287 */
288 private boolean isSame(long[] x){289 for( int i = 0; i< x.length -1; i++)290 if(x[i] !=x[i+1])291 return false;292 return true;293 }294 /**
295 * 打印任意代最优的路径序列296 */
297 private voidprintBestRoute(){298 CalAll();299 long temp = citys[0].fitness;300 int index = 0;301 for (int i = 1; i < popSize; i++) {302 if(citys[i].fitness
319 System.out.println();320 }321 /**
322 * 算法执行323 */
324 public voidrun(){325 long[] result = new long[range];326 //result初始化为所有的数字都不相等
327 for( int i = 0; i< range; i++)328 result[i] =i;329 int index = 0; //数组中的位置
330 int num = 1; //第num代
331 while(maxgens>0){332 System.out.println("----------------- 第 "+num+" 代 -------------------------");333 CalAll();334 print();335 pad();336 crossover();337 mutate();338 maxgens --;339 long temp = citys[0].fitness;340 for ( int i = 1; i< popSize; i++)341 if(citys[i].fitness
356 *@parama 开始时间357 *@paramb 结束时间358 */
359 public voidCalTime(Calendar a,Calendar b){360 long x = b.getTimeInMillis() -a.getTimeInMillis();361 long y = x/1000;362 x = x - 1000*y;363 System.out.println("算法执行时间:"+y+"."+x+" 秒");364 }365 /**
366 * 程序入口367 */
368 public static voidmain(String[] args) {369 Calendar a = Calendar.getInstance(); //开始时间
370 Tsp tsp = newTsp();371 tsp.run();372 Calendar b = Calendar.getInstance(); //结束时间
373 tsp.CalTime(a, b);374 }375 }