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 }

 

posted @ 2014-03-07 10:40  哎呦喂,我的小祖宗╰つ  阅读(799)  评论(1编辑  收藏  举报