[原创]遗传算法matlab接口函数

这里只有作者精心编写的学习经历!
回复
头像
hellohappy
网站管理员
网站管理员
帖子: 267
注册时间: 2018年11月18日, 14:27
Been thanked: 1 time

#1 [原创]遗传算法matlab接口函数

未读文章 hellohappy » 2019年1月13日, 08:57

    比赛的时候你不太可能有时间去找某个算法,然后再去测试他的接口是否合适,或者他的程序有木有缺陷。
    下面这个遗传算法是我找了很多很多不同版本的遗传算法以后,筛选下来的。
        1.接口完整。
        2.函数功能十分齐全。
        3.程序注释清晰且有效。
        4.自带图像输出。

    可以说是接近完美的一个遗传算法基础接口。
    遗传算法matlab接口函数程序基本信息如下:

Code: 全选

function [X,MaxFval,BestPop,Trace]=fga(FUN,bounds,MaxEranum,PopSize,options,pCross,pMutation,pInversion)
% [X,MaxFval,BestPop,Trace]=fga(FUN,bounds,MaxEranum,PopSize,options,pCross,pMutation,pInversion)
% Finds a  maximum of a function of several variables.
% fga solves problems of the form:  
%      max F(X)  subject to:  LB <= X <= UB   (LB=bounds(:,1),UB=bounds(:,2))    
%  X             - 最优个体对应自变量值
%  MaxFval       - 最优个体对应函数值
%  BestPop       - 最优的群体即为最优的染色体群
%  Trace         - 每代最佳个体所对应的目标函数值
%  FUN           - 目标函数
%  bounds        - 自变量范围
%  MaxEranum     - 种群的代数,取50--500(默认200)
%  PopSize       - 每一代种群的规模;此可取50--200(默认100)
%  pCross        - 交叉概率,一般取0.5--0.85之间较好(默认0.8)
%  pMutation     - 初始变异概率,一般取0.05-0.2之间较好(默认0.1)
%  pInversion    - 倒位概率,一般取0.05-0.3之间较好(默认0.2)
%  options       - 1*2矩阵,options(1)=0二进制编码(默认0),option(1)~=0十进制编码,option(2)设定求解精度(默认1e-4)
    完整代码如下:
完整代码
Show

Code: 全选

function [X,MaxFval,BestPop,Trace]=fga(FUN,bounds,MaxEranum,PopSize,options,pCross,pMutation,pInversion)
% [X,MaxFval,BestPop,Trace]=fga(FUN,bounds,MaxEranum,PopSize,options,pCross,pMutation,pInversion)
% Finds a  maximum of a function of several variables.
% fga solves problems of the form:  
%      max F(X)  subject to:  LB <= X <= UB   (LB=bounds(:,1),UB=bounds(:,2))    
%  X             - 最优个体对应自变量值
%  MaxFval       - 最优个体对应函数值
%  BestPop       - 最优的群体即为最优的染色体群
%  Trace         - 每代最佳个体所对应的目标函数值
%  FUN           - 目标函数
%  bounds        - 自变量范围
%  MaxEranum     - 种群的代数,取50--500(默认200)
%  PopSize       - 每一代种群的规模;此可取50--200(默认100)
%  pCross        - 交叉概率,一般取0.5--0.85之间较好(默认0.8)
%  pMutation     - 初始变异概率,一般取0.05-0.2之间较好(默认0.1)
%  pInversion    - 倒位概率,一般取0.05-0.3之间较好(默认0.2)
%  options       - 1*2矩阵,options(1)=0二进制编码(默认0),option(1)~=0十进制编码,option(2)设定求解精度(默认1e-4)


T1=clock;
%检验初始参数
if nargin<2, error('FMAXGA requires at least three input arguments'); end
if nargin==2, MaxEranum=150;PopSize=100;options=[1 1e-4];pCross=0.85;pMutation=0.1;pInversion=0.25;end
if nargin==3, PopSize=100;options=[1 1e-4];pCross=0.85;pMutation=0.1;pInversion=0.25;end
if nargin==4, options=[1 1e-4];pCross=0.85;pMutation=0.1;pInversion=0.25;end
if nargin==5, pCross=0.85;pMutation=0.1;pInversion=0.25;end
if nargin==6, pMutation=0.1;pInversion=0.25;end
if nargin==7, pInversion=0.25;end

if (options(1)==0|options(1)==1)&find((bounds(:,1)-bounds(:,2))>0)
   error('数据输入错误,请重新输入:');
end

% 定义全局变量
global m n NewPop children1 children2 VarNum

% 初始化种群和变量
precision     = options(2);
bits          = ceil(log2((bounds(:,2)-bounds(:,1))' ./ precision));%由设定精度划分区间
VarNum        = size(bounds,1);
[Pop]         = InitPop(PopSize,bounds,bits,options);%初始化种群
[m,n]         = size(Pop);
fit           = zeros(1,m);
NewPop        = zeros(m,n);
children1     = zeros(1,n);
children2     = zeros(1,n);
pm0           = pMutation;
BestPop       = zeros(MaxEranum,n);%分配初始解空间BestPop,Trace
Trace         = zeros(1,MaxEranum);
Lb            = ones(PopSize,1)*bounds(:,1)';
Ub            = ones(PopSize,1)*bounds(:,2)';

%二进制编码采用多点交叉和均匀交叉,并逐步增大均匀交叉概率
%浮点编码采用离散交叉(前期)、算术交叉(中期)、AEA重组(后期)
OptsCrossOver = [ones(1,MaxEranum)*options(1);...
                 round(unidrnd(2*(MaxEranum-[1:MaxEranum]))/MaxEranum)]';

%浮点编码时采用两种自适应变异和一种随机变异(自适应变异发生概率为随机变异发生的2倍)
OptsMutation  = [ones(1,MaxEranum)*options(1);unidrnd(5,1,MaxEranum)]';

if options(1)==3
    D=zeros(n);
    CityPosition=bounds;
    D = sqrt((CityPosition(:,  ones(1,n)) - CityPosition(:,  ones(1,n))').^2 +...
             (CityPosition(:,2*ones(1,n)) - CityPosition(:,2*ones(1,n))').^2 );
end

%==========================================================================
%                              进化主程序                                 %
%==========================================================================
eranum = 1;
H=waitbar(0,'Please wait...');
while(eranum<=MaxEranum)
    for j=1:m
       if options(1)==1
           %eval(['[fit(j)]=' FUN '(Pop(j,:));']);%但执行字符串速度比直接计算函数值慢
           fit(j)=feval(FUN,Pop(j,:));%计算适应度
       elseif options(1)==0
           %eval(['[fit(j)]=' FUN '(b2f(Pop(j,:),bounds,bits));']);
           fit(j)=feval(FUN,(b2f(Pop(j,:),bounds,bits)));
       else
           fit(j)=-feval(FUN,Pop(j,:),D);
       end
    end
    [Maxfit,fitIn]=max(fit);%得到每一代最大适应值
    Meanfit(eranum)=mean(fit);
    BestPop(eranum,:)=Pop(fitIn,:);
    Trace(eranum)=Maxfit;
    if options(1)==1
       Pop=(Pop-Lb)./(Ub-Lb);%将定义域映射到[0,1]:[Lb,Ub]-->[0,1] ,Pop-->(Pop-Lb)./(Ub-Lb)
    end
    
    switch round(unifrnd(0,eranum/MaxEranum))%进化前期尽量使用实行锦标赛选择,后期逐步增大非线性排名选择
        case {0}
             [selectpop]=TournamentSelect(Pop,fit,bits);%锦标赛选择
        case {1}
             [selectpop]=NonlinearRankSelect(Pop,fit,bits);%非线性排名选择
     end 
     
    [CrossOverPop]=CrossOver(selectpop,pCross,OptsCrossOver(eranum,:));%交叉
    
    [MutationPop]=Mutation(CrossOverPop,fit,pMutation,VarNum,OptsMutation(eranum,:)); %变异
    
    [InversionPop]=Inversion(MutationPop,pInversion);%倒位
    
    %更新种群
    if options(1)==1
       Pop=Lb+InversionPop.*(Ub-Lb);%还原Pop
    else
       Pop=InversionPop;
    end
    pMutation=pm0+(eranum^3)*(pCross/2-pm0)/(eranum^4); %逐步增大变异率至1/2交叉率
    percent=num2str(round(100*eranum/MaxEranum));
    waitbar(eranum/MaxEranum,H,['Evolution complete  ',percent,'%']);
    eranum=eranum+1;
end
close(H);

% 格式化输出进化结果和解的变化情况
t=1:MaxEranum;
plot(t,Trace,t,Meanfit);
legend('解的变化','种群的变化');
title('函数优化的遗传算法');
xlabel('进化世代数');
ylabel('每一代最优适应度');
[MaxFval,MaxFvalIn]=max(Trace);
if options(1)==1|options(1)==3
   X=BestPop(MaxFvalIn,:);
elseif options(1)==0
   X=b2f(BestPop(MaxFvalIn,:),bounds,bits);
end
hold on;  
plot(MaxFvalIn,MaxFval,'*');
text(MaxFvalIn+5,MaxFval,['FMAX=' num2str(MaxFval)]);
str1=sprintf(' Best generation:\n  %d\n\n Best X:\n  %s\n\n MaxFval\n  %f\n',...
             MaxFvalIn,num2str(X),MaxFval);
disp(str1);

% -计时
T2=clock;
elapsed_time=T2-T1;
if elapsed_time(6)<0
    elapsed_time(6)=elapsed_time(6)+60; elapsed_time(5)=elapsed_time(5)-1;
end
if elapsed_time(5)<0
    elapsed_time(5)=elapsed_time(5)+60;elapsed_time(4)=elapsed_time(4)-1;
end  
str2=sprintf('elapsed_time\n %d (h) %d (m) %.4f (s)',elapsed_time(4),elapsed_time(5),elapsed_time(6));
disp(str2);

%==========================================================================
%                               遗传操作子程序                            %
%==========================================================================

% -- 初始化种群 --
% 采用浮点编码和二进制Gray编码(为了克服二进制编码的Hamming悬崖缺点)
function [initpop]=InitPop(popsize,bounds,bits,options)
numVars=size(bounds,1);%变量数目
rang=(bounds(:,2)-bounds(:,1))';%变量范围
if options(1)==1
    initpop=zeros(popsize,numVars);
    initpop=(ones(popsize,1)*rang).*(rand(popsize,numVars))+(ones(popsize,1)*bounds(:,1)');
elseif options(1)==0    
    precision=options(2);%由求解精度确定二进制编码长度
    len=sum(bits);
    initpop=zeros(popsize,len);%The whole zero encoding individual
    for i=2:popsize-1
        pop=round(rand(1,len));
        pop=mod(([0 pop]+[pop 0]),2);
        %i=1时,b(1)=a(1);i>1时,b(i)=mod(a(i-1)+a(i),2)
        %其中原二进制串:a(1)a(2)...a(n),Gray串:b(1)b(2)...b(n)
        initpop(i,:)=pop(1:end-1);
    end
    initpop(popsize,:)=ones(1,len);%The whole one encoding individual
else
    for i=1:popsize
        initpop(i,:)=randperm(numVars);%为Tsp问题初始化种群
    end
end

% -- 二进制串解码 --
function [fval] = b2f(bval,bounds,bits)
% fval   - 表征各变量的十进制数
% bval   - 表征各变量的二进制编码串
% bounds - 各变量的取值范围
% bits   - 各变量的二进制编码长度
scale=(bounds(:,2)-bounds(:,1))'./(2.^bits-1); %The range of the variables
numV=size(bounds,1);
cs=[0 cumsum(bits)]; 
for i=1:numV
  a=bval((cs(i)+1):cs(i+1));
  fval(i)=sum(2.^(size(a,2)-1:-1:0).*a)*scale(i)+bounds(i,1);
end


% -- 选择操作 --
% 采用基于轮盘赌法的非线性排名选择
% 各个体成员按适应值从大到小分配选择概率:
% P(i)=(q/1-(1-q)^n)*(1-q)^i,  其中 P(0)>P(1)>...>P(n), sum(P(i))=1
function [NewPop]=NonlinearRankSelect(OldPop,fit,bits)
global m n NewPop
fit=fit';
selectprob=fit/sum(fit);%计算各个体相对适应度(0,1)
q=max(selectprob);%选择最优的概率
x=zeros(m,2);
x(:,1)=[m:-1:1]';
[y x(:,2)]=sort(selectprob);
r=q/(1-(1-q)^m);%标准分布基值
newfit(x(:,2))=r*(1-q).^(x(:,1)-1);%生成选择概率
newfit=[0 cumsum(newfit)];%计算各选择概率之和
rNums=rand(m,1);
newIn=1;
while(newIn<=m)
      NewPop(newIn,:)=OldPop(length(find(rNums(newIn)>newfit)),:);
      newIn=newIn+1;
end

% -- 锦标赛选择(含精英选择) --
function [NewPop]=TournamentSelect(OldPop,fit,bits)
global m n NewPop
num=floor(m./2.^(1:10));
num(find(num==0))=[];
L=length(num);
a=sum(num);
b=m-a;
PopIn=1;
while(PopIn<=L)
      r=unidrnd(m,num(PopIn),2^PopIn);
      [LocalMaxfit,In]=max(fit(r),[],2);
      SelectIn=r((In-1)*num(PopIn)+[1:num(PopIn)]');
      NewPop(sum(num(1:PopIn))-num(PopIn)+1:sum(num(1:PopIn)),:)=OldPop(SelectIn,:);
      PopIn=PopIn+1;
      r=[];In=[];LocalMaxfit=[];
  end
  if b>1
     NewPop((sum(num)+1):(sum(num)+b-1),:)=OldPop(unidrnd(m,1,b-1),:);
  end
  [GlobalMaxfit,I]=max(fit);%保留每一代中最佳个体
  NewPop(end,:)=OldPop(I,:);

 
% -- 交叉操作 --
function [NewPop]=CrossOver(OldPop,pCross,opts)
global m n NewPop 
r=rand(1,m);
y1=find(r<pCross);
y2=find(r>=pCross);
len=length(y1);
if len==1|(len>2&mod(len,2)==1)%如果用来进行交叉的染色体的条数为奇数,将其调整为偶数
    y2(length(y2)+1)=y1(len);
    y1(len)=[];
end
i=0;
if length(y1)>=2
    if opts(1)==1%浮点编码交叉
       while(i<=length(y1)-2)
           NewPop(y1(i+1),:)=OldPop(y1(i+1),:);
           NewPop(y1(i+2),:)=OldPop(y1(i+2),:);
           if opts(2)==0&n>1%discret crossover
              Points=sort(unidrnd(n,1,2));
              NewPop(y1(i+1),Points(1):Points(2))=OldPop(y1(i+2),Points(1):Points(2));
              NewPop(y1(i+2),Points(1):Points(2))=OldPop(y1(i+1),Points(1):Points(2));
           elseif opts(2)==1%arithmetical crossover
              Points=round(unifrnd(0,pCross,1,n));
              CrossPoints=find(Points==1);
              r=rand(1,length(CrossPoints));
              NewPop(y1(i+1),CrossPoints)=r.*OldPop(y1(i+1),CrossPoints)+(1-r).*OldPop(y1(i+2),CrossPoints);
              NewPop(y1(i+2),CrossPoints)=r.*OldPop(y1(i+2),CrossPoints)+(1-r).*OldPop(y1(i+1),CrossPoints);
          else %AEA recombination
              Points=round(unifrnd(0,pCross,1,n));
              CrossPoints=find(Points==1);
              v=unidrnd(4,1,2);
              NewPop(y1(i+1),CrossPoints)=(floor(10^v(1)*OldPop(y1(i+1),CrossPoints))+...
                                       10^v(1)*OldPop(y1(i+2),CrossPoints)-floor(10^v(1)*OldPop(y1(i+2),CrossPoints)))/10^v(1);
              NewPop(y1(i+2),CrossPoints)=(floor(10^v(2)*OldPop(y1(i+2),CrossPoints))+...
                                       10^v(2)*OldPop(y1(i+1),CrossPoints)-floor(10^v(2)*OldPop(y1(i+1),CrossPoints)))/10^v(2);  
           end
           i=i+2;
       end       
   elseif opts(1)==0%二进制编码交叉
       while(i<=length(y1)-2)
           if opts(2)==0
              [NewPop(y1(i+1),:),NewPop(y1(i+2),:)]=EqualCrossOver(OldPop(y1(i+1),:),OldPop(y1(i+2),:));
           else
              [NewPop(y1(i+1),:),NewPop(y1(i+2),:)]=MultiPointCross(OldPop(y1(i+1),:),OldPop(y1(i+2),:));
           end
           i=i+2;
      end 
  else %Tsp问题次序杂交
      for i=0:2:length(y1)-2    
          xPoints=sort(unidrnd(n,1,2));
          NewPop([y1(i+1) y1(i+2)],xPoints(1):xPoints(2))=OldPop([y1(i+2) y1(i+1)],xPoints(1):xPoints(2));
          %NewPop(y1(i+2),xPoints(1):xPoints(2))=OldPop(y1(i+1),xPoints(1):xPoints(2));
          temp=[OldPop(y1(i+1),xPoints(2)+1:n) OldPop(y1(i+1),1:xPoints(2))];
          for del1i=xPoints(1):xPoints(2)
              temp(find(temp==OldPop(y1(i+2),del1i)))=[];
          end
          NewPop(y1(i+1),(xPoints(2)+1):n)=temp(1:(n-xPoints(2)));
          NewPop(y1(i+1),1:(xPoints(1)-1))=temp((n-xPoints(2)+1):end);
          
          temp=[OldPop(y1(i+2),xPoints(2)+1:n) OldPop(y1(i+2),1:xPoints(2))];
          for del2i=xPoints(1):xPoints(2)
              temp(find(temp==OldPop(y1(i+1),del2i)))=[];
          end
          NewPop(y1(i+2),(xPoints(2)+1):n)=temp(1:(n-xPoints(2)));
          NewPop(y1(i+2),1:(xPoints(1)-1))=temp((n-xPoints(2)+1):end);
      end
   end
end
NewPop(y2,:)=OldPop(y2,:);

% -二进制串均匀交叉算子
function [children1,children2]=EqualCrossOver(parent1,parent2)
global n children1 children2 
hidecode=round(rand(1,n));%随机生成掩码
crossposition=find(hidecode==1);
holdposition=find(hidecode==0);
children1(crossposition)=parent1(crossposition);%掩码为1,父1为子1提供基因
children1(holdposition)=parent2(holdposition);%掩码为0,父2为子1提供基因
children2(crossposition)=parent2(crossposition);%掩码为1,父2为子2提供基因
children2(holdposition)=parent1(holdposition);%掩码为0,父1为子2提供基因

% -二进制串多点交叉算子
function [Children1,Children2]=MultiPointCross(Parent1,Parent2)%交叉点数由变量数决定
global n Children1 Children2 VarNum
Children1=Parent1;
Children2=Parent2;
Points=sort(unidrnd(n,1,2*VarNum));
for i=1:VarNum
    Children1(Points(2*i-1):Points(2*i))=Parent2(Points(2*i-1):Points(2*i));
    Children2(Points(2*i-1):Points(2*i))=Parent1(Points(2*i-1):Points(2*i));
end 


% -- 变异操作 --
function [NewPop]=Mutation(OldPop,fit,pMutation,VarNum,opts)
global m n NewPop
NewPop=OldPop;
r=rand(1,m);
MutIn=find(r<=pMutation);
L=length(MutIn);
i=1;
if opts(1)==1%浮点变异
   maxfit=max(fit);
   upfit=maxfit+0.05*abs(maxfit);
   if opts(2)==1|opts(2)==3
      while(i<=L)%自适应变异(自增或自减)
            Point=unidrnd(n);
            T=(1-fit(MutIn(i))/upfit)^2;
            q=abs(1-rand^T);
            %if q>1%按严格数学推理来说,这段程序是不能缺少的
            %   q=1
            %end
            p=OldPop(MutIn(i),Point)*(1-q);
            if unidrnd(2)==1
               NewPop(MutIn(i),Point)=p+q;
            else
               NewPop(MutIn(i),Point)=p;
            end
            i=i+1;
       end
   elseif opts(2)==2|opts(2)==4%AEA变异(任意变量的某一位变异)
       while(i<=L)
             Point=unidrnd(n);
             T=(1-abs(upfit-fit(MutIn(i)))/upfit)^2;
             v=1+unidrnd(1+ceil(10*T));
             %v=1+unidrnd(5+ceil(10*eranum/MaxEranum));
             q=mod(floor(OldPop(MutIn(i),Point)*10^v),10);
             NewPop(MutIn(i),Point)=OldPop(MutIn(i),Point)-(q-unidrnd(9))/10^v;
             i=i+1;
       end
   else
       while(i<=L)
           Point=unidrnd(n);
           if round(rand)
              NewPop(MutIn(i),Point)=OldPop(MutIn(i),Point)*(1-rand);
          else
              NewPop(MutIn(i),Point)=OldPop(MutIn(i),Point)+(1-OldPop(MutIn(i),Point))*rand;
          end
          i=i+1;
      end
   end   
elseif opts(1)==0%二进制串变异
   if L>=1
      while i<=L
          k=unidrnd(n,1,VarNum); %设置变异点数(=变量数)
          for j=1:length(k)
              if NewPop(MutIn(i),k(j))==1
                 NewPop(MutIn(i),k(j))=0;
              else
                 NewPop(MutIn(i),k(j))=1;
              end
          end
          i=i+1;
      end
   end
else%Tsp变异
   if opts(2)==1|opts(2)==2|opts(2)==3|opts(2)==4
      numMut=ceil(pMutation*m);
      r=unidrnd(m,numMut,2);
      [LocalMinfit,In]=min(fit(r),[],2);
      SelectIn=r((In-1)*numMut+[1:numMut]');
      while(i<=numMut)
           mPoints=sort(unidrnd(n,1,2));
           if mPoints(1)~=mPoints(2)
              NewPop(SelectIn(i),1:mPoints(1)-1)=OldPop(SelectIn(i),1:mPoints(1)-1);
              NewPop(SelectIn(i),mPoints(1):mPoints(2)-1)=OldPop(SelectIn(i),mPoints(1)+1:mPoints(2));
              NewPop(SelectIn(i),mPoints(2))=OldPop(SelectIn(i),mPoints(1));
              NewPop(SelectIn(i),mPoints(2)+1:n)=OldPop(SelectIn(i),mPoints(2)+1:n);
           else
              NewPop(SelectIn(i),:)=OldPop(SelectIn(i),:);
           end
           i=i+1;
      end
   else     
      r=rand(1,m);
      MutIn=find(r<=pMutation);
      L=length(MutIn);
      while i<=L
            mPoints=sort(unidrnd(n,1,2));
            rIn=randperm(mPoints(2)-mPoints(1)+1);
            NewPop(MutIn(i),mPoints(1):mPoints(2))=OldPop(MutIn(i),mPoints(1)+rIn-1);
            i=i+1;
      end
    end
end


% -- 倒位操作 --
function [NewPop]=Inversion(OldPop,pInversion)
global m n NewPop
NewPop=OldPop;
r=rand(1,m);
PopIn=find(r<=pInversion);
len=length(PopIn);
i=1;
if len>=1
    while(i<=len)
        d=sort(unidrnd(n,1,2));
        NewPop(PopIn(i),d(1):d(2))=OldPop(PopIn(i),d(2):-1:d(1));
        i=i+1;    
    end
end
 

Link:
Hide post links
Show post links


回复