遺傳演算法與非線性規劃結合求解函式極值
阿新 • • 發佈:2019-02-02
動機
MATLAB經典非線性規劃演算法大多采用梯度下降的方法進行求解,區域性搜尋能力較強,但容易掉入區域性極值,而遺傳演算法採用選擇、交叉和變異運算元進行搜尋,全域性搜尋能力較強,區域性搜尋能力較弱
打個比方的話,大概就是遺傳演算法可以看到各個山丘,但它不會去分辨哪個才是最高的,很容易隨便選一個就爬上去了。而梯度下降演算法視野比較窄,但它會在看到的那些裡爬到最高的山上去
如果將二者結合,就很有可能能夠得到問題的全域性最優解
流程
N是個固定的數,先用遺傳演算法進行N次迭代(即先找出那些山丘),等到了N次,再用梯度下降演算法來在這些山丘裡尋求最高的那個
MATLAB程式碼
clc
clear all
close all
%定義自變數的範圍
lbx1=0;ubx1=2.8274;
lbx2=0;ubx2=2.8274;
lbx3=0;ubx3=2.8274;
lbx4=0;ubx4=2.8274;
lbx5=0;ubx5=2.8274;
%% 定義遺傳演算法引數
NIND=100; %個體數目
MAXGEN=30; %最大遺傳代數
PRECI=20; %變數的二進位制位數
GGAP=0.95; %代溝
px=0.6; %交叉概率
pm=0.1; %變異概率
trace=zeros(MAXGEN,6); %尋優結果的初始值
FieldD=[PRECI PRECI PRECI PRECI PRECI;lbx1 lbx2 lbx3 lbx4 lbx5;ubx1 ubx2 ubx3 ubx4 ubx5;1 1 1 1 1;0 0 0 0 0;1 1 1 1 1;1 1 1 1 1]; %區域描述器
Chrom=crtbp(NIND,PRECI*5); %初始種群
%% 優化
gen=0; %代計數器
X=bs2rv(Chrom,FieldD); %計算初始種群的十進位制轉換
X1=X(:,1);X2=X(:,2);X3=X(:,3);X4=X(:,4);X5=X(:,5);
ObjV=-5*sin(X1).*sin(X2).*sin(X3).*sin(X4).*sin(X5)-sin(5*X1).*sin(5*X2).*sin(5*X3).*sin(5*X4).*sin(5*X5)+8; %計算目標函式值
while gen<MAXGEN
FitnV=ranking(ObjV); %分配適應度值
SelCh=select('sus',Chrom,FitnV,GGAP); %選擇
SelCh=recombin('xovsp',SelCh,px); %重組
SelCh=mut(SelCh,pm); %變異
X=bs2rv(SelCh,FieldD); %子代個體的十進位制轉換
X1=X(:,1);X2=X(:,2);X3=X(:,3);X4=X(:,4);X5=X(:,5);
ObjVSel= -5*sin(X1).*sin(X2).*sin(X3).*sin(X4).*sin(X5)-sin(5*X1).*sin(5*X2).*sin(5*X3).*sin(5*X4).*sin(5*X5)+8; %計運算元代的目標函式值
[Chrom,ObjV]=reins(Chrom,SelCh,1,1,ObjV,ObjVSel); %重插入子代到父代,得到新種群
X=bs2rv(Chrom,FieldD);
X1=X(:,1);X2=X(:,2);X3=X(:,3);X4=X(:,4);X5=X(:,5);
gen=gen+1; %代計數器增
if mod(gen,10)==0
for i=1:NIND
x=X(i,:); %X_init拿來裝每次起始的自變數值,是個行向量
%X_min=zeros(5,NIND); %X_min拿來記錄每次求出最小值對應的自變數。每列代表一次求出的自變數值們
%Z_min=zeros(NIND,1); %Z_min拿來記錄每次求出的最小值
[X_min(:,i),Z_min(i)]=fmincon(inline('8-5*sin(x(1))*sin(x(2))*sin(x(3))*sin(x(4))*sin(x(5))-sin(5*x(1))*sin(5*x(2))*sin(5*x(3))*sin(5*x(4))*sin(5*x(5))'),x,[],[],[],[],[0 0 0 0 0],[2.8274 2.8274 2.8274 2.8274 2.8274]);
end
[A,I]=min(Z_min);trace(gen,1)=A;trace(gen,2)=X_min(1,I);trace(gen,3)=X_min(2,I);trace(gen,4)=X_min(3,I);trace(gen,5)=X_min(4,I);trace(gen,6)=X_min(5,I);
else
[A,I]=min(ObjV);trace(gen,1)=A;trace(gen,2)=X1(I);trace(gen,3)=X2(I);trace(gen,4)=X3(I);trace(gen,5)=X4(I);trace(gen,6)=X5(I);
end
end
%% 畫進化圖
figure(1);
plot(1:MAXGEN,trace(:,1));
grid on
xlabel('遺傳代數')
ylabel('解的變化')
title('進化過程')
bestZ=trace(1,end);
bestX1=trace(2,end);
bestX2=trace(3,end);
bestX3=trace(4,end);
bestX4=trace(5,end);
bestX5=trace(6,end);
fprintf(['最優解:\nX1=',num2str(bestX1),'\nX2=',num2str(bestX2),'\nX3=',num2str(bestX3),'\nX4=',num2str(bestX4),'\nX5=',num2str(bestX5),'\nZ=',num2str(bestZ),'\n'])
最後執行出來結果是
發現每次到呼叫非線性規劃來求最優解時就能找到最優值…估計是這個函式比較簡單,可以直接用遺傳演算法來搞的緣故?