java遗传算法
1 import java.util.*; 2 public class Tsp { 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 class genotype { 13 int city[] = new int[cityNum]; //单个基因的城市序列 14 long fitness; //该基因的适应度 15 double selectP; //选择概率 16 double exceptp; //期望概率 17 int isSelected; //是否被选择 18 } 19 private genotype[] citys = new genotype[popSize]; 20 /** 21 * 构造函数,初始化种群 22 */ 23 public Tsp() { 24 for (int i = 0; i < popSize; i++) { 25 citys[i] = new genotype(); 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 void CalAll(){ 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 void pad(){ 62 int best = 0; 63 int bad = 0; 64 while(true){ 65 while(citys[best].isSelected <= 1 && best<popSize-1) 66 best ++; 67 while(citys[bad].isSelected != 0 && bad<popSize-1) 68 bad ++; 69 for(int i = 0; i< cityNum; i++) 70 citys[bad].city[i] = citys[best].city[i]; 71 citys[best].isSelected --; 72 citys[bad].isSelected ++; 73 bad ++; 74 if(best == popSize ||bad == popSize) 75 break; 76 } 77 } 78 /** 79 * 交叉主体函数 80 */ 81 public void crossover() { 82 int x; 83 int y; 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 个体x 95 * @param 个体y 96 * 对个体x和个体y执行佳点集的交叉,从而产生下一代城市序列 97 */ 98 private void executeCrossover(int x,int y){ 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 * @param individual 个体 160 * @param dimension 维数 161 * @return 佳点集 (用于交叉函数的交叉点) 在executeCrossover()函数中使用 162 */ 163 private double[] gp(int individual, int dimension){ 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 return temp; 184 } 185 /** 186 * 变异 187 */ 188 public void mutate(){ 189 double random; 190 int temp; 191 int temp1; 192 int temp2; 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 void print(){ 208 /** 209 * 初始化各城市之间的距离 210 */ 211 private void initDistance(){ 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 void CalFitness() { 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 void CalSelectP(){ 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 void CalExceptP(){ 242 for( int i = 0; i< popSize; i++) 243 citys[i].exceptp = (double)citys[i].selectP * popSize; 244 } 245 /** 246 * 计算该城市序列是否较优,较优则被选择,进入下一代 247 */ 248 private void CalIsSelected(){ 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 * @param x 276 * @return 判断一个数是否是素数的函数 277 */ 278 private boolean isSushu( int x){ 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 * @param x 数组 286 * @return x数组的值是否全部相等,相等则表示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 void printBestRoute(){ 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<temp){ 303 temp = citys[i].fitness; 304 index = i; 305 } 306 } 307 System.out.println(); 308 System.out.println("最佳路径的序列:"); 309 for (int j = 0; j < cityNum; j++) 310 { 311 String cityEnd[]={cityName[citys[index].city[j]]}; 312 for(int m=0;m<cityEnd.length;m++) 313 { 314 System.out.print(cityEnd[m] + " "); 315 } 316 } 317 //System.out.print(citys[index].city[j] + cityName[citys[index].city[j]] + " "); 318 //System.out.print(cityName[citys[index].city[j]]); 319 System.out.println(); 320 } 321 /** 322 * 算法执行 323 */ 324 public void run(){ 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<temp){ 342 temp = citys[i].fitness; 343 } 344 System.out.println("最优的解:"+temp); 345 result[index] = temp; 346 if(isSame(result)) 347 break; 348 index++; 349 if(index==range) 350 index = 0; 351 num++; 352 } 353 printBestRoute(); 354 } 355 /** 356 * @param a 开始时间 357 * @param b 结束时间 358 */ 359 public void CalTime(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 void main(String[] args) { 369 Calendar a = Calendar.getInstance(); //开始时间 370 Tsp tsp = new Tsp(); 371 tsp.run(); 372 Calendar b = Calendar.getInstance(); //结束时间 373 tsp.CalTime(a, b); 374 } 375 }
如果有使用请标明来源:http://www.cnblogs.com/duwenlei/