matlab手写遗传算法解决一元函数最值问题(实例)

问题:找出y=x4-4x3+3x+5 (xÎ[0,6])在[0,6]之间的最小值。

思路:用33位0,1变量来编码x,3位编码整数,30位编码小数。理论上30位编码小数可以将最小值对应的x精确到小数点后九位.

下面是我解决这个问题所有的函数,复制就可以运行了。

交换值的函数:

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

猜你喜欢

转载自blog.csdn.net/cysisu/article/details/82810202