赞
踩
写在前边:本文在原作者基础上补充了自己的理解,并将代码改成了更适宜本人理解的方式,总体算法没有做较多的改动,更多内容可移步博客,代码下载可移步NSGA-II代码。如果有需要本文代码的可移步下载,也可以在评论区留言邮箱。留言邮箱的话麻烦给本篇博文点一下赞哦,或者关注一下博主也可以,你的鼓励是博主更新的最大动力^_^
clear; clc; %%----------代码中用到的一些变量------------ % pop:种群规模 % gen:迭代次数 % pc:交叉概率 % pm:变异概率 % yita1:SBX分布参数 % yita2:多项式变异分布参数 % f_num:目标函数个数 % x_num:决策变量个数 % x_min:决策变量取值范围下界 % x_max:决策变量取值范围上界 % F:pareto等级为pareto_rank的集合 % n:支配当前解的解个数 % s:当前解支配的解个数 %%----------chromo矩阵的组成----------- % 前x_num列:决策变量值 % x_num+1:x_num+f_num列:当前决策向量对应的目标函数值 % x_num+f_num+1列:rank值 % x_num+f_num+1+1列:拥挤度值 %------------------------------------------- %% 函数选择 disp('please input a function you want to optimize') fun = input('from ZDT1—ZDT6、DTLZ1、DTLZ2: ','s'); tic; % 开启计时器 [f_num,x_num,x_min,x_max] = function_select(fun); %% 参数设置 pop=100;%种群大小100 gen=250;%250进化代数 进化代数越高越接近PF pc=0.9;%交叉概率 pm=1/x_num;%变异概率,x-num为决策变量个数 yita1=20;%SBX分布参数 yita2=20;%多项式变异分布参数 %% 种群初始化 chromo=initialize(pop,f_num,x_num,x_min,x_max,fun);%该函数中调用了目标函数表达式 %%初始种群的非支配排序 [F1,chromo_non]=non_domination_sort(pop,chromo,f_num,x_num); %F为pareto等级为pareto_rank的集合,%p为每个个体p的集合(包括每个个体p的被支配个数n和该个体支配的解的集合s),chromo最后一列加入个体的等级 %%计算拥挤度 chromo=crowding_distance_sort(F1,chromo_non,f_num,x_num); i=1; %% 循环开始 for i=1:gen %%二进制竞赛选择(每次取pop/2,所以选两次,保证选择后的种群数量为100) chromo_parent1 = tournament_selection(chromo); %50 chromo_parent2 = tournament_selection(chromo); %50 chromo_parent = [chromo_parent1;chromo_parent2]; %100 % chromo_parent = tournament_selection(chromo); % 只选一次也能满足后续操作,但是没有选两次的效果好 %%模拟二进制交叉与多项式变异 chromo_offspring=cross_mutation(chromo_parent,f_num,x_num,x_min,x_max,pc,pm,yita1,yita2,fun ); %%精英保留策略 %将父代和子代合并 [pop_parent,~]=size(chromo); [pop_offspring,~]=size(chromo_offspring); combine_chromo(1:pop_parent,1:(f_num+x_num))=chromo(:,1:(f_num+x_num)); combine_chromo((pop_parent+1):(pop_parent+pop_offspring),1:(f_num+x_num))=chromo_offspring(:,1:(f_num+x_num)); %快速非支配排序 [pop2,~]=size(combine_chromo); [F2,combine_chromo1]=non_domination_sort(pop2,combine_chromo,f_num,x_num); %计算拥挤度进行排序 combine_chromo2=crowding_distance_sort(F2,combine_chromo1,f_num,x_num); %精英保留产生下一代种群 chromo=elitism(pop,combine_chromo2,f_num,x_num); if mod(i,10) == 0 fprintf('%d gen has completed!\n',i); end end toc;%读取计时器中的数 aaa=toc;%输出计时时间 hold on if(f_num==2)%f-num为目标函数个数 plot(chromo(:,x_num+1),chromo(:,x_num+2),'r*'); end if(f_num==3) plot3(chromo(:,x_num+1),chromo(:,x_num+2),chromo(:,x_num+2),'r*'); end
function [f_num,x_num,x_min,x_max] = function_select(fun) %% 函数选择 %定义 决策变量取值范围,决策变量个数,目标函数个数 %导入 已知PF最前沿 %--------------------ZDT1-------------------- if strcmp(fun,'ZDT1') %strcmp:字符串之间比较 f_num=2;%目标函数个数 x_num=30;%决策变量个数 x_min=zeros(1,x_num);%决策变量的最小值 x_max=ones(1,x_num);%决策变量的最大值 load('ZDT1.txt');%导入正确的前端解 plot(ZDT1(:,1),ZDT1(:,2),'g*'); PP=ZDT1; end %--------------------ZDT2-------------------- if strcmp(fun,'ZDT2') f_num=2;%目标函数个数 x_num=30;%决策变量个数 x_min=zeros(1,x_num);%决策变量的最小值 x_max=ones(1,x_num);%决策变量的最大值 load('ZDT2.txt');%导入正确的前端解 plot(ZDT2(:,1),ZDT2(:,2),'g*'); PP=ZDT2; end %--------------------ZDT3-------------------- if strcmp(fun,'ZDT3') f_num=2;%目标函数个数 x_num=30;%决策变量个数 x_min=zeros(1,x_num);%决策变量的最小值 x_max=ones(1,x_num);%决策变量的最大值 load('ZDT3.txt');%导入正确的前端解 plot(ZDT3(:,1),ZDT3(:,2),'g*'); PP=ZDT3; end %--------------------ZDT4-------------------- if strcmp(fun,'ZDT4') f_num=2;%目标函数个数 x_num=10;%决策变量个数 x_min=[0,-5,-5,-5,-5,-5,-5,-5,-5,-5];%决策变量的最小值 x_max=[1,5,5,5,5,5,5,5,5,5];%决策变量的最大值 load('ZDT4.txt');%导入正确的前端解 plot(ZDT4(:,1),ZDT4(:,2),'g*'); PP=ZDT4; end %--------------------ZDT6-------------------- if strcmp(fun,'ZDT6') f_num=2;%目标函数个数 x_num=10;%决策变量个数 x_min=zeros(1,x_num);%决策变量的最小值 x_max=ones(1,x_num);%决策变量的最大值 load('ZDT6.txt');%导入正确的前端解 plot(ZDT6(:,1),ZDT6(:,2),'g*'); PP=ZDT6; end %-------------------------------------------- %--------------------DTLZ1-------------------- if strcmp(fun,'DTLZ1') f_num=3;%目标函数个数 x_num=10;%决策变量个数 x_min=zeros(1,x_num);%决策变量的最小值 x_max=ones(1,x_num);%决策变量的最大值 load('DTLZ1.txt');%导入正确的前端解 % plot3(DTLZ1(:,1),DTLZ1(:,2),DTLZ1(:,3),'g*'); PP=DTLZ1; end %-------------------------------------------- %--------------------DTLZ2-------------------- if strcmp(fun,'DTLZ2') f_num=3;%目标函数个数 x_num=10;%决策变量个数 x_min=zeros(1,x_num);%决策变量的最小值 x_max=ones(1,x_num);%决策变量的最大值 load('DTLZ2.txt');%导入正确的前端解 % plot3(DTLZ2(:,1),DTLZ2(:,2),DTLZ2(:,3),'g*'); PP=DTLZ2; end end
function chromo = initialize( pop,f_num,x_num,x_min,x_max,fun )
% 种群初始化
for i=1:pop
for j=1:x_num
chromo(i,j)=x_min(j)+(x_max(j)-x_min(j))*rand(1);
end
%计算决策向量对应的目标向量并将其放在决策向量后边
chromo(i,x_num+1:x_num+f_num) = object_fun(chromo(i,:),f_num,x_num,fun);
end
function [F,chromo] = non_domination_sort( pop,chromo,f_num,x_num ) %% 初始化 pareto_rank=1; %初始pareto等级为1 F(pareto_rank).ss=[];%pareto等级为pareto_rank的集合 p=[];%每个个体p的集合 %% 计算所有个体的n、s集,并选出F1中的个体(n=0) for i=1:pop %%%计算出种群中每个个体p的被支配个数n和该个体支配的解的集合s p(i).n=0;%被支配个体数目n初始化为0 p(i).s=[];%支配解的集合s for j=1:pop less=0;%y'的目标函数值小于个体的目标函数值数目 equal=0;%y'的目标函数值等于个体的目标函数值数目 greater=0;%y'的目标函数值大于个体的目标函数值数目 for k=1:f_num if(chromo(i,x_num+k)<chromo(j,x_num+k)) less=less+1; elseif(chromo(i,x_num+k)==chromo(j,x_num+k)) equal=equal+1; else greater=greater+1; end end if(less==0 && equal~=f_num) p(i).n=p(i).n+1;%被支配个体数目n+1 elseif(greater==0 && equal~=f_num) p(i).s=[p(i).s j]; %若less和greater都不等于0,证明两者互不支配 end end %%%判断当前个体n是否为0,若为0,则将其放入集合F(1)中 if(p(i).n==0) chromo(i,f_num+x_num+1)=1;%在决策向量+目标向量后存储个体的等级信息 F(pareto_rank).ss=[F(pareto_rank).ss i]; end end %% 在F1层的基础上,继续进行分层 while ~isempty(F(pareto_rank).ss) %直到某层个体数为0就可以结束分层 temp=[]; for i=1:length(F(pareto_rank).ss) if ~isempty(p(F(pareto_rank).ss(i)).s) for j=1:length(p(F(pareto_rank).ss(i)).s) %n=0个体对应的s集中所有的n-1 p(p(F(pareto_rank).ss(i)).s(j)).n=p(p(F(pareto_rank).ss(i)).s(j)).n - 1; if p(p(F(pareto_rank).ss(i)).s(j)).n==0 %若s集中的个体n-1等于0,则放到下一层上 chromo(p(F(pareto_rank).ss(i)).s(j),f_num+x_num+1)=pareto_rank+1;%储存个体的等级信息 temp=[temp p(F(pareto_rank).ss(i)).s(j)]; %把放到下一层的个体单独存放在temp中 end end end end pareto_rank=pareto_rank+1; F(pareto_rank).ss=temp; %下一次非支配排序基于下一层个体 end
function chromo = crowding_distance_sort( F,chromo,f_num,x_num ) %% 计算拥挤度 %% 按照pareto等级对种群中的个体进行排序,便于逐层求解拥挤度 [~,index]=sort(chromo(:,f_num+x_num+1)); [~,mm1]=size(chromo); temp=zeros(length(index),mm1); for i=1:length(index)%=pop temp(i,:)=chromo(index(i),:);%按照pareto等级排序后种群 end %% 对于每个等级的个体开始计算拥挤度 current_index = 0; for pareto_rank=1:(length(F)-1) %计算F的循环时多了一次空(直到s集中n-1=0的个体数为0时才跳出循环),所以减掉 %%%当前等级拥挤度计算初始化 nd=[]; nd(:,1)=zeros(length(F(pareto_rank).ss),1); %y=[];%储存当前处理的等级的个体 [~,mm2]=size(temp); y=zeros(length(F(pareto_rank).ss),mm2);%储存当前处理的等级的个体 previous_index=current_index + 1; for i=1:length(F(pareto_rank).ss) y(i,:)=temp(current_index + i,:); end current_index=current_index + i; %%%针对每一个目标函数fm计算相邻两解的函数差值 %根据函数值排序,边界点差值直接设为inf,计算中间点差值后附在决策向量+目标向量+rank后 for i=1:f_num %%根据该目标函数值对该等级的个体进行排序 [~,index_objective]=sort(y(:,x_num+i)); %objective_sort=[];%通过目标函数排序后的个体 [~,mm3]=size(y); objective_sort=zeros(length(index_objective),mm3);%通过目标函数排序后的个体 for j=1:length(index_objective) objective_sort(j,:)=y(index_objective(j),:); end %%记fmax为最大值,fmin为最小值 fmin=objective_sort(1,x_num+i); fmax=objective_sort(length(index_objective),x_num+i); %%对排序后的两个边界拥挤度设为1d和nd设为无穷 y(index_objective(1),f_num+x_num+1+i)=Inf; y(index_objective(length(index_objective)),f_num+x_num+1+i)=Inf; %%计算nd=nd+(fm(i+1)-fm(i-1))/(fmax-fmin) for j=2:(length(index_objective)-1) pre_f=objective_sort(j-1,x_num+i); next_f=objective_sort(j+1,x_num+i); if (fmax-fmin==0) y(index_objective(j),f_num+x_num+1+i)=Inf; else y(index_objective(j),f_num+x_num+1+i)=(next_f-pre_f)/(fmax-fmin); end end end %%%计算拥挤度 %多个目标函数相邻解差值求和,计算拥挤度,并将最终拥挤度附在决策向量+目标向量+rank后 for i=1:f_num nd(:,1)=nd(:,1)+y(:,f_num+x_num+1+i); end %第2列保存拥挤度,其他的覆盖掉 y(:,f_num+x_num+2)=nd; y=y(:,1:(f_num+x_num+2)); temp_two(previous_index:current_index,:) = y; %将当前等级计算出的y储存到temp_two中 end chromo=temp_two; end
function chromo_parent = tournament_selection( chromo ) %% 二进制竞标赛选择 [pop, index] = size(chromo); touranment=2; %(两两抉择) a=round(pop/2); %初始化 chromo_candidate=zeros(touranment,1); chromo_rank=zeros(touranment,1); chromo_distance=zeros(touranment,1); chromo_parent=zeros(a,index); % 获取等级的索引 rank = index - 1; % 获得拥挤度的索引 distance = index; for i=1:a for j=1:touranment chromo_candidate(j)=round(pop*rand(1));%随机产生候选者 if(chromo_candidate(j)==0)%索引从1开始 chromo_candidate(j)=1; end if(j>1) while (~isempty(find(chromo_candidate(1:j-1)==chromo_candidate(j)))) chromo_candidate(j)=round(pop*rand(1)); if(chromo_candidate(j)==0)%索引从1开始 chromo_candidate(j)=1; end end end end for j=1:touranment chromo_rank(j)=chromo(chromo_candidate(j),rank); chromo_distance(j)=chromo(chromo_candidate(j),distance); end %取出低等级的个体索引 minchromo_candidate=find(chromo_rank==min(chromo_rank)); %多个索引按拥挤度排序 if (length(minchromo_candidate)~=1) maxchromo_candidate=find(chromo_distance(minchromo_candidate)==max(chromo_distance(minchromo_candidate))); if(length(maxchromo_candidate)~=1) maxchromo_candidate = maxchromo_candidate(1); end chromo_parent(i,:)=chromo(chromo_candidate(minchromo_candidate(maxchromo_candidate)),:); else chromo_parent(i,:)=chromo(chromo_candidate(minchromo_candidate(1)),:); end end end
function chromo_offspring = cross_mutation( chromo_parent,f_num,x_num,x_min,x_max,pc,pm,yita1,yita2,fun ) %模拟二进制交叉与多项式变异 [pop,~]=size(chromo_parent); suoyin=1; for i=1:pop %%%模拟二进制交叉 %初始化子代种群 %随机选取两个父代个体 parent_1=round(pop*rand(1)); if (parent_1<1) parent_1=1; end parent_2=round(pop*rand(1)); if (parent_2<1) parent_2=1; end %确定两个父代个体不是同一个 while isequal(chromo_parent(parent_1,:),chromo_parent(parent_2,:)) parent_2=round(pop*rand(1)); if(parent_2<1) parent_2=1; end end chromo_parent_1=chromo_parent(parent_1,:); chromo_parent_2=chromo_parent(parent_2,:); off_1=chromo_parent_1;%将子代初始化为chromo_parent1 off_2=chromo_parent_1; if(rand(1)<pc) %进行模拟二进制交叉 u1=zeros(1,x_num); gama=zeros(1,x_num); for j=1:x_num u1(j)=rand(1); if u1(j)<0.5 gama(j)=(2*u1(j))^(1/(yita1+1)); else gama(j)=(1/(2*(1-u1(j))))^(1/(yita1+1)); end off_1(j)=0.5*((1+gama(j))*chromo_parent_1(j)+(1-gama(j))*chromo_parent_2(j)); off_2(j)=0.5*((1-gama(j))*chromo_parent_1(j)+(1+gama(j))*chromo_parent_2(j)); %使子代在定义域内 if(off_1(j)>x_max(j)) off_1(j)=x_max(j); elseif(off_1(j)<x_min(j)) off_1(j)=x_min(j); end if(off_2(j)>x_max(j)) off_2(j)=x_max(j); elseif(off_2(j)<x_min(j)) off_2(j)=x_min(j); end end %计算子代个体的目标函数值 off_1(1,(x_num+1):(x_num+f_num))=object_fun(off_1,f_num,x_num,fun); off_2(1,(x_num+1):(x_num+f_num))=object_fun(off_2,f_num,x_num,fun); end %%%多项式变异 if(rand(1)<pm) u2=zeros(1,x_num); delta=zeros(1,x_num); for j=1:x_num u2(j)=rand(1); if(u2(j)<0.5) delta(j)=(2*u2(j))^(1/(yita2+1))-1; else delta(j)=1-(2*(1-u2(j)))^(1/(yita2+1)); end off_1(j)=off_1(j)+delta(j); %使子代在定义域内 if(off_1(j)>x_max(j)) off_1(j)=x_max(j); elseif(off_1(j)<x_min(j)) off_1(j)=x_min(j); end end %计算子代个体的目标函数值 off_1(1,(x_num+1):(x_num+f_num))=object_fun(off_1,f_num,x_num,fun); end if(rand(1)<pm) u2=zeros(1,x_num); delta=zeros(1,x_num); for j=1:x_num u2(j)=rand(1); if(u2(j)<0.5) delta(j)=(2*u2(j))^(1/(yita2+1))-1; else delta(j)=1-(2*(1-u2(j)))^(1/(yita2+1)); end off_2(j)=off_2(j)+delta(j); %使子代在定义域内 if(off_2(j)>x_max(j)) off_2(j)=x_max(j); elseif(off_2(j)<x_min(j)) off_2(j)=x_min(j); end end %计算子代个体的目标函数值 off_2(1,(x_num+1):(x_num+f_num))=object_fun(off_2,f_num,x_num,fun); end off(suoyin,:)=off_1; off(suoyin+1,:)=off_2; suoyin=suoyin+2; end chromo_offspring=off; end
function chromo = elitism( pop,combine_chromo2,f_num,x_num ) %% 精英保留策略 %总体思路——依照文中定义的偏序关系: %先按照Pareto等级选取子代,最后在同一等级中按照拥挤度选取子代 %% 根据pareto等级从高到低进行排序 [pop2,temp]=size(combine_chromo2); chromo_rank=zeros(pop2,temp); chromo=zeros(pop,(f_num+x_num+2)); %初始化存放排序后种群的矩阵 [~,index_rank]=sort(combine_chromo2(:,f_num+x_num+1)); for i=1:pop2 chromo_rank(i,:)=combine_chromo2(index_rank(i),:); end %求出最高的pareto等级 max_rank=max(combine_chromo2(:,f_num+x_num+1)); %% 形成子代 %根据排序后的顺序,将等级相同的种群整个放入父代种群中,直到某一层不能全部放下为止 prev_index=0; for i=1:max_rank %寻找当前等级i个体里的最大索引 current_index=max(find(chromo_rank(:,(f_num+x_num+1))==i)); %不能放下为止 if(current_index>pop) %剩余群体数 remain_pop=pop-prev_index; %等级为i的个体 temp=chromo_rank(((prev_index+1):current_index),:); %根据拥挤度从大到小排序 [~,index_crowd]=sort(temp(:,(f_num+x_num+2)),'descend'); %填满父代 for j=1:remain_pop chromo(prev_index+j,:)=temp(index_crowd(j),:); end return; elseif(current_index<pop) % 将所有等级为i的个体直接放入父代种群 chromo(((prev_index+1):current_index),:)=chromo_rank(((prev_index+1):current_index),:); else % 将所有等级为i的个体直接放入父代种群 chromo(((prev_index+1):current_index),:)=chromo_rank(((prev_index+1):current_index),:); return; end prev_index = current_index; end end
function f = object_fun( x,f_num,x_num,fun ) % 测试函数的设置 % --------------------ZDT1-------------------- if strcmp(fun,'ZDT1') f=[]; f(1)=x(1); sum=0; for i=2:x_num sum = sum+x(i); end g=1+9*(sum/(x_num-1)); f(2)=g*(1-(f(1)/g)^0.5); end % --------------------ZDT2-------------------- if strcmp(fun,'ZDT2') f=[]; f(1)=x(1); sum=0; for i=2:x_num sum = sum+x(i); end g=1+9*(sum/(x_num-1)); f(2)=g*(1-(f(1)/g)^2); end % --------------------ZDT3-------------------- if strcmp(fun,'ZDT3') f=[]; f(1)=x(1); sum=0; for i=2:x_num sum = sum+x(i); end g=1+9*(sum/(x_num-1)); f(2)=g*(1-(f(1)/g)^0.5-(f(1)/g)*sin(10*pi*f(1))); end % --------------------ZDT4-------------------- if strcmp(fun,'ZDT4') f=[]; f(1)=x(1); sum=0; for i=2:x_num sum = sum+(x(i)^2-10*cos(4*pi*x(i))); end g=1+9*10+sum; f(2)=g*(1-(f(1)/g)^0.5); end % --------------------ZDT6-------------------- if strcmp(fun,'ZDT6') f=[]; f(1)=1-(exp(-4*x(1)))*((sin(6*pi*x(1)))^6); sum=0; for i=2:x_num sum = sum+x(i); end g=1+9*((sum/(x_num-1))^0.25); f(2)=g*(1-(f(1)/g)^2); end % -------------------------------------------- % --------------------DTLZ1-------------------- if strcmp(fun,'DTLZ1') f=[]; sum=0; for i=3:x_num sum = sum+((x(i)-0.5)^2-cos(20*pi*(x(i)-0.5))); end g=100*(x_num-2)+100*sum; f(1)=(1+g)*x(1)*x(2); f(2)=(1+g)*x(1)*(1-x(2)); f(3)=(1+g)*(1-x(1)); end % -------------------------------------------- % --------------------DTLZ2-------------------- if strcmp(fun,'DTLZ2') f=[]; sum=0; for i=3:x_num sum = sum+(x(i))^2; end g=sum; f(1)=(1+g)*cos(x(1)*pi*0.5)*cos(x(2)*pi*0.5); f(2)=(1+g)*cos(x(1)*pi*0.5)*sin(x(2)*pi*0.5); f(3)=(1+g)*sin(x(1)*pi*0.5); end % -------------------------------------------- end
本文参考代码:
更多优秀代码:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。