日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

演化计算简单实例(附代码)

發(fā)布時(shí)間:2025/7/14 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 演化计算简单实例(附代码) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處。

本周的任務(wù)一個(gè)是搞JavaWeb的學(xué)習(xí),一個(gè)是搞演化計(jì)算的學(xué)習(xí),可惜的是JavaWeb的東西沒(méi)搞出來(lái),現(xiàn)在還是一團(tuán)亂麻,演化計(jì)算終于是寫出個(gè)小程序,但是也算是對(duì)演化計(jì)算有了初步的了解,所以這次就把演化計(jì)算的心得拿出來(lái)說(shuō)說(shuō),用以本周總結(jié)和搞日后的回顧。

一、演化計(jì)算的基本步驟

  • 根據(jù)需求制定編碼方案,我的理解中編碼其實(shí)就是確定染色體的形式,這個(gè)編碼方案是整個(gè)計(jì)算的基礎(chǔ),變異雜交都是基于編碼(染色體)之上的,所以首先就應(yīng)該制定合理的編碼方案。
  •    編碼方案有很多種,最簡(jiǎn)單的是二進(jìn)制編碼,也是目前我唯一能理解的編碼形式。所謂二進(jìn)制編碼就是用一串01的序列作為染色體,這種編碼某種意義上講和自然界真實(shí)的染色體是很想相似的,可以看做01是染色體顆粒,非常方便進(jìn)行變異和交叉。二進(jìn)制編碼是一種很自然的編碼方式。

       還有g(shù)ray編碼,實(shí)數(shù)編碼,有序位串編碼結(jié)構(gòu)式編碼等等其他形式,編碼會(huì)影響到之后的效率,其他的編碼形式日后再講。

      2.確定適應(yīng)函數(shù)。適應(yīng)函數(shù)就是描述一個(gè)個(gè)體的好壞,用以進(jìn)行選擇,適應(yīng)函數(shù)也分原始適應(yīng)函數(shù)和標(biāo)準(zhǔn)適應(yīng)函數(shù)。

      3.確定選擇策略。選擇策略是重中之重,因?yàn)檫@決定了進(jìn)化的方向,選擇函數(shù)就是自然界中的各種災(zāi)難和競(jìng)爭(zhēng),只有實(shí)力強(qiáng)大的和幸運(yùn)的(?)才能存留下來(lái),看來(lái)果然運(yùn)氣也是實(shí)力的一部分。

      選擇策略也是多種多樣的,但是關(guān)注的點(diǎn)不太一樣,包括進(jìn)化的速度,是否會(huì)陷入局部最優(yōu),群體的數(shù)目大小等等,具體的策略有繁殖池選擇,轉(zhuǎn)輪盤選擇,線性排名選擇,非線性排名選擇錦標(biāo)賽選擇等等。

      4.控制參數(shù)的選擇。就是根據(jù)具體問(wèn)題決定算法中種群的規(guī)模,最大代數(shù),一些遺傳操作的概率和輔助性的參數(shù)的設(shè)置,看起來(lái)是比較微小的東西,但是像秤砣一樣左右著整個(gè)計(jì)算的結(jié)果。

      5.遺傳算子的設(shè)計(jì)。遺傳算子主要包括繁殖,雜交,變異,是對(duì)于自然的進(jìn)一步模擬,能夠優(yōu)化算法的性能,通過(guò)引入隨機(jī)性來(lái)克服程序化的問(wèn)題。

      6.確定終止的準(zhǔn)則。

    二、一個(gè)簡(jiǎn)單的實(shí)例

        f(x1,x2)=x1^2+x2^2,x1和x2是屬于0~7的正整數(shù),求f的最大值。

    這種弱智問(wèn)題當(dāng)然一眼就可以看出答案,但是就是要用遺傳算法來(lái)實(shí)現(xiàn),用以熟悉相關(guān)的操作和步驟,下面開(kāi)始介紹我的想法。(哦,這是用C++寫的)

    1.編碼:這個(gè)0~7簡(jiǎn)直就是為了二進(jìn)制編碼設(shè)計(jì)的,對(duì)x1,x2分別用三位二進(jìn)制數(shù)來(lái)表示就可以了

    2.適應(yīng)函數(shù):由于是求f的最大值,就是說(shuō)f越大越好,所以就直接拿f來(lái)做適應(yīng)函數(shù)來(lái)評(píng)價(jià)x1,x2.

    3.選擇策略:本例中我用的是輪盤賭的策略,所謂輪盤賭就是讓每一個(gè)個(gè)體根據(jù)某種和為1的概率被挑選,挑中了就留下,否則就淘汰,這個(gè)概率就是該個(gè)體適應(yīng)值占總適應(yīng)值的比例。也就是說(shuō)適應(yīng)值越高的越有可能被選中(當(dāng)然,個(gè)體越多的也越容易被選中),但是夠幸運(yùn)的個(gè)體即使概率很低也有機(jī)會(huì)存留下來(lái)。被挑中存留的個(gè)體才有機(jī)會(huì)參加之后的繁殖雜交突變等等,其實(shí)就相當(dāng)于自然界中的種群越是厲害的越有機(jī)會(huì)留下來(lái),但是厲害的也可能陰差陽(yáng)錯(cuò)就被淘汰了(比如因?yàn)檎镜锰弑焕着赖念^狼?),比較差的也可能碰巧沒(méi)被淘汰。

    4.控制參數(shù):我設(shè)置的是最多一百代,0.6的概率會(huì)交叉,0.006的概率會(huì)突變,這個(gè)突變必須控制在較低的范圍,否則是無(wú)法完成進(jìn)化的,因?yàn)檫x擇了半天,留下了適應(yīng)度很高的染色體,但是染色體突變率很高,執(zhí)行突變時(shí)又全都給你變沒(méi)了,又恢復(fù)到隨機(jī)的一種情況之下,進(jìn)化就相當(dāng)于沒(méi)有發(fā)生。

    5.遺傳算子:我這里有突變和交叉兩個(gè)算子,突變是每一條染色體的每一個(gè)基因都有Pm的概率取反,交叉是隨機(jī)設(shè)置交叉點(diǎn),兩個(gè)染色體有一定的概率發(fā)生交叉(單點(diǎn)交叉)。

    1 #include<iostream> 2 #include<string> 3 #include<time.h> 4 #include<sstream> 5 using namespace std; 6 7 8 //種群總數(shù) 9 const int popSize=100; 10 //染色體長(zhǎng)度 11 const int chromosomeSize=6; 12 //變異概率 13 const double Pm=0.001; 14 //最多代數(shù) 15 const int MaxGen=100; 16 //變異概率 17 const double Pc=0.1; 18 19 20 21 22 23 //遺傳個(gè)體類 24 class individual 25 { 26 public: 27 //個(gè)體目標(biāo)值 28 double ObjectValue; 29 //個(gè)體適應(yīng)值 30 double FitValue; 31 //染色體編碼 32 string Chromosome; 33 //構(gòu)造函數(shù) 34 individual() 35 { 36 ObjectValue=0; 37 FitValue=0; 38 Chromosome="000000"; 39 } 40 }; 41 42 //進(jìn)化處理類 43 class Evaluation 44 { 45 private: 46 47 //種群 48 individual Population[popSize]; 49 //進(jìn)行選擇 50 void SelectPop(); 51 //進(jìn)行變異 52 void VaryPop(); 53 //進(jìn)行雜交 54 void CrossPop(); 55 //優(yōu)化 56 void OptimizePop(); 57 //初始化種群,隨機(jī)構(gòu)造一個(gè)群體 58 void Initialization(); 59 //找出最優(yōu)和最差及平均值 60 void Statistics(); 61 //評(píng)價(jià)種群 62 void EvaluatePop(); 63 //最好個(gè)體 64 individual Best; 65 //最壞個(gè)體 66 individual Worst; 67 //最壞個(gè)體下標(biāo) 68 int WorstIndex; 69 //歷史最佳 70 individual HistoryBest; 71 //平均值 72 double avg; 73 74 public: 75 //構(gòu)造函數(shù),調(diào)用初始化函數(shù) 76 Evaluation(); 77 //產(chǎn)生下一代 78 void NextPopulation(); 79 //打印 80 void output(); 81 //代數(shù) 82 int generation; 83 }; 84 85 //構(gòu)造函數(shù),調(diào)用初始化函數(shù) 86 Evaluation::Evaluation() 87 { 88 Initialization(); 89 generation=0; 90 91 } 92 93 //初始化構(gòu)造初始種群 94 void Evaluation::Initialization() 95 { 96 //對(duì)染色體進(jìn)行初始化設(shè)置,逐顆粒隨機(jī)賦值 97 char temp; 98 int Index=0,bitIndex=0; 99 for(;Index<popSize;Index++) 100 { 101 for(bitIndex=0;bitIndex<chromosomeSize;bitIndex++) 102 { 103 int r=rand()%2; 104 if (r==0) 105 temp='0'; 106 else 107 temp='1'; 108 Population[Index].Chromosome[bitIndex]=temp; 109 } 110 } 111 //初始化時(shí)設(shè)置歷史最佳為第一個(gè) 112 HistoryBest=Population[0]; 113 //調(diào)用目標(biāo)值和適應(yīng)值的初始化函數(shù),評(píng)價(jià)種群 114 EvaluatePop(); 115 Statistics(); 116 } 117 118 //評(píng)價(jià)函數(shù),就是用函數(shù)f(x1,x2)=x1^2+x2^2,因?yàn)槭菙?shù)值函數(shù),所以適應(yīng)值和目標(biāo)值是一致的 119 void Evaluation::EvaluatePop() 120 { 121 string num1,num2; 122 int value1,value2; 123 int Index=0; 124 for(;Index<popSize;Index++) 125 { 126 num1=Population[Index].Chromosome.substr(0,3); 127 num2=Population[Index].Chromosome.substr(3,3); 128 //二進(jìn)制轉(zhuǎn)化為十進(jìn)制 129 stringstream ss; 130 ss<<num1; 131 ss>>value1; 132 //清空緩沖區(qū) 133 ss.clear(); 134 ss.str(""); 135 ss<<num2; 136 ss>>value2; 137 138 int a,b,c; 139 a=value1/100; 140 b=(value1-a*100)/10; 141 c=value1-a*100-b*10; 142 value1=a*4+b*2+c; 143 a=value2/100; 144 b=(value2-a*100)/10; 145 c=value2-a*100-b*10; 146 value2=a*4+b*2+c; 147 //計(jì)算適應(yīng)值和目標(biāo)值 148 Population[Index].FitValue=value1*value1+value2*value2; 149 Population[Index].ObjectValue=value1*value1+value2*value2; 150 } 151 } 152 153 //生成下一代 154 void Evaluation::NextPopulation() 155 { 156 SelectPop(); 157 VaryPop(); 158 CrossPop(); 159 EvaluatePop(); 160 Statistics(); 161 OptimizePop(); 162 EvaluatePop(); 163 Statistics(); 164 generation++; 165 } 166 167 //選擇算子,輪盤賭 168 void Evaluation::SelectPop() 169 { 170 double FitSum=0,selection[popSize]; 171 individual newPopulation[popSize]; 172 int index=0,popindex=0; 173 //求適應(yīng)值的總和 174 for(;index<popSize;index++) 175 { 176 FitSum+=Population[index].FitValue; 177 } 178 179 //確定輪盤分布 180 for(index=0;index<popSize;index++) 181 { 182 selection[index]=Population[index].FitValue/FitSum; 183 } 184 for(index=1;index<popSize;index++) 185 { 186 selection[index]=selection[index]+selection[index-1]; 187 } 188 //用輪盤進(jìn)行隨機(jī)選取,形成新的種群 189 for(popindex=0;popindex<popSize;popindex++) 190 { 191 double p= (rand()%100); 192 p/=100; 193 index=0; 194 while(p>selection[index]) 195 index++; 196 newPopulation[popindex]=Population[index]; 197 } 198 //將剛產(chǎn)生的群體替換為系統(tǒng)的群體 199 for(index=0;index<popSize;index++) 200 { 201 Population[index]=newPopulation[index]; 202 } 203 204 } 205 206 //雜交算子,隨機(jī)選取交叉點(diǎn) 207 void Evaluation::CrossPop() 208 { 209 int Localtion; 210 int index=0; 211 string str1,str2,str3,str4; 212 //打亂順序 213 for(;index<popSize;index++) 214 { 215 individual temp; 216 int r=rand()%popSize; 217 temp=Population[index]; 218 Population[index]=Population[r]; 219 Population[r]=temp; 220 } 221 //隨機(jī)選取交叉點(diǎn),將染色體分裂,然后交叉,得到新的染色體 222 for(index=0;index<popSize;index+=2) 223 { 224 double temp=rand()%1000/1000.0; 225 if(temp<Pc) 226 { 227 Localtion=rand()%chromosomeSize; 228 str1=Population[index].Chromosome.substr(0,Localtion); 229 str2=Population[index].Chromosome.substr(Localtion); 230 str3=Population[index+1].Chromosome.substr(0,Localtion); 231 str4=Population[index+1].Chromosome.substr(Localtion); 232 Population[index].Chromosome=str1+str4; 233 Population[index+1].Chromosome=str3+str2; 234 } 235 } 236 } 237 238 //變異算子,對(duì)所有染色體每一位的隨機(jī)位置以變異概率進(jìn)行變異 239 void Evaluation::VaryPop() 240 { 241 int index=0,bitindex=0; 242 string str1="0"; 243 string str2="1"; 244 245 for(;index<popSize;index++) 246 { 247 for(bitindex=0;bitindex<chromosomeSize;bitindex++) 248 { 249 double r=rand()%1000; 250 r/=1000; 251 if(r<Pm) 252 { 253 if(Population[index].Chromosome[bitindex]==str1[0]) 254 Population[index].Chromosome[bitindex]=str2[0]; 255 else 256 Population[index].Chromosome[bitindex]=str1[0]; 257 } 258 } 259 } 260 } 261 262 //優(yōu)化 263 void Evaluation::OptimizePop() 264 { 265 Population[WorstIndex] = HistoryBest; 266 } 267 268 //統(tǒng)計(jì) 269 void Evaluation::Statistics() 270 { 271 Best=Population[0]; 272 Worst=Population[0]; 273 int index=0; 274 double sum=0; 275 for(;index<popSize;index++) 276 { 277 if(Best.FitValue<Population[index].FitValue) 278 Best=Population[index]; 279 if(Worst.FitValue>Population[index].FitValue) 280 { 281 Worst=Population[index]; 282 WorstIndex=index; 283 } 284 sum+=Population[index].FitValue; 285 } 286 if(HistoryBest.FitValue<Best.FitValue) 287 HistoryBest=Best; 288 avg=sum/popSize; 289 290 } 291 292 293 //輸出文本 294 void Evaluation::output() 295 { 296 cout<<"Generation:"<<generation<<" Average:"<<avg<<" Best:"<<Best.FitValue<<" Chromosome"<<Best.Chromosome<<endl; 297 } 298 299 300 int main() 301 { 302 Evaluation eva; 303 eva.output(); 304 while(eva.generation<MaxGen) 305 { 306 eva.NextPopulation(); 307 eva.output(); 308 } 309 310 311 }

    結(jié)果:

        寫完這個(gè)小程序之后我就在思考選擇,交叉,突變的意義是什么,目前的想法是這樣:選擇的目的是在當(dāng)前種群中尋求當(dāng)前最優(yōu)的,只考慮現(xiàn)狀,留下來(lái)的趨向于當(dāng)前群體的最優(yōu),但是是不是整體最優(yōu)是未知的,所以又引入了交叉和突變。

        交叉可以讓優(yōu)質(zhì)基因和劣質(zhì)基因在種群中變得更加均勻,方便于選擇(就是留下好的去除壞的,因?yàn)楹玫暮蛪牡亩伎赡芤虼孙@得更加突出了,而平庸的在選擇中并沒(méi)有優(yōu)勢(shì)),同時(shí)也會(huì)產(chǎn)生新的個(gè)體。

        而變異就是為了產(chǎn)生新個(gè)體才引入的,事實(shí)上我覺(jué)得他會(huì)降低選擇的速度,因?yàn)檫x擇出的好的個(gè)體經(jīng)過(guò)突變很可能就沒(méi)有之前那么好了,但是引入新的個(gè)體的意義是顯然的,這可以避免局部最優(yōu)。

    為了更好的說(shuō)明,我們走兩個(gè)極端,一是只選擇不變異不交叉,很快這個(gè)種群就會(huì)被目前最好的個(gè)體占據(jù),二是選擇交叉,百分百變異,那么得到的群體幾乎就是一個(gè)全新的群體了,選擇已經(jīng)失去了留下優(yōu)質(zhì)基因淘汰劣質(zhì)基因的能力因?yàn)楹芸煊謺?huì)到原點(diǎn),選了半天和沒(méi)選一樣。所以我目前認(rèn)為選擇是為了獲得局部最優(yōu),交叉和變異是為了一定程度上擴(kuò)充這個(gè)群體的基因庫(kù),努力向全局最優(yōu)靠近,交叉和突變都會(huì)降低選擇的速度,因?yàn)楸贿x擇留下的個(gè)體發(fā)生了變化。

    附上不同變異概率的進(jìn)化結(jié)果:

    Pm=0

    Pm=0.001

    Pm=0.01

    Pm=0.1

    Pm=0.3

    0.01以下的還算是進(jìn)化了,但是隨著Pm的增大,進(jìn)化到最優(yōu)的狀態(tài)需要的代數(shù)也越來(lái)越多(即進(jìn)化速度變慢了),0.1之后的基本上已經(jīng)陷入無(wú)序的狀態(tài),選擇已經(jīng)沒(méi)有用了。

    改變了Pc(交叉概率),沒(méi)有什么太大的影響。

    下周的話盡量了解其他的編碼方式,并嘗試不同的選擇策略,本次總結(jié)就到此為止。

    時(shí)間:2016/10/22

    轉(zhuǎn)載于:https://www.cnblogs.com/liyuwang/p/5988358.html

    總結(jié)

    以上是生活随笔為你收集整理的演化计算简单实例(附代码)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。