matlab手寫遺傳演算法解決一元函式最值問題(例項)
問題:找出y=x4-4x3+3x+5 (xÎ[0,6])在[0,6]之間的最小值。
思路:用33位0,1變數來編碼x,3位編碼整數,30位編碼小數。理論上30位編碼小數可以將最小值對應的x精確到小數點後九位.
下面是我解決這個問題所有的函式,複製就可以運行了,不明白可以私下找我。微信:cy15215191378
交換值的函式:
function [x,y]=exchange(x,y)
temp=x;
x=y;
y=temp;
end
執行交叉:
%交叉操作 function [A,B]=cross(A,B) L=length(A); if L<10 W=L; elseif((L/10)-floor(L/10))>=rand&&L>10 W=ceil(L/10)+8; else W=floor(L/10)+8; end p=unidrnd(L-W+1); for i=1:W [A(1,p+i-1),B(1,p+i-1)]=exchange(A(1,p+i-1),B(1,p+i-1)); end end
變異過程,通過調節函式的第二個引數來改變每個個體的變異率,這樣從一定程度上能對不同問題達到更好的效果
function a=Mutation(A,fitness)
nnper=randperm(size(A,2));
if (A(1,nnper(1)))==1
A(1,nnper(1))=0;
elseif(A(1,nnper(1))==0)&(rand>fitness)
A(1,nnper(1))=1;
end
a=A;
end
解碼操作,就是將二進位制字串轉化成十進位制數:
function dePop=decode(pop) [lengthx,lengthy]=size(pop); dePop=zeros(lengthx,1); for i=1:lengthx for j=1:lengthy dePop(i)=dePop(i)+pop(i,j)*2^(3-j); end end end
適應度函式,就是將每個x對應的函式值計算出來,再乘以-1,這樣函式值越大,適應度反而越小,函式值越小,適應度越大
function fitness=fit(dePop)
dePop=dePop.^4-4*dePop.^3+3*dePop+5;
fitness=-dePop;
end
主函式呼叫上面函式,可以通過C修改迭代次數,pop修改種群大小和密碼子長度。我的迭代是5000次,相當於從10萬個個體中挑選出最優的一個。
clear; clc; M = 20;%種群個數 C = 5000; %迭代次數 m = 2; %適應值歸一淘汰加速指數 Pmutation = 0.2; %變異概率 Pc = 0.4;%交叉概率 pop=rand(20,33); %種群 %%%%初始化種群及其適應函式%%%% fitness=decode(pop); fitness=fit(fitness); maxfitness=max(fitness); rr=find(fitness==maxfitness); R=pop(rr(1,1),:); fprintf('當前種群最優個體:%.12f\n',-fitness(rr)); while C>=0 fprintf('迭代第%d次\n',C); %%%%選擇操作%%%% [px,py]=size(pop); ms=sort(rand(px)); fitin=1; nn=1; while nn<=px if (ms(nn))<fitness(fitin) pop_sel(nn,:)=pop(fitin,:); nn=nn+1; fitin=fitin+1; if fitin>px fitin=floor(rand*(px-1))+1; end else fitin=fitin+1; if fitin>px fitin=floor(rand*(px-1))+1; end end end %%%%保留最優個體%%%% maxfitness=max(fitness); rr=find(fitness==maxfitness); pop_sel(1,:)=pop(rr(1),:); %%%%交叉操作%%%% nnper=randperm(M); A=pop_sel(nnper(1),:); B=pop_sel(nnper(2),:); for i=1:M*Pc [A,B]=cross(A,B); pop_sel(nnper(1),:)=A; pop_sel(nnper(2),:)=B; end %%%%變異操作%%%% for i=1:M pick=rand; while pick==0 pick=rand; end if pick<=Pmutation pop_sel(i,:)=Mutation(pop_sel(i,:),0.5); end end %%%%求適應度函式%%%% pop=pop_sel; fitness=decode(pop); fitness=fit(fitness); maxfitness=max(fitness); rr=find(fitness==maxfitness); R=-fitness(rr(1)); fprintf('當前最小值=%.14f ',-fitness(rr(1))); C=C-1; end
答案如下:
當前最小值=-13.13000339865731 迭代第22次
當前最小值=-13.13000339865731 迭代第21次
當前最小值=-13.13000339865731 迭代第20次
當前最小值=-13.13000339865731 迭代第19次
當前最小值=-13.13000339865731 迭代第18次
當前最小值=-13.13000339865731 迭代第17次
當前最小值=-13.13000339865731 迭代第16次
當前最小值=-13.13000339865731 迭代第15次
當前最小值=-13.13000339865731 迭代第14次
當前最小值=-13.13000339865731 迭代第13次
當前最小值=-13.13000339865731 迭代第12次
當前最小值=-13.13000339865731 迭代第11次
當前最小值=-13.13000339865731 迭代第10次
當前最小值=-13.13000339865731 迭代第9次
當前最小值=-13.13000339865731 迭代第8次
當前最小值=-13.13000339865731 迭代第7次
當前最小值=-13.13000339865731 迭代第6次
當前最小值=-13.13000339865731 迭代第5次
當前最小值=-13.13000339865731 迭代第4次
當前最小值=-13.13000339865731 迭代第3次
當前最小值=-13.13000339865731 迭代第2次
當前最小值=-13.13000339865731 迭代第1次
當前最小值=-13.13000339865731 迭代第0次
我用其它方法驗證過,結果最後精確到了小數點的後10位。