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);%生成选择概率
评论0