1. 程式人生 > >matlab手寫遺傳演算法解決一元函式最值問題(例項)

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位。