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

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-----]
最后
正如我們看見的那樣,遺傳算法,每次迭代都會從整個集合中去計算選擇,然后通過交叉變異去產生新的種群,這樣的好處顯而易見,不會像梯度下降,貪心這類算法會陷入局部最優,至於其編碼的選擇,我想編碼的好壞決定了適應函數的簡單還是復雜的程度,適應函數設計的好壞決定了,整個算法是否能更快更好的收斂於近似最優。注意這里,遺傳算法不能保證會得到最優解,但是在整個迭代過程,它會不斷的接近於最優。
值得一提的是,遺傳算法是基於圖式理論的,其基因型從各個特征進行描述,這樣就隱含了其搜索過程是並行處理的,對於隱含並行能力,現在已經給出了證明,每次迭代,對於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/