遺傳算法基本原理
借鑒物種進化的思想,將欲求解問題編碼,把可行解轉化為字符串形式。初始化隨機產生一個種群,用合理的評價函數對種群進行評估,在此基礎上進行選擇、交叉、變異的操作。選擇算子根據父代中個體適值大小進行選擇或淘汰,保證了算法的最優搜索方向。
交叉算子模擬基因重組及隨機信息交換,產生更好的1個體,使其在可行域中有效搜索。
變異算子模擬基因突變,保證了算法的全局搜索能力,避免陷入局部最優。
遺傳算法基本過程
1.編碼
有多種編碼方式,一般采用二進制編碼
2.解碼
目的是為了將不直觀的二進制數據串還原成十進制
3.初始種群
利用隨機函數產生k位(假設二進制數的最大長度為k)的0、1排列,將該排列數表示一個染色體,每個染色體代表一個初始值
4.選擇
根據個體適應值的比例來確定個體的選擇概率,是一個隨機采用的過程,一般再用輪盤賭算法來進行選擇。
這里來舉個🌰栗子來解釋輪盤賭算法
個體序號 1 2 3 4 5 6 7 8 9 10
適應度 8 2 17 2 12 11 7 3 7
適應度累計值 8 10 27 34 36 48 59 66
隨機數 23 49 76 13 1 27 57
被選中的個體號 3 7 10 3 1 3 7
設個體序號為i ,適應度累計值 為 個體序號1~i的適應度的累加和;
被選中的個體號為 比隨機數大的最小的適應度累計值的索引
5.交叉
隨機產生一個1到k-1的數(假設二進制數的最大長度為k),個體A、B在該位后的染色體進行交換
6.變異
為了避免在算法迭代后期出現種群過早收斂,隨機選取1~k中的某位若其為0將其變為1,若其為1將其變為0
7.個體適應度評估
在設計適應度函數時要考慮:
1.適應度函數能否反映解的優劣
2.該函數是否時單值的和非負的
對於函數優化問題,適應度可取為函數值
8.復制
將子代復制為父代
無約束目標函數的最大值的求解
%target.m % 案例一:無約束目標函數的最大值 % 求解maxf(x)=200*e(−0.05x)*sinx; x∈[−2,2] %主程序:用遺傳算法求解y=200*exp(-0.05*x).*sin(x)在[-2 2]區間上的最大值 clc; global BitLength %全局變量,計算如果滿足求解精度至少需要編碼的長度 global boundsbegin %全局變量,自變量的起始點 global boundsend %全局變量,自變量的終止點 bounds=[-2 2];%一維自變量的取值范圍 precision=0.0001;%運算精度 boundsbegin=bounds(:,1); boundsend=bounds(:,2); %計算滿足求解精度至少需要多長的染色體 BitLength=ceil(log2((boundsend-boundsbegin)'./precision)); popsize=50;%初始種群大小 Generationnmax=20;%最大代數 pcrossover=0.9;%交配概率 pmutation=0.09;%變異概率 %產生初始種群 %Round函數返回一個數值,該數值是按照指定的小數位數進行四舍五入運算的結果。可是當保留位跟着的即使是5,有可能進位,也有可能舍去,機會各50%。 population=round(rand(popsize,BitLength));%隨機產生初始種群,行為種群大小,列為二進制長度 %計算適應度,返回適應度Fitvalue和累計概率cumsump [Fitvalue,cumsump]=fitnessfun(population);%輸入population返回適應度和累計概率 Generation=1; while Generation<Generationnmax+1 for j=1:2:popsize %1對1對的群體進行交叉、變異 %選擇操作 seln=selection(population,cumsump);%選擇兩個個體,返回個體的序號 %交叉操作 scro=crossover(population,seln,pcrossover); scnew(j,:)=scro(1,:);%先兩個個體交叉,再分別對兩個個體進行變異 scnew(j+1,:)=scro(2,:); %變異操作 在交叉基礎上變異 smnew(j,:)=mutation(scnew(j,:),pmutation); smnew(j+1,:)=mutation(scnew(j+1,:),pmutation); end population=smnew;%產生了新的種群 %計算新種群的適應度 [Fitvalue,cumsump]=fitnessfun(population); %記錄當前代最好的適應度和平均適應度 [fmax,nmax]=max(Fitvalue);%最好的適應度為fmax(函數值最大),其對應個體為nmax fmean=mean(Fitvalue);%平均適應度 ymax(Generation)=fmax;%每代中最好的適應度 ymean(Generation)=fmean;%每代中的平均適應度 %記錄當前代的最佳染色體個體 x=transform2to10(population(nmax,:));%population(nmax,:)為最佳染色體個體,x返回的時其對應的十進制數 %自變量取值范圍[-2,2],需要把經過遺傳運算的最佳染色體整合到[-2,2]區間 xx=boundsbegin+x*(boundsend-boundsbegin)/(power(2,BitLength)-1); xmax(Generation)=xx; Generation=Generation+1; end Generation=Generation-1; targetfunvalue=targetfun(xmax); [Besttargetfunvalue,nmax]=max(targetfunvalue); Bestpopulation=xmax(nmax); figure(1); hand1=plot(1:Generation,ymax); set(hand1,'linestyle','-','linewidth',1.8,'marker','*','markersize',6); hold on; hand2=plot(1:Generation,ymean); set(hand2,'color','r','linestyle','-','linewidth',1.8,'marker','h','markersize',6); xlabel('進化代數');ylabel('最大/平均適應度'); xlim([1 Generationnmax]); legend('最大適應度','平均適應度'); hold off;
%fitnessfun.m %計算適應度函數 返回適應度 累計概率 function [Fitvalue,cumsump]=fitnessfun(population) global BitLength; global boundsbegin; global boundsend; popsize=size(population,1);%計算個體個數,有popsize個個體 for i=1:popsize x=transform2to10(population(i,:));%將二進制轉換為十進制 %譯碼過程 轉化為[-2,2]區間的實數 xx=boundsbegin+x*(boundsend-boundsbegin)/(power(boundsend,BitLength)-1); Fitvalue(i)=targetfun(xx);%計算函數值即適應度,保存在行向量中 end %給適應度函數加上一個大小合理的數以便保證種群適應值為正數 Fitvalue=Fitvalue'+230;%轉化為列向量 %計算選擇概率 fsum=sum(Fitvalue); Pperpopulation=Fitvalue/fsum;%適應度歸一化,及被復制的概率 %計算累計概率 cumsump(1)=Pperpopulation(1); for i=2:popsize cumsump(i)=cumsump(i-1)+Pperpopulation(i);%求累計概率 end cumsump=cumsump';%累計概率 轉化為行向量 end
%selection.m %新種群選擇操作 選擇兩個個體,返回個體序號,可能兩個序號相同 function seln=selection(population,cumsump)%參數 種群 個體累積概率 %從種群中選擇兩個個體 所以下面的過程循環兩次 for i=1:2 r=rand;%產生一個隨機數 %模擬輪盤賭算法 prand=cumsump-r; j=1; while prand(j)<0 j=j+1; end seln(i)=j;%選中個體的序號 end end
%IfCroIfMut.m %判斷遺傳運算是否需要進行交叉或變異 %mutORcro為動作(交叉、變異)發生的概率 %根據概率mutORcro決定是否進行操作,產生1的概率是mutORcro,產生0的概率為1-mutORcro function pcc=IfCroIfMut(mutORCro) test(1:100)=0;%1*100的行向量 l=round(100*mutORCro); test(1:l)=1; n=round(rand*99)+1; pcc=test(n); end
%crossover.m %新種群交叉操作 function scro=crossover(population,seln,pc)%參數 種群 選擇的兩個個體 交配的概率 BitLength=size(population,2);%二進制的個數 pcc=IfCroIfMut(pc);%根據交叉概率決定是否進行交叉操作,1則是,0則否 if pcc==1 %進行交叉操作 %獲取交換位前面一位的index chb=round(rand*(BitLength-2))+1;%在[1,BitLength-1]范圍內隨機產生一個交叉位 scro(1,:)=[population(seln(1),1:chb) population(seln(2),chb+1:BitLength)]; scro(2,:)=[population(seln(2),1:chb) population(seln(1),chb+1:BitLength)]; else scro(1,:)=population(seln(1),:); scro(2,:)=population(seln(2),:); end end
%mutation.m %新種群變異操作 %snew為一個個體 function snnew=mutation(snew,pmutation) BitLength=size(snew,2);%獲取個體的二進制長度 snnew=snew; pmm=IfCroIfMut(pmutation);%根據變異概率決定是否進行變異操作,1則是,0則否 if pmm==1 chb=round(rand*(BitLength-1))+1;%在[1,BitLength]范圍內隨機產生一個變異位 snnew(chb)=abs(snew(chb)-1);%0變成1,1變成0 end end
%transform2to10.m將二進制轉換為十進制 function x=transform2to10(population) BitLength=size(population,2);%Population的列,即二進制的長度 x=population(BitLength);%x=末位 for i=1:BitLength-1 x=x+population(BitLength-i)*power(2,i); end end
%targetfun.m %對於優化最大值或極大值函數問題,目標函數可以作為適應度函數 function y=targetfun(x) y=200*exp(-0.05*x).*sin(x); end