自話遺傳算法(帶實例)


簡介

    好像有那么點空閑時間,那就寫點東西吧,由於近期一個項目用到了遺傳算法,粒子群算法,蟻群算法等啟發式智能搜索算法,今天先以本人的觀點去闡述遺傳算法,僅作自己對知識點的回顧,和給大家一點參考的意見,其他算法以后有時間再作描述。

    遺傳算法(Genetic Algorithm)是模擬達爾文生物進化論的自然選擇和遺傳學機理的生物進化過程的計算模型,是一種通過模擬自然進化過程搜索最優解的方法,它最初由美國Michigan大學J.Holland教授於1975年首先提出來的,並出版了頗有影響的專著《Adaptation in Natural and Artificial Systems》,GA這個名稱才逐漸為人所知,J.Holland教授所提出的GA通常為簡單遺傳算法(SGA),這里我就直接摘抄百度百科了。

術語

    種群(population)

    基因(gene)

    染色體(chromosome)

    表現型(phenotype)

    編碼(codeing)

    解碼(decodeing)

    交叉( Crossover )

    突變 ( Mutation )

基本思想

    正如簡介所描述的那樣,遺傳算法是模擬達爾文的進化論思想,我想"生存競爭,適者生存"正好簡要的闡述了這一算法的基本特質。用適應函數去考核每個基因的生存能力,用選擇交叉變異去實現進化,搜索出種群的近似最優解,其主要步驟如下:

  • 初始化種群
  • 適應選擇
  • 交叉變異
  • 迭代

算法描述

    為了更好的描述,這里我以一個01背包問題為例子來簡單的闡述遺傳算法。

    給定一個背包C=100,N=5個物品,其重量和價值分別如下,求這個背包能裝的最大價值是多少

 

1     77 92
2     22 22
3     29 87
4     50 46
5     99 90

 

 

 

 

    那么針對上面這個問題,首先我們要考慮編碼,也就是把它轉換成我們的基因型的形式,這里,我們用一個長度為5的二進制字符串表示相應物品的取舍。其基因型(染色體)就是10100,那么表現型就是選擇了1號物品和3號物品。有編碼自然就有解碼,就是把基因型轉換成表現型,編碼個人認為是遺傳算法中至關重要的一步,怎么根據問題去選擇編碼方式,直接影響了后面所提到的適應函數的簡與復雜。

    把問題映射到基因型上我們已經解決了,現在就是怎么去考核一個基因型對當前環境的適應度,換句話說就是更有可能存活遺傳下去,那么這里我們必須得設計一個適應函數f,因為是求背包的最大值,又因為不能超過背包所能承受的總重量,所以用h(x)表示第二個不超過總重量的條件,f(y)表示背包的價值,所以得到適應函數f(h(x))。

    然后就是怎么去選擇的問題,我們用p(x)=f(y)/totall(f(y))來表示某個基因型占總體的概率,現在我們就采用輪盤賭的方法,什么是輪盤賭呢,這里簡要提及一下,我們把各個概率放在一個輪盤里,然后轉動這個輪盤,最后輪盤停止,指針停在哪里就代表選擇哪個概率的事件。

    比如在01背包中,我們根據適應函數算出各個基因型的適應度,也算出了每個基因型所占的比例,然后我們根據輪盤賭的方法從中選擇出n條基因型出來,然后n條基因型隨機兩兩配對交叉產生兩個子代。

交叉

    那么什么是交叉呢,和生物學中染色體交叉是一樣的概念,就是互換某一段基因,如下圖,這里我們采用的是單點交叉。

變異

    變異是指,在某一個比較小的概率下,某個基因在遺傳時,某個基因座上的基因由0邊成1,或者由1變成0。

    新產生的基因型,如果原來的種群中沒有的話,就加進這個種群,然后再按上面所述去迭代,直到找到我們比較滿意的基因型為止,現在我們什么都准備好了,就讓它們去交配把,去創建一個種族吧。

下面給出按照上面的例子我臨時打的代碼.

  1 package artiano.ga;
  2 
  3 import java.util.HashMap;
  4 import java.util.Iterator;
  5 import java.util.LinkedList;
  6 import java.util.List;
  7 import java.util.Map;
  8 import java.util.Set;
  9 
 10 class Chromosome{
 11     String key;
 12     double f;
 13     double p;
 14     public Chromosome(String key,double f,double p){
 15         this.key=key;
 16         this.f=f;
 17         this.p=p;
 18     }
 19     public Chromosome(Chromosome o){
 20         this.key=o.key;
 21         this.f=o.f;
 22         this.p=o.p;        
 23     }
 24 }
 25 
 26 public class GAtest { 
 27     public Map<String,Chromosome> SAVE=new HashMap<String,Chromosome>();
 28     public List<Chromosome> list;
 29     public double[][] B={
 30             {77,92},
 31             {22,22},
 32             {29,87},
 33             {50,46},
 34             {99,90}
 35     };
 36     private double M=100;
 37     private int N=5;
 38     
 39     public double toPhenotype(String key){ //解碼成表現型
 40 
 41         double count=0;
 42         for(int i=0;i<key.length();i++){
 43             double tmp=0;
 44             if(key.charAt(i)=='1'){
 45                 tmp+=B[i][1];
 46             }
 47             count+=tmp;
 48         }
 49         return count;        
 50     }
 51     public void init(int n){ //這里的初始化種族應該是隨機的,這里為了簡單起見,我隨便給了一組
 52         SAVE.put("10000", new Chromosome("10000",0,0));
 53         SAVE.put("01100", new Chromosome("01100",0,0));
 54         SAVE.put("00001", new Chromosome("00001",0,0));
 55         SAVE.put("01010", new Chromosome("01010",0,0));
 56         
 57     }
 58     public String lunpandu(){  //輪盤賭
 59         double nowP=Math.random();
 60         Set<String> keySet=SAVE.keySet();
 61         Iterator it=keySet.iterator();
 62         double m=0;
 63         while(it.hasNext()){
 64             String key=(String)it.next();
 65             Chromosome o=SAVE.get(key);
 66             m+=o.p;
 67             if(nowP<=m) return key;
 68         }
 69         return "";
 70     } 
 71     public Chromosome selected(){  //選擇
 72         Set<String> keySet=SAVE.keySet();
 73         Iterator it=keySet.iterator();
 74         double count=0;
 75         Chromosome max=new Chromosome("-1",0,0);
 76         while(it.hasNext()){
 77             String key=(String)it.next();
 78             Chromosome o=SAVE.get(key);
 79             count+=o.f=toPhenotype(key);
 80             if(o.f>max.f) max=o;
 81         }
 82         it=keySet.iterator();
 83         while(it.hasNext()){
 84             String key=(String)it.next();
 85             Chromosome o=SAVE.get(key);
 86             o.p=o.f/count;
 87             
 88             System.out.println(o.key+"    "+o.f+"   "+o.p);
 89         }
 90         list=new LinkedList<Chromosome>();
 91         for(int i=0;i<2;i++){
 92             String seleKey=lunpandu();
 93             list.add(new Chromosome(SAVE.get(seleKey)));
 94             System.out.println("--->"+seleKey);
 95         }
 96         return max;
 97     }
 98     
 99     public void crossover(){ //交叉
100         for(int i=0;i<list.size()/2;i++){
101             Chromosome o1=list.get(i*2); 
102             Chromosome o2=list.get(i*2+1);
103             int index=(int)Math.round(1+Math.random() * 2);
104             String o11=o1.key.substring(0, index);
105             String o12=o1.key.substring(index, o1.key.length());
106             String o21=o2.key.substring(0, index);
107             String o22=o2.key.substring(index, o1.key.length());
108             System.out.println("|||| "+o11+" | "+o12);
109             System.out.println("|||| "+o21+" | "+o22);
110             o1.key=o11+o22;
111             o2.key=o21+o12;
112             System.out.println("|||| "+o1.key);
113             System.out.println("|||| "+o2.key);
114             long bianyi=Math.round(Math.random() * 10000);
115             if(bianyi<100);
116             
117             if(hefa(o1.key) && SAVE.get(o1.key)==null) SAVE.put(o1.key, o1);
118             if(hefa(o2.key) && SAVE.get(o2.key)==null) SAVE.put(o2.key, o2);
119         }
120     }
121     public boolean hefa(String key){ //是否滿足h(x)
122         double m=0;
123         for(int i=0;i<N;i++){
124             if(key.charAt(i)=='1'){
125                 m+=B[i][0];
126             }
127         }
128         if(m<=M)return true;
129         return false;
130     }
131     public void iteration(int n){ //種群迭代
132         for(int i=0;i<n;i++){
133             System.out.println("========="+(i+1));
134             Chromosome max=selected();
135             if(max.f>=133){
136                 System.out.println("                [----"+max.key+"  "+max.f+"  "+max.p+"-----]");
137                 break;
138             }
139             crossover();
140         }
141 
142         
143     }
144     public static void main(String[] args){
145         GAtest ts=new GAtest();
146         ts.init(6);
147         ts.iteration(510);
148         
149     }
150 
151 }
View Code

 

打印結果:

  1 =========1
  2 00001    90.0   0.25069637883008355
  3 10000    92.0   0.2562674094707521
  4 01010    68.0   0.1894150417827298
  5 01100    109.0   0.30362116991643456
  6 --->01100
  7 --->01100
  8 |||| 01 | 100
  9 |||| 01 | 100
 10 |||| 01100
 11 |||| 01100
 12 =========2
 13 00001    90.0   0.25069637883008355
 14 10000    92.0   0.2562674094707521
 15 01010    68.0   0.1894150417827298
 16 01100    109.0   0.30362116991643456
 17 --->01100
 18 --->01100
 19 |||| 0 | 1100
 20 |||| 0 | 1100
 21 |||| 01100
 22 |||| 01100
 23 =========3
 24 00001    90.0   0.25069637883008355
 25 10000    92.0   0.2562674094707521
 26 01010    68.0   0.1894150417827298
 27 01100    109.0   0.30362116991643456
 28 --->10000
 29 --->00001
 30 |||| 10 | 000
 31 |||| 00 | 001
 32 |||| 10001
 33 |||| 00000
 34 =========4
 35 00000    0.0   0.0
 36 00001    90.0   0.25069637883008355
 37 10000    92.0   0.2562674094707521
 38 01010    68.0   0.1894150417827298
 39 01100    109.0   0.30362116991643456
 40 --->01100
 41 --->00001
 42 |||| 011 | 00
 43 |||| 000 | 01
 44 |||| 01101
 45 |||| 00000
 46 =========5
 47 00000    0.0   0.0
 48 00001    90.0   0.25069637883008355
 49 10000    92.0   0.2562674094707521
 50 01010    68.0   0.1894150417827298
 51 01100    109.0   0.30362116991643456
 52 --->00001
 53 --->10000
 54 |||| 00 | 001
 55 |||| 10 | 000
 56 |||| 00000
 57 |||| 10001
 58 =========6
 59 00000    0.0   0.0
 60 00001    90.0   0.25069637883008355
 61 10000    92.0   0.2562674094707521
 62 01010    68.0   0.1894150417827298
 63 01100    109.0   0.30362116991643456
 64 --->00001
 65 --->01100
 66 |||| 00 | 001
 67 |||| 01 | 100
 68 |||| 00100
 69 |||| 01001
 70 =========7
 71 00000    0.0   0.0
 72 00001    90.0   0.20179372197309417
 73 10000    92.0   0.2062780269058296
 74 01010    68.0   0.15246636771300448
 75 00100    87.0   0.19506726457399104
 76 01100    109.0   0.24439461883408073
 77 --->01100
 78 --->01010
 79 |||| 0 | 1100
 80 |||| 0 | 1010
 81 |||| 01010
 82 |||| 01100
 83 =========8
 84 00000    0.0   0.0
 85 00001    90.0   0.20179372197309417
 86 10000    92.0   0.2062780269058296
 87 01010    68.0   0.15246636771300448
 88 00100    87.0   0.19506726457399104
 89 01100    109.0   0.24439461883408073
 90 --->10000
 91 --->01100
 92 |||| 10 | 000
 93 |||| 01 | 100
 94 |||| 10100
 95 |||| 01000
 96 =========9
 97 00000    0.0   0.0
 98 00001    90.0   0.19230769230769232
 99 10000    92.0   0.19658119658119658
100 01000    22.0   0.04700854700854701
101 01010    68.0   0.1452991452991453
102 00100    87.0   0.1858974358974359
103 01100    109.0   0.2329059829059829
104 --->00100
105 --->00100
106 |||| 0 | 0100
107 |||| 0 | 0100
108 |||| 00100
109 |||| 00100
110 =========10
111 00000    0.0   0.0
112 00001    90.0   0.19230769230769232
113 10000    92.0   0.19658119658119658
114 01000    22.0   0.04700854700854701
115 01010    68.0   0.1452991452991453
116 00100    87.0   0.1858974358974359
117 01100    109.0   0.2329059829059829
118 --->10000
119 --->01010
120 |||| 10 | 000
121 |||| 01 | 010
122 |||| 10010
123 |||| 01000
124 =========11
125 00000    0.0   0.0
126 00001    90.0   0.19230769230769232
127 10000    92.0   0.19658119658119658
128 01000    22.0   0.04700854700854701
129 01010    68.0   0.1452991452991453
130 00100    87.0   0.1858974358974359
131 01100    109.0   0.2329059829059829
132 --->01100
133 --->01100
134 |||| 01 | 100
135 |||| 01 | 100
136 |||| 01100
137 |||| 01100
138 =========12
139 00000    0.0   0.0
140 00001    90.0   0.19230769230769232
141 10000    92.0   0.19658119658119658
142 01000    22.0   0.04700854700854701
143 01010    68.0   0.1452991452991453
144 00100    87.0   0.1858974358974359
145 01100    109.0   0.2329059829059829
146 --->00001
147 --->10000
148 |||| 000 | 01
149 |||| 100 | 00
150 |||| 00000
151 |||| 10001
152 =========13
153 00000    0.0   0.0
154 00001    90.0   0.19230769230769232
155 10000    92.0   0.19658119658119658
156 01000    22.0   0.04700854700854701
157 01010    68.0   0.1452991452991453
158 00100    87.0   0.1858974358974359
159 01100    109.0   0.2329059829059829
160 --->00100
161 --->00001
162 |||| 001 | 00
163 |||| 000 | 01
164 |||| 00101
165 |||| 00000
166 =========14
167 00000    0.0   0.0
168 00001    90.0   0.19230769230769232
169 10000    92.0   0.19658119658119658
170 01000    22.0   0.04700854700854701
171 01010    68.0   0.1452991452991453
172 00100    87.0   0.1858974358974359
173 01100    109.0   0.2329059829059829
174 --->00100
175 --->00100
176 |||| 00 | 100
177 |||| 00 | 100
178 |||| 00100
179 |||| 00100
180 =========15
181 00000    0.0   0.0
182 00001    90.0   0.19230769230769232
183 10000    92.0   0.19658119658119658
184 01000    22.0   0.04700854700854701
185 01010    68.0   0.1452991452991453
186 00100    87.0   0.1858974358974359
187 01100    109.0   0.2329059829059829
188 --->10000
189 --->01100
190 |||| 1 | 0000
191 |||| 0 | 1100
192 |||| 11100
193 |||| 00000
194 =========16
195 00000    0.0   0.0
196 00001    90.0   0.19230769230769232
197 10000    92.0   0.19658119658119658
198 01000    22.0   0.04700854700854701
199 01010    68.0   0.1452991452991453
200 00100    87.0   0.1858974358974359
201 01100    109.0   0.2329059829059829
202 --->00001
203 --->00100
204 |||| 00 | 001
205 |||| 00 | 100
206 |||| 00100
207 |||| 00001
208 =========17
209 00000    0.0   0.0
210 00001    90.0   0.19230769230769232
211 10000    92.0   0.19658119658119658
212 01000    22.0   0.04700854700854701
213 01010    68.0   0.1452991452991453
214 00100    87.0   0.1858974358974359
215 01100    109.0   0.2329059829059829
216 --->01010
217 --->00100
218 |||| 010 | 10
219 |||| 001 | 00
220 |||| 01000
221 |||| 00110
222 =========18
223 00000    0.0   0.0
224 00001    90.0   0.1497504159733777
225 10000    92.0   0.15307820299500832
226 01000    22.0   0.036605657237936774
227 01010    68.0   0.11314475873544093
228 00110    133.0   0.22129783693843594
229 00100    87.0   0.1447587354409318
230 01100    109.0   0.18136439267886856
231 --->00001
232 --->01100
233                 [----00110  133.0  0.22129783693843594-----]
View Code

 

最后

    正如我們看見的那樣,遺傳算法,每次迭代都會從整個集合中去計算選擇,然后通過交叉變異去產生新的種群,這樣的好處顯而易見,不會像梯度下降,貪心這類算法會陷入局部最優,至於其編碼的選擇,我想編碼的好壞決定了適應函數的簡單還是復雜的程度,適應函數設計的好壞決定了,整個算法是否能更快更好的收斂於近似最優。注意這里,遺傳算法不能保證會得到最優解,但是在整個迭代過程,它會不斷的接近於最優。

    值得一提的是,遺傳算法是基於圖式理論的,其基因型從各個特征進行描述,這樣就隱含了其搜索過程是並行處理的,對於隱含並行能力,現在已經給出了證明,每次迭代,對於n的種群,大致處理了O(n^3)個狀態,這個處理能力還是相當吃驚的。

 

注:本博文版權屬BreezeDust所有

 

歡迎轉載,轉載請注明:http://www.cnblogs.com/BreezeDust/p/3352090.html 

 本文的最新修改和意見請點擊:http://breezedust.com/2013/10/05/zi-hua-yi-chuan-suan-fa-dai-shi-li/

 

 

    

 


免責聲明!

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



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