遺傳算法基本原理
借鑒物種進化的思想,將欲求解問題編碼,把可行解轉化為字符串形式。初始化隨機產生一個種群,用合理的評價函數對種群進行評估,在此基礎上進行選擇、交叉、變異的操作。選擇算子根據父代中個體適值大小進行選擇或淘汰,保證了算法的最優搜索方向。
交叉算子模擬基因重組及隨機信息交換,產生更好的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

