遺傳算法_解決無約束目標函數的最大值問題


遺傳算法基本原理

借鑒物種進化的思想,將欲求解問題編碼,把可行解轉化為字符串形式。初始化隨機產生一個種群,用合理的評價函數對種群進行評估,在此基礎上進行選擇、交叉、變異的操作。選擇算子根據父代中個體適值大小進行選擇或淘汰,保證了算法的最優搜索方向。

交叉算子模擬基因重組及隨機信息交換,產生更好的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

 

 

 


免責聲明!

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



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