遗传算法

来源:互联网 发布:怎么查电脑网络端口 编辑:程序博客网 时间:2024/06/11 16:21

import java.util.*;

public class Tsp {   
   
private String cityName[]={"北京","上海","天津","重庆","哈尔滨","长春","沈阳","呼和浩特","石家庄","太原","济南","郑州","西安","兰州","银川","西宁","乌鲁木齐","合肥","南京","杭州","长沙","南昌","武汉","成都","贵州","福建","台北","广州","海口","南宁","昆明","拉萨","香港","澳门"};
   
//private String cityEnd[]=new String[34];
    private int cityNum=cityName.length;                //城市个数
    private int popSize = 50;                //种群数量
    private int maxgens = 20000;            //迭代次数
    private double pxover = 0.8;            //交叉概率
    private double pmultation = 0.05;        //变异概率
    private long[][] distance = new long[cityNum][cityNum];
   
private int range = 2000;                //用于判断何时停止的数组区间
   
   
private class genotype {
       
int city[] = new int[cityNum];        //单个基因的城市序列
        long fitness;                        //该基因的适应度
        double selectP;                        //选择概率
        double exceptp;                        //期望概率
        int isSelected;                        //是否被选择
    }
   
private genotype[] citys = new genotype[popSize];

   
/**
     *     构造函数,初始化种群
    
*/
   
public Tsp() {
       
for (int i = 0; i < popSize; i++) {
            citys[i]
= new genotype();
           
int[] num = new int[cityNum];
           
for (int j = 0; j < cityNum; j++)
                num[j]
= j;
           
int temp = cityNum;
           
for (int j = 0; j < cityNum; j++) {
               
int r = (int) (Math.random() * temp); citys[i].city[j] = num[r];
                num[r]
= num[temp - 1];
                temp
--;
            }
            citys[i].fitness
= 0;
            citys[i].selectP
= 0;
            citys[i].exceptp
= 0;
            citys[i].isSelected
= 0;
        }
        initDistance();
    }
   
   
/**
     *  计算每个种群每个基因个体的适应度,选择概率,期望概率,和是否被选择。
    
*/
   
public void CalAll(){
       
for( int i = 0; i< popSize; i++){
            citys[i].fitness
= 0;
            citys[i].selectP
= 0;
            citys[i].exceptp
= 0;
            citys[i].isSelected
= 0;
        }
        CalFitness();
        CalSelectP();
        CalExceptP();
        CalIsSelected();
    }

   
/**
     *     填充,将多选的填充到未选的个体当中
    
*/
   
public void pad(){
       
int best = 0;
       
int bad = 0;
       
while(true){           
           
while(citys[best].isSelected <= 1 && best<popSize-1)
                best
++;
           
while(citys[bad].isSelected != 0 && bad<popSize-1)
                bad
++;
           
for(int i = 0; i< cityNum; i++)
                citys[bad].city[i]
= citys[best].city[i];
                citys[best].isSelected
--;
                citys[bad].isSelected
++;
                bad
++;   
           
if(best == popSize ||bad == popSize)
               
break;
        }
    }
   
   
/**
     *     交叉主体函数
    
*/
   
public void crossover() {
       
int x;
       
int y;
       
int pop = (int)(popSize* pxover /2);
       
while(pop>0){
            x
= (int)(Math.random()*popSize);
            y
= (int)(Math.random()*popSize);
           
            executeCrossover(x,y);
//x y 两个体执行交叉
            pop--;
        }
    }
   
   
/**
     * 执行交叉函数
     *
@param 个体x
     *
@param 个体y
     * 对个体x和个体y执行佳点集的交叉,从而产生下一代城市序列
    
*/
   
private void executeCrossover(int x,int y){
       
int dimension = 0;
       
for( int i = 0 ;i < cityNum; i++)
           
if(citys[x].city[i] != citys[y].city[i]){
                dimension
++;
            }   
       
int diffItem = 0;
       
double[] diff = new double[dimension];

       
for( int i = 0 ;i < cityNum; i++){
           
if(citys[x].city[i] != citys[y].city[i]){
                diff[diffItem]
= citys[x].city[i];
                citys[x].city[i]
= -1;
                citys[y].city[i]
= -1;
                diffItem
++;
            }   
        }
   
        Arrays.sort(diff);

       
double[] temp = new double[dimension];
        temp
= gp(x, dimension);

       
for( int k = 0; k< dimension;k++)
           
for( int j = 0; j< dimension; j++)
               
if(temp[j] == k){
                   
double item = temp[k];
                    temp[k]
= temp[j];
                    temp[j]
= item;
                   
                    item
= diff[k];
                    diff[k]
= diff[j];
                    diff[j]
= item;   
                }
       
int tempDimension = dimension;
       
int tempi = 0;

       
while(tempDimension> 0 ){
           
if(citys[x].city[tempi] == -1){
                citys[x].city[tempi]
= (int)diff[dimension - tempDimension];
               
                tempDimension
--;
            }   
            tempi
++;
        }

        Arrays.sort(diff);

        temp
= gp(y, dimension);

       
for( int k = 0; k< dimension;k++)
           
for( int j = 0; j< dimension; j++)
               
if(temp[j] == k){
                   
double item = temp[k];
                    temp[k]
= temp[j];
                    temp[j]
= item;
                   
                    item
= diff[k];
                    diff[k]
= diff[j];
                    diff[j]
= item;   
                }

        tempDimension
= dimension;
        tempi
= 0;

       
while(tempDimension> 0 ){
           
if(citys[y].city[tempi] == -1){
                citys[y].city[tempi]
= (int)diff[dimension - tempDimension];
               
                tempDimension
--;
            }   
            tempi
++;
        }

    }
   
   
/**
     *
@param individual 个体
     *
@param dimension      维数
     *
@return 佳点集    (用于交叉函数的交叉点)    在executeCrossover()函数中使用
    
*/
   
private double[] gp(int individual, int dimension){
       
double[] temp = new double[dimension];
       
double[] temp1 = new double[dimension];
       
int p = 2 * dimension + 3;

       
while(!isSushu(p))
            p
++;

       
for( int i = 0; i< dimension; i++){
            temp[i]
= 2*Math.cos(2*Math.PI*(i+1)/p) * (individual+1);
            temp[i]
= temp[i] - (int)temp[i];
           
if( temp [i]< 0)
                temp[i]
= 1+temp[i];

        }
       
for( int i = 0; i< dimension; i++)
            temp1[i]
= temp[i];
        Arrays.sort(temp1);   
       
//排序
        for( int i = 0; i< dimension; i++)
           
for( int j = 0; j< dimension; j++)
               
if(temp[j]==temp1[i])
                    temp[j]
= i;   
       
return temp;
    }
   
   
   
/**
     *     变异
    
*/
   
public void mutate(){
       
double random;
       
int temp;
       
int temp1;
       
int temp2;
       
for( int i = 0 ; i< popSize; i++){
            random
= Math.random();
           
if(random<=pmultation){
                temp1
= (int)(Math.random() * (cityNum));
                temp2
= (int)(Math.random() * (cityNum));
                temp
= citys[i].city[temp1];
                citys[i].city[temp1]
= citys[i].city[temp2];
                citys[i].city[temp2]
= temp;

            }
        }       
    }
   
   
/**
     *    打印当前代数的所有城市序列,以及其相关的参数
    
*/
   
public void print(){
   
/**
     * 初始化各城市之间的距离
    
*/
   
private void initDistance(){
       
for (int i = 0; i < cityNum; i++) {
           
for (int j = 0; j < cityNum; j++){
                distance[i][j]
= Math.abs(i-j);
            }
        }
    }
   
   
/**
     * 计算所有城市序列的适应度
    
*/
   
private void CalFitness() {
       
for (int i = 0; i < popSize; i++) {
           
for (int j = 0; j < cityNum - 1; j++)
                citys[i].fitness
+= distance[citys[i].city[j]][citys[i].city[j + 1]];
            citys[i].fitness
+= distance[citys[i].city[0]][citys[i].city[cityNum - 1]];
        }
    }
   
   
/**
     * 计算选择概率
    
*/
   
private void CalSelectP(){
       
long sum = 0;
       
for( int i = 0; i< popSize; i++)
            sum
+= citys[i].fitness;
       
for( int i = 0; i< popSize; i++)
            citys[i].selectP
= (double)citys[i].fitness/sum;

    }
   
   
/**
     * 计算期望概率
    
*/
   
private void CalExceptP(){
       
for( int i = 0; i< popSize; i++)
            citys[i].exceptp
= (double)citys[i].selectP * popSize;
    }
   
   
/**
     * 计算该城市序列是否较优,较优则被选择,进入下一代
    
*/
   
private void CalIsSelected(){
       
int needSelecte = popSize;
       
for( int i = 0; i< popSize; i++)
           
if( citys[i].exceptp<1){
                citys[i].isSelected
++;
                needSelecte
--;
            }
       
double[] temp = new double[popSize];
       
for (int i = 0; i < popSize; i++) {
//            temp[i] = citys[i].exceptp - (int) citys[i].exceptp;
//            temp[i] *= 10;
            temp[i] = citys[i].exceptp*10;
        }
       
int j = 0;
       
while (needSelecte != 0) {
           
for (int i = 0; i < popSize; i++) {
               
if ((int) temp[i] == j) {
                    citys[i].isSelected
++;
                    needSelecte
--;
                   
if (needSelecte == 0)
                       
break;
                }
            }
            j
++;
        }
       
    }
   
   
/**
     *
@param x
     *
@return 判断一个数是否是素数的函数
    
*/
   
private boolean isSushu( int x){
          
if(x<2) return false;
          
for(int i=2;i<=x/2;i++)
          
if(x%i==0&&x!=2) return false;

          
return true;
        }
   
   
/**
     *
@param x 数组
     *
@return x数组的值是否全部相等,相等则表示x.length代的最优结果相同,则算法结束
    
*/
   
private boolean isSame(long[] x){
       
for( int i = 0; i< x.length -1; i++)
           
if(x[i] !=x[i+1])
               
return false;
       
return true;
    }
   
   
/**
     * 打印任意代最优的路径序列
    
*/
   
private void printBestRoute(){
        CalAll();
       
long temp = citys[0].fitness;
       
int index = 0;
       
for (int i = 1; i < popSize; i++) {
           
if(citys[i].fitness<temp){
                temp
= citys[i].fitness;
                index
= i;
            }
        }
        System.out.println();
        System.out.println(
"最佳路径的序列:");
       
for (int j = 0; j < cityNum; j++)
        {
            String cityEnd[]
={cityName[citys[index].city[j]]};
           
for(int m=0;m<cityEnd.length;m++)
            {
                System.out.print(cityEnd[m]
+ " ");
            }
        }
       
           
//System.out.print(citys[index].city[j] + cityName[citys[index].city[j]] + "  ");
           
//System.out.print(cityName[citys[index].city[j]]);
        System.out.println();
    }
   
   
/**
     * 算法执行
    
*/
   
public void run(){
       
long[] result = new long[range];
       
//result初始化为所有的数字都不相等
        for( int= 0; i< range; i++)
            result[i]
= i;
       
int index = 0;        //数组中的位置
        int num = 1;        //第num代
        while(maxgens>0){
            System.out.println(
"-----------------  第  "+num+" 代  -------------------------");
            CalAll();
            print();
            pad();
            crossover();
            mutate();
            maxgens
--;
           
long temp = citys[0].fitness;
           
for ( int i = 1; i< popSize; i++)
               
if(citys[i].fitness<temp){
                    temp
= citys[i].fitness;
                }
            System.out.println(
"最优的解:"+temp);
            result[index]
= temp;
           
if(isSame(result))
               
break;
            index
++;
           
if(index==range)
                index
= 0;
            num
++;
        }
        printBestRoute();
    }
   
   
/**
     *
@param a 开始时间
     *
@param b     结束时间
    
*/
   
public void CalTime(Calendar a,Calendar b){
       
long x = b.getTimeInMillis() - a.getTimeInMillis();
       
long y = x/1000;
        x
= x - 1000*y;
        System.out.println(
"算法执行时间:"+y+"."+x+"");
    }
   
   
/**
     *    程序入口
    
*/
   
public static void main(String[] args) {
       
        Calendar a
= Calendar.getInstance();    //开始时间
        Tsp tsp = new Tsp();
        tsp.run();
        Calendar b
= Calendar.getInstance();    //结束时间
        tsp.CalTime(a, b);
       
    }
}