非支配快速排序算法详解
对NSGA-II的一个学习记录
为易于理解,只用三个点举例子。
Np=3; %三个点
current_vector = [1:1:Np]'; %当前向量
current_pf=1; %先找F1
RANK = zeros(Np,1); %RANK初始化
all_perm = [repmat([1:1:Np]',Np',1), reshape(repmat([1:1:Np],Np,1),Np^2,1)];%生成两列
all_perm(all_perm(:,1)==all_perm(:,2),:) = []; %每个点和其余比较
d=[0 1 0 0 1 1]; %假设支配关系
dominated_particles = unique(all_perm(d==1,2));%依次找到各个点是否受人支配,不在乎受几个人支配,只要受人支配了,那他就不是当前要找的等级。
non_dom_idx = ~ismember(current_vector,dominated_particles);%找到非支配的点的位置,这是一个逻辑值
RANK(current_vector(non_dom_idx)) = current_pf; %让这些位置成为当前等级
all_perm(ismember(all_perm(:,1),current_vector(non_dom_idx)),:) = [];%找到以后,删除,因为一个点只能属于一个等级
all_perm(ismember(all_perm(:,2),current_vector(non_dom_idx)),:) = [];%找到以后,删除,因为一个点只能属于一个等级
current_vector(non_dom_idx) = [];%当前向量中删除那些非支配点
current_pf = current_pf + 1; %等级+1,找下一个等级。
思路以及程序实现过程即为上述。其实在非支配快速排序中还要判断是否已经把所有粒子给分好等级了。有两个跳出循环的地方
1、判断当前向量中是否只有一个点了,要是就一个点了,那他就是最后一个等级了,直接跳出就好了;
2、判断当前向量中,是否没有更多空间去放等级了。(没看太明白,这块直接跳出了,等级也没加,可能就是一个判断的过程。)不影响分等级。
有两个函数,快速非支配排序和比较函数
function [RANK] = FastNonDominatedSorting_Vectorized(fitness)
% Initialization
Np = size(fitness,1);
RANK = zeros(Np,1);
current_vector = [1:1:Np]';
current_pf = 1;
all_perm = [repmat([1:1:Np]',Np',1), reshape(repmat([1:1:Np],Np,1),Np^2,1)];
all_perm(all_perm(:,1)==all_perm(:,2),:) = []; %每个个体去和别人比。 一个个体有两个目标函数值
% Computing each Pareto Front
while ~isempty(current_vector) %非空,就是我这100个个体还没分完等级呢。
% Check if there is only a single particle
if length(current_vector) == 1
RANK(current_vector) = current_pf;
break;
end
% Non-dominated particles
% Note: nchoosek has an exponential grow in computation time, so
% it's better to take all the combinations including repetitions using a
% loops (quasi-linear grow) or repmats (linear grow)
%all_perm = nchoosek(current_vector,2);
%all_perm = [all_perm; [all_perm(:,2) all_perm(:,1)]];
d = dominates(fitness(all_perm(:,1),:),fitness(all_perm(:,2),:));
%d是一个逻辑值,他判断了所有个体和单个个体的支配关系。第一列是2到200,第二列全是1,先判断2到200是不是支配了1。以此类推。
dominated_particles = unique(all_perm(d==1,2));
% 找到被人支配的,unique就是不管是谁支配了1,不管有几个,我只计数一个
% Check if there is no room for more Pareto Fronts
if sum(~ismember(current_vector,dominated_particles)) == 0
break;
end
% Update ranks and current_vector 更新等级
non_dom_idx = ~ismember(current_vector,dominated_particles); %找出那些没有人支配的所在的位置,然后在current_vector中挑出来,就是第一等级
RANK(current_vector(non_dom_idx)) = current_pf; %把这些定为第一等级,其余位置都是0,我不在乎他是第几等级。用逻辑值来判断
all_perm(ismember(all_perm(:,1),current_vector(non_dom_idx)),:) = [];
all_perm(ismember(all_perm(:,2),current_vector(non_dom_idx)),:) = [];%判断完的就把剔除出去
current_vector(non_dom_idx) = []; %判断完的就剔除出去了
current_pf = current_pf + 1; %找下一等级的去,知道找完了才停下来。
end
end
% Function that returns true if x dominates y and false otherwise
function d = dominates(x,y)
d = (all(x<=y,2) & any(x<y,2));
end
只是记录学习,如有错误,请及时指出,谢谢大家。
参考:mathworks NSGA-II(2019年更新的那版)