posts - 32, comments - 153, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          使用遺傳算法求解函數 xyz*sin(xyz)的最大值

          Posted on 2007-04-26 21:41 Zou Ang 閱讀(7049) 評論(14)  編輯  收藏 所屬分類:
          最近學習遺傳算法,寫了這么一個小程序來計算函數 f(x,y,z) = xyz*sin(xyz)的最大值,這段程序經過小小改變就可以適應其他的函數最大值求解問題
          首先介紹一下遺傳算法,遺傳算法就是模擬自然界中物競天擇,適者生存的法則,通過對解空間進行進化從而求得最優方案的方法,遺傳算法的好處在于,即使算法中的某些參數不起作用了,整個算法還是可以正常地工作,也就是說,整體種群的走向是越來越好的
          遺傳算法的關鍵內容包括:
          1. 染色體
              首先對優化問題的解進行編碼,編碼后的一個解被稱為一個染色體,組成染色體的元素稱為基因。比如對于上面那個函數,我們就可以用24位的2進制串進行編碼,首先8位2進制數代表x,中間為y,最后為z,x,y,z都屬于[0,255]
          2. 交配
              將兩個染色體進行交叉的操作被稱為交配,交配可能提高染色體的適應值,也可能降低其適應值。通常交配是以一定的概率發生的。在程序中,我們通過隨機交換兩個染色體的一些位來體現。
          3. 適應函數
              我們需要使用一個函數來表現解的優異程度,這個函數只要可以反映出解的優劣即可,沒必要很精確。適應函數就類似我們生存的環境,環境評估我們的生存能力,評估值高的更容易存活。
          4. 變異
              有時候種群中的某些個體會發生變異的現象,變異一般是以很小的概率發生的,但是變異增加了種群進化的不確定性,也讓種群中的個體類型更加豐富。在程序中,我們用隨機變化某一位來體現。

          算法的流程為:
          1.初始化種群
          2.進行第一輪評估
          3.交配
          4.變異
          5.評估
          6.重新選擇種群
          7.若未達到結束條件,轉3

          隨機數生成器:
          package edu.zsu.zouang.util;

          import java.util.Random;

          public class Randomizer {
              
          private int lower;
              
          private int upper;
              
              
          private static Random random = new Random();
              
              
          public Randomizer(int lower, int upper){
                  
          if(upper <= lower){
                      
          throw new IllegalStateException("Upper is smaller than lower!");
                  }

                  
          this.lower = lower;
                  
          this.upper = upper;
              }

              
          public Double nextDouble(){
                  
          return Double.valueOf(lower + (upper - lower) * random.nextDouble());
              }

              
              
          public Integer nextInteger(){
                  
          return Integer.valueOf(lower +random.nextInt(upper - lower));
              }

              
              
          public char[] nextBitArray(int length){
                  
          if(length <= 0){
                      
          throw new IllegalStateException("Length is less than ZERO!");
                  }

                  
          char[] temp = new char[length];
                  
          for(int i = 0; i < length ; i++){
                      temp[i] 
          = random.nextBoolean() ? '1' : '0';
                  }

                  
          return temp;
              }

          }


          染色體:
          package edu.zsu.zouang.inheritence;

          import java.util.Arrays;

          import edu.zsu.zouang.util.Randomizer;

          public class Chromosome implements Cloneable{
              
          private double fitness = -1//代表未計算適應函數
              
              
          private double select = -1// 選擇概率
              
              
          private char[] chromo; //染色體串
              
              
          private Randomizer random;
              
              
          private int lower;
              
              
          private int upper;
              
              
          public Chromosome(int lower, int upper, int length){
                  
          this.lower = lower;
                  
          this.upper = upper;
                  random 
          = new Randomizer(lower, upper);
                  chromo 
          = random.nextBitArray(length);
              }


              
          /**
               * 克隆一個染色體
               
          */

              
          public Chromosome clone(){
                  Chromosome c 
          = new Chromosome(lower,upper,chromo.length);
                  
          char[] temp = new char[c.chromo.length];
                  System.arraycopy(chromo, 
          0, temp, 0, chromo.length);
                  c.setChromo(temp);
                  
          return c;
              }

              
          public char[] getChromo() {
                  
          return chromo;
              }


              
          public void setChromo(char[] chromo) {
                  
          this.chromo = chromo;
              }


              
          public double getFitness() {
                  
          return fitness;
              }


              
          public void setFitness(double fitness) {
                  
          this.fitness = fitness;
              }


              
          public double getSelect() {
                  
          return select;
              }


              
          public void setSelect(double select) {
                  
          this.select = select;
              }

              
              
          }


          適應函數接口:
          package edu.zsu.zouang.inheritence;

          public interface FitnessCalculate {
              
          public double calculate(char[] chromosome);
          }


          本函數的適應函數,既然是求最大值,干脆用求解的函數來做適應函數
          package edu.zsu.zouang.inheritence;

          /**
           * 計算xyz*sin(xyz)最大值的遺傳函數適應值
           * 2007-4-25
           * 
          @author Zou Ang
           * Contact <a href ="mailto:richardeee@gmail.com">Zou Ang</a>
           
          */

          public class FunctionFitness implements FitnessCalculate {

              
              
          public double calculate(char[] chromosome) {
                  
          /*
                   * x、y、z都用8位來編碼,即x,y,z都屬于[0,255]
                   
          */

                  
          double x = 0;
                  
          double y = 0;
                  
          double z = 0;
                  
          for(int i = 0; i < 8; i++){
                      
          int j = i + 8;
                      
          int k = i + 16;
                      x 
          = x + Math.pow(27 - i) * (Integer.valueOf(chromosome[i]) - 48);
                      y 
          = y + Math.pow(27 - i) * (Integer.valueOf(chromosome[j]) - 48);
                      z 
          = z + Math.pow(27 - i) * (Integer.valueOf(chromosome[k]) - 48);
                  }

                  
          return x * y * z * Math.sin(x*y*z);
              }


          }

          種群詳細信息類:
          package edu.zsu.zouang.inheritence;

          public class GenerationDetail {
              
          private double averageFitness = 0.0;
              
              
          private double maxFitness = 0.0;
              
              
          private double minFitness = 0.0;

              
          public double getAverageFitness() {
                  
          return averageFitness;
              }


              
          public void setAverageFitness(double averageFitness) {
                  
          this.averageFitness = averageFitness;
              }


              
          public double getMaxFitness() {
                  
          return maxFitness;
              }


              
          public void setMaxFitness(double maxFitness) {
                  
          this.maxFitness = maxFitness;
              }


              
          public double getMinFitness() {
                  
          return minFitness;
              }


              
          public void setMinFitness(double minFitness) {
                  
          this.minFitness = minFitness;
              }

              
              
          }


          最后是主類:
          package edu.zsu.zouang.inheritence;

          import java.util.ArrayList;
          import java.util.List;

          import edu.zsu.zouang.util.Randomizer;

          public class GeneticAlgorithm {
              
              
          private int generation; //進化代數
              
              
          private int population; //種群數量
              
              
          private double crossoverPossibility; //繁殖概率
              
              
          private double mutationPossibility; //變異概率
              
              
          private FitnessCalculate calculator = new FunctionFitness(); //適應函數計算
              
              
          private List<Chromosome> clist = new ArrayList<Chromosome>();
              
              
          private Randomizer random1; //隨機數生成器1,用于生成變異位和交配位
              
              
          private Randomizer random2 = new Randomizer(0,1); //隨機數生成器2,用于生成0-1之間的概率
              
              
          private GenerationDetail detail = new GenerationDetail();
              
              
          public GeneticAlgorithm(int population, double sp, double cp, double mp,int length){
                  
          this.population = population;
                  
          this.crossoverPossibility = cp;
                  
          this.mutationPossibility = mp;
                  random1 
          = new Randomizer(0,length - 1);
                  generatePopulation(
          0,255,length); //用24位表示一組x,y,z的值
              }

              
              
          /**
               * 生成初始種群
               * 
          @param lower
               * 
          @param upper
               * 
          @param length
               
          */

              
          private void generatePopulation(int lower, int upper, int length){
                  
          //隨機生成染色體
                  for(int i = 0; i < population; i ++){
                      clist.add(
          new Chromosome(lower,upper,length));
                  }

                  
          //計算染色體的適應值
                  evaluate();
              }

              
              
          /**
               * 計算群體的適應值
               
          */

              
          private void evaluate(){
                  
          double sum = 0.0;
                  
          double min = Double.MAX_VALUE;
                  
          double max = Double.MIN_VALUE;
                  
          for(Chromosome c : clist){
                      
          double fitness = calculator.calculate(c.getChromo());
                      
          if(fitness > max){
                          max 
          = fitness;
                      }

                      
          if(fitness < min){
                          min 
          = fitness;
                      }

                      c.setFitness(fitness);
                      sum 
          += fitness;
                  }

                  detail.setMaxFitness(max);
                  detail.setMinFitness(min);
                  detail.setAverageFitness(sum
          /population);
                  
          for(Chromosome c : clist){
                      c.setSelect((c.getFitness())
          /sum);    //設置選擇概率
                  }

              }

              
              
          /**
               * 在后代中選擇新種群
               
          */

              
          private void selectPopulation(){
                  List
          <Chromosome> tempList = new ArrayList<Chromosome>();
                  
          for(Chromosome c : clist){
                      
          long expectation = Math.round(c.getSelect() * population);
                      
          for(int i = 0; i < expectation; i ++){
                          tempList.add(c.clone());
                      }

                  }

                  
          //如果選擇種群數量大于種群規定數量,則淘汰適應值最小的染色體
                  while(tempList.size() > population){
                      
          int location = 0;
                      
          double min = tempList.get(0).getFitness();
                      
          for(int i = 0 ; i < tempList.size(); i ++){
                          
          if(tempList.get(i).getFitness() < min){
                              location 
          = i;
                          }

                      }

                      tempList.remove(location);
                  }

                  
          //如果選擇種群數量小于種群規定數量,則加入適應值最大的染色體
                  while(tempList.size() < population){
                      
          int location = 0;
                      
          double max = tempList.get(0).getFitness();
                      
          for(int i = 0; i < tempList.size(); i++){
                          
          if(tempList.get(i).getFitness() > max){
                              location 
          = i;
                          }

                      }

                      tempList.add(tempList.get(location).clone());
                  }

                  clist 
          = tempList;
              }

              
              
          /**
               * 交配兩個染色體
               * 
          @param c1
               * 
          @param c2
               * 
          @param location
               
          */

              
          private void crossover(Chromosome c1, Chromosome c2){
                  
          if(c1.getChromo().length != c2.getChromo().length){
                      
          throw new IllegalStateException("染色體長度不同!");
                  }

                  
          //交換染色體上的基因
                  
          //隨機確定交配位
                  int location = random1.nextInteger();
                  
          for(int i = location ; i < c1.getChromo().length; i ++){
                      
          char temp;
                      temp 
          = c1.getChromo()[i];
                      c1.getChromo()[i] 
          = c2.getChromo()[i];
                      c2.getChromo()[i] 
          = temp;
                  }

              }

              
              
          /**
               * 交配整個種群,完成一次進化
               *
               
          */

              
          public void crossoverPopulation(){
                  
          for(int j = 0; j < population; j ++){
                      
          for(int i = 0; i < population - 1; i++){
                          
          double temp = random2.nextDouble();
                          
          if(temp < crossoverPossibility){//在交配概率之內
                              crossover(clist.get(i), clist.get(i + 1));
                          }

                      }

                      
          double mutation = random2.nextDouble();
                      
          if(mutation < mutationPossibility){//在變異概率之內
                          mutation(clist.get(j));
                      }

                  }

                  
          //重新計算群體適應值
                  evaluate();
                  
          //重新選擇種群
                  selectPopulation();
                  generation 
          ++;
              }

              
              
          //隨機變異一位
              private void mutation(Chromosome ch){
                  
          int location = random1.nextInteger();
                  
          char c = ch.getChromo()[location];
                  
          if(c == '1'){
                      ch.getChromo()[location] 
          = '0';
                  }
          else{
                      ch.getChromo()[location] 
          = '1';
                  }

              }

              
              
          public void printDetail(){
                  System.out.println(
          "/*****************************************");
                  System.out.println(
          "*           -----遺傳算法報告-----                 ");
                  System.out.println(
          "*  當前是第" + generation + "");
                  System.out.println(
          "*  當前種群平均適應值為: " + detail.getAverageFitness());
                  System.out.println(
          "*  其中最大適應值為:" + detail.getMaxFitness());
                  System.out.println(
          "*  其中最小適應值為:" + detail.getMinFitness());
                  System.out.println(
          "*******************************************/");
              }

              
              
          public static void main(String[] args){
                  
          //種群數量:30
                  
          //選擇概率:0.0
                  
          //交配概率:0.9
                  
          //變異概率: 0.01
                  GeneticAlgorithm ga = new GeneticAlgorithm(30,0.0,0.9,0.01,24);
                  
          for(int i = 0; i < 5; i ++){
                      ga.crossoverPopulation();
                  }

                  ga.printDetail();
                  
          for(int j = 0; j < 25; j++){
                      ga.crossoverPopulation();
                  }

                  ga.printDetail();
                  
          for(int k = 0; k < 1000; k++){
                      ga.crossoverPopulation();
                  }

                  ga.printDetail();
              }

          }


          輸出的結果是
          /*****************************************
          *           -----遺傳算法報告-----                 
          *  當前是第5代
          *  當前種群平均適應值為: 7592451.0488077225
          *  其中最大適應值為:9031331.437029611
          * 對應最大適應值的染色體為:111011101101010010111000
          *  其中最小適應值為:-1.2521097155031694E7
          * 其中對應最小適應值的染色體為111011101101010011111011
          ******************************************
          */

          /*****************************************
          *           -----遺傳算法報告-----                 
          *  當前是第30代
          *  當前種群平均適應值為: 8785113.746617064
          *  其中最大適應值為:9836674.727850026
          * 對應最大適應值的染色體為:111111101101010010111000
          *  其中最小適應值為:-1.1676031572464054E7
          * 其中對應最小適應值的染色體為111011101101010011111000
          ******************************************
          */

          /*****************************************
          *           -----遺傳算法報告-----                 
          *  當前是第1030代
          *  當前種群平均適應值為: 8763072.724911185
          *  其中最大適應值為:9836674.727850026
          * 對應最大適應值的染色體為:111111101101010010111000
          *  其中最小適應值為:-9580464.117842415
          * 其中對應最小適應值的染色體為111101101101010010111000
          ******************************************
          */


          示例程序見:
          http://www.aygfsteel.com/richardeee/archive/2007/04/29/114536.html

          評論

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值  回復  更多評論   

          2007-04-27 09:50 by 王凌華
          第一次聽說。請問LZ這東西能用到嗎,在我們實際的開發中? 謝謝. :)

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值  回復  更多評論   

          2007-04-27 12:11 by Zou Ang
          @王凌華
          在實際的開發中,是可以用到的。但是要看具體的情況。比如波音飛機螺旋槳的扇片設計就用到了遺傳算法,還有比如求路徑最短問題,在非常大的圖中尋找最短路徑,遺傳算法就是非常好的選擇了。對于復雜的優化問題,遺傳算法都是比較好的選擇

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值  回復  更多評論   

          2007-04-28 08:26 by brucelee521
          好文章。

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值  回復  更多評論   

          2007-04-28 09:04 by my name
          不懂啊 有空看看

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值  回復  更多評論   

          2007-04-28 11:45 by hooooo
          沒看明白,也沒仔細看

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值  回復  更多評論   

          2007-04-28 15:15 by lancey
          感覺還不錯,有機會看看

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值  回復  更多評論   

          2007-07-27 22:30 by 車薩莉
          好專業的頁面。。好恐怖。。

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值  回復  更多評論   

          2008-09-15 17:45 by m.dreamfly
          double min = Double.MAX_VALUE;
          double max = Double.MIN_VALUE;
          ??

          it's right?

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值  回復  更多評論   

          2008-12-26 20:38 by lavender314
          要怎么樣改改就能編程求 f(x)=x*x x屬于[0,31]的最大值呢
          改好了麻煩你發到我郵箱吧 lavender314@126.com 謝謝

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值[未登錄]  回復  更多評論   

          2009-05-13 10:27 by yuan
          LZ好啊,能發我一下遺傳算法實現的Java代碼嗎?我正在寫用遺傳算法解決庫存管理方面的論文,萬分感謝!!!yuankunbo@sina.com

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值  回復  更多評論   

          2009-12-25 10:15 by huhu
          麻煩問下樓主二進制編碼串的長度如何確定??謝謝

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值[未登錄]  回復  更多評論   

          2010-07-08 16:55 by sunny
          樓主好文章!我有一點疑問,就是我們在使用遺傳算法的時候大都直接隨機生成解,如果想要自己生成一個存在規定個數規定解的解空間,應該怎么實現呢?
          yangguang760@gmail.com
          望不吝賜教

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值  回復  更多評論   

          2010-12-14 20:17 by chuanwang66
          樓主您好!我每次運行這個程序時都有不同的結果,怎么才能得到一個比較收斂的結果呢?

          # re: 使用遺傳算法求解函數 xyz*sin(xyz)的最大值[未登錄]  回復  更多評論   

          2013-05-11 16:35 by fanfan
          請問你改好的那個實現了么,同求@lavender314
          主站蜘蛛池模板: 曲靖市| 镇安县| 清水县| 灵武市| 三亚市| 岳池县| 大足县| 平罗县| 宁强县| 宝丰县| 湖北省| 衡阳市| 兰溪市| 如皋市| 广灵县| 陆良县| 宁化县| 辉南县| 禄丰县| 神池县| 和平县| 南投市| 全州县| 遵义市| 泰来县| 开阳县| 竹北市| 襄垣县| 东平县| 大荔县| 涿鹿县| 五常市| 连州市| 资兴市| 陆川县| 颍上县| 高邮市| 乌审旗| 山西省| 台东县| 宜宾市|