[原]遺傳算法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】

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM