[原]遗传算法Java实现源代码

【Title】[原]遗传算法Java实现源代码
【Date】2013-04-07
【Abstract】以前学习遗传算法时,用Java实现的遗传算法程序,现整理分享出来。
【Keywords】wintys、遗传、算法、algorithm、种群、基因、个体、进化、染色体、适应度、Rosenbrock
【Environment】Windows 7、PowerDesigner16
【Author】wintys (wintys@gmail.com) http://wintys.cnblogs.com
【URL】http://www.cnblogs.com/wintys/archive/2013/04/07/genetic_algorithms.html

【Content】:

1、简介

    此程序是对照《遗传算法原理及应用》(周明、孙树栋编著),附录所列C程序改编而来,用Java实现的遗传算法程序。相关理论请参考《遗传算法原理及应用》。

2、类图

    类图由源代码经PowerDesigner反向生成。

 

 

   (类图)

3、代码

3.1、染色体

    //染色体:Chromesone.java
    class Chromosome implements Cloneable{
        private StringBuffer chromosome;
        private int chromosomeLength;//染色体长度
        private char defaultChar; //默认基因填充字符
        
        public Chromosome(int chromosomeLength){
            chromosome = new StringBuffer(chromosomeLength);
            chromosome.setLength(chromosomeLength);
            defaultChar = '0';
            this.chromosomeLength = chromosomeLength;
        }
        
        //设置基因
        public boolean setGene(int begin , int end , String gene){
            int len = gene.length();
            
            if(len > end - begin + 1)
                return false;
                
            //index => chromosome , idx => gene
            for (int index = begin , idx = 0; index <= end; index++ , idx++) {
                if(idx < len)
                    chromosome.setCharAt(index , gene.charAt(idx));
                else
                    chromosome.setCharAt(index , defaultChar);
            }
            
            return true;    
        }
        
        //获取基因
        public String getGene(int begin , int end){
            char[] dest = new char[end - begin + 1];
            chromosome.getChars(begin , end + 1 , dest , 0);

            return new String(dest);        
        }
        
        public int getLength(){
            return chromosomeLength;
        }
        
        public String toString(){
            return chromosome.toString();
        }
        
        @Override
        public     Object clone()throws CloneNotSupportedException{
            Chromosome c = null;
            try{
                c = (Chromosome)super.clone();
                c.chromosome = new StringBuffer(chromosome);
            }catch(CloneNotSupportedException e ){
                System.out.println(e.getMessage());
            }

            return c;    
        }
    }

3.2、个体

3.2.1、抽象个体

    //Individual.java
    abstract class Individual implements Cloneable{
        protected Chromosome chrom;//个体基因型:一个基因型染色体由多个基因组成
        protected int genelen;//基因长度
        protected double fitness;//适应度
        protected double targetValue;//目标函数值
        
        public abstract void coding();//编码
        public abstract void decode();//解码
        public abstract void calFitness();//计算个体适应度
        public abstract void generateIndividual();//随机产生个体
        public abstract void calTargetValue();//获取目标函数值
        
        public double getFitness(){
            return fitness;
        }
        
        public double getTargetValue(){
            return targetValue;
        }
        
        public int getChromlen(){
            return chrom.getLength();
        }
        
        public boolean setChrom(int begin , int end , String gene){
            return chrom.setGene(begin,end,gene);
        }
        
        public String getChrom(int begin , int end){
            return chrom.getGene(begin,end);
        }
        
        public void mutateSingleBit(int index){
            String gene , gn;
            gene = chrom.getGene(index , index);
            gn = gene.equals("0") ? "1":"0";
            chrom.setGene(index , index , gn);
        }
        
        @Override
        public Object clone(){
            Individual indv = null;
            
            try{
                indv = (Individual)super.clone();
                indv.chrom = (Chromosome)chrom.clone();
            }catch(CloneNotSupportedException e ){
                System.out.println(e.getMessage());
            }
            
            return indv;
        }
    }

3.2.2、Rosenbrock个体实现

    //RosenbrockIndividual.java
    class RosenbrockIndividual extends Individual {
        private double x1 , x2; // 个体表现型
        //基因型chromosome由 (x1 , x2)编码而成
        
        RosenbrockIndividual(int chromlen){
            genelen = 10;
            chrom = new Chromosome(chromlen);
        }
        
        //编码
        public void coding(){
            String code1,code2;
            code1 = codingVariable(x1);
            code2 = codingVariable(x2);
            
            chrom.setGene(0 , 9 , code1);
            chrom.setGene(10, 19 , code2);
        }
        
        //解码
        public void decode(){
            String gene1,gene2;
            
            gene1 = chrom.getGene(0 , 9);
            gene2 = chrom.getGene(10 , 19);
            
            x1 = decodeGene(gene1);
            x2 = decodeGene(gene2);
        }
        
        //计算目标函数值
        public  void calTargetValue(){
            decode();
            targetValue = rosenbrock(x1 , x2);
        }
        
        //计算个体适应度
        public void calFitness(){
            fitness = getTargetValue();
        }
        
        private String codingVariable(double x){
            double y = (((x + 2.048) * 1023) / 4.096);
            String code = Integer.toBinaryString((int) y);
            
            StringBuffer codeBuf = new StringBuffer(code);
            for(int i = code.length(); i<genelen; i++)
                codeBuf.insert(0,'0');
                
            return codeBuf.toString();
        }
        
        private double decodeGene(String gene){
            int value ;
            double decode;
            value = Integer.parseInt(gene, 2);
            decode = value/1023.0*4.096 - 2.048;
            
            return decode;
        }
            
        public String toString(){
            String str = "";
            ///str = "基因型:" + chrom + "  ";
            ///str+= "表现型:" + "[x1,x2]=" + "[" + x1 + "," + x2 + "]" + "\t";
            str+="函数值:" + rosenbrock(x1 , x2) + "\n";
            
            return     str;    
        }
        
        /**
         *Rosenbrock函数:
         *f(x1,x2) = 100*(x1**2 - x2)**2 + (1 - x1)**2
         *在当x在[-2.048 , 2.048]内时,
         *函数有两个极大点:
         *f(2.048 , -2.048) = 3897.7342
         *f(-2.048,-2.048) = 3905.926227
         *其中后者为全局最大点。
         */
        public static double rosenbrock(double x1 , double x2){
            double fun;
            fun = 100*Math.pow((x1*x1 - x2) , 2) + Math.pow((1 - x1) , 2);
            
            return fun;
        }
        
        //随机产生个体
        public void generateIndividual(){
            x1 = Math.random() * 4.096 - 2.048;
            x2 = Math.random() * 4.096 - 2.048;
            
            //同步编码和适应度
            coding();
            calTargetValue();
            calFitness();
        }
    }

3.3、种群

    //Population.java
    class Population{
        private int generation; //种群的代数
        private int size;            //群体大小
        private Individual[] pop;   //种群
        private double averageFitness;    //平均适应度
        private double[] relativeFitness;    //相对适应度
        private int chromlen;//基因长度
        Individual bestIndividual;//当前代适应度最好的个体
        Individual worstIndividual;//当前代适应度最差的个体
        Individual currentBest;//到目前代为止最好的个体
        private int worstIndex;//bestIndividual对应的数组下标

        
        public Population(int size){
            this.generation = 0;
            this.size = size;
            
            this.pop = new Individual[size];
            this.averageFitness = 0;
            this.relativeFitness = new double[size];
            this.chromlen = 20;
            
            for(int i = 0; i < size; i++){
                pop[i] = new RosenbrockIndividual(chromlen);
            }
        }
        
        
        //初始化种群
        public void initPopulation(){
            for(int i = 0;i < size;i++){
                pop[i].generateIndividual();
            }
            
            findBestAndWorstIndividual();                
        }

        //----------------------------------------------------
        //比例选择
        public void  select(){
            double[] rouletteWheel; //赌盘
            Individual[] childPop = new Individual[size];
            
            calRelativeFitness();
            
            //产生赌盘
            rouletteWheel  = new double[size];
            rouletteWheel[0] = relativeFitness[0];
            for(int i=1;i<size -1;i++){
                rouletteWheel[i] = relativeFitness[i] + rouletteWheel[i - 1];
            }
            rouletteWheel[size - 1] = 1;
            
            //进行赌盘选择,产生新种群
            for(int i = 0;i < size ; i++){
                double rnd = rand();
                for(int j = 0; j < size; j++){
                    if(rnd < rouletteWheel[j]){
                        childPop[i] = pop[j];
                        break;
                    }    
                }        
            }
            
            for(int i = 0;i < size; i++){
                pop[i] = childPop[i];
            }
            
            //return     childPop;
        }
        
        //求总适应度
        private double calTotalFitness(){
            double total = 0;
            for(int i = 0 ; i < size ;i++)
                total += pop[i].getFitness();
            return total;
        }
            
        //计算相对适应度
        public double[] calRelativeFitness(){
            double totalFitness = calTotalFitness();
            for(int i = 0 ;i < size ; i++){
                relativeFitness[i] = pop[i].getFitness() / totalFitness;    
            }
            
            return relativeFitness;
        }
        
        //================================
        
        //------------------------------------------------------
        //单点交叉
        public void crossover(){
            for(int i = 0 ; i < size/2*2; i+=2){
                int rnd;
                //随机两两配对
                rnd = rand(i , size);

                if(rnd != i)
                    exchange(pop , i , rnd);
                    
                rnd = rand(i , size);
                if(rnd != i+1)
                    exchange(pop , i + 1 , rnd);    
                        
                //交叉
                double random = rand();

                if(random < GeneticAlgorithms.crossoverRate){
                    cross(i);
                }            
            }
        }
        
        //执行交叉操作
        private void cross(int i){
            String chromFragment1,chromFragment2;//基因片段
            
            int rnd = rand(0 , getChromlen() - 1);//交叉点为rnd之后,可能的位置有chromlen - 1个.
            chromFragment1 = pop[i].getChrom(rnd + 1 , getChromlen() - 1);
            chromFragment2 = pop[i+1].getChrom(rnd + 1 , getChromlen() - 1);
                
            pop[i].setChrom(rnd + 1 , getChromlen() - 1 , chromFragment2);
            pop[i+1].setChrom(rnd + 1 , getChromlen() - 1 , chromFragment1);            
        }
        
        //产生随机数
        private int rand(int start , int end){//产生区间为[start , end)的随机整数
            return (int)(rand()*(end - start) + start);
        }
        
        //交换
        private void exchange(Individual[] p ,int src , int dest){
            Individual temp;
            temp = p[src];
            p[src] = p[dest];
            p[dest] = temp;    
        }
        //==============================

        //-----------------------------------------------------
        //变异
        public void mutate(){
            for(int i = 0 ; i < size;i++){
                for(int j = 0 ;j < getChromlen(); j++){
                    if(rand() < GeneticAlgorithms.mutateRate){
                        pop[i].mutateSingleBit(j);
                        ///System.out.print("变异"+ i +" - "+ j + "  ");///
                    }    
                }
            }
        }
        //==============================
        
        //-----------------------------------------------------
        //进化
        public void evolve(){
            select();
            crossover();
            mutate();
            evaluate();    
        }
        
        
        //==============================
        //计算目标函数值、适应度、找出最优个体。
        public void evaluate(){
            //同步目标函数值和适应度
            for(int i = 0; i < size; i++){
                pop[i].calTargetValue();
                pop[i].calFitness();
            }
            
            //使用最优保存策略(Elitist Model)保存最优个体
            findBestAndWorstIndividual();
            pop[worstIndex] = (Individual)currentBest.clone();
            
            generation++;    
        }    
        //找出适应度最大的个体
        public void findBestAndWorstIndividual(){
            bestIndividual = worstIndividual = pop[0];
            for(int i = 1; i <size;i++){
                if(pop[i].fitness > bestIndividual.fitness){
                    bestIndividual = pop[i];
                }
                if(pop[i].fitness < worstIndividual.fitness){
                    worstIndividual = pop[i];
                    worstIndex = i;
                }
            }
        
            if( generation == 0 ){//初始种群
                currentBest = (Individual)bestIndividual.clone();
            }else{
                if(bestIndividual.fitness > currentBest.fitness)
                    currentBest = (Individual)bestIndividual.clone();
            }
        }
        
        //判断进化是否完成
        public boolean isEvolutionDone(){
            if(generation < GeneticAlgorithms.maxGeneration)
                return false;
            return true;    
        }
            
        //计算平均适应度
        public double calAverageFitness(){
            for(int i = 0 ; i < size; i++){
                averageFitness += pop[i].getFitness();
            }
            averageFitness/=size;
                
            return averageFitness;
        }
                    
        //产生随机数
        private double rand(){
            return Math.random();
        }
        
        public int getChromlen(){
            return chromlen;
        }
        
        public void setGeneration(int generation){
            this.generation = generation;
        }
        
        public int getGeneration(){
            return generation;
        }
        /*
        public String printPop(Individual[] pop){
            String str="";
            for(int i = 0 ; i < size ; i++)
                str += pop[i];
            return str;
        }*/
        
        public String toString(){
            String str="";
            for(int i = 0 ; i < size ; i++)
                str += pop[i];
            return str;
        }    
    }

3.4 测试

    //GeneticAlgorithms.java 给定参数,测试遗传算法
    import java.io.*;
    //2008-11-21
    class GeneticAlgorithms{
        public static double crossoverRate;//交叉概率
        public static double mutateRate;//变异概率
        public static int maxGeneration;//进化代数
        public static int populationSize;//群体大小
        
        static {
            //crossoverRate = 0.6;
            //mutateRate = 0.001;
            //maxGeneration  = 100;
            //populationSize = 500;
            maxGeneration  = 100;
            populationSize = 500;
            crossoverRate = 0.6;
            mutateRate = 0.001;
        }
        
        public static void main(String[] args)throws IOException{

            FileWriter fw = new FileWriter("result.txt");
            BufferedWriter bw = new BufferedWriter(fw);
            PrintWriter pw = new PrintWriter(bw);
            
            Population pop = new Population(populationSize);
            pop.initPopulation();

            pw.println("初始种群:\n" + pop);
            while(!pop.isEvolutionDone()){
                pop.evolve();
                pw.print("第" + pop.getGeneration() + "代Best:" + pop.bestIndividual );
                pw.print("第" + pop.getGeneration()  + "代current:" + pop.currentBest );
                pw.println("");        
            }
            pw.println();
            pw.println("第"+ pop.getGeneration()  + "代群体:\n" + pop);

            pw.close();
        }
        
        public void print(){

        }
    }

【Reference】
[1]《遗传算法原理及应用》(周明、孙树栋编著)

【Attachment】

 

posted @ 2013-04-07 13:25  wintys  阅读(8812)  评论(2编辑  收藏  举报