【笔记2021-11-19】NSGAII代码 MATLAB

  1. nsga_2.m
function nsga_2(pop,gen)
% 函数名字叫nsga_2,参数是pop=种群大小,gen遍历的代数

%% 检测输入的各种问题

if nargin < 2 % nargin是MATLAB中管参数数量的
% 要是参数数量小于2说明少输入了
    error('NSGA-II: Please enter the population size and number of generations as input arguments.');
end

% 两个输入参数都需要为整数数据类型
if isnumeric(pop) == 0 || isnumeric(gen) == 0
    error('Both input arguments pop and gen should be integer datatype');
end
% 最小人口数必须为20个人,最小代数为5
if pop < 20
    error('Minimum population for running this function is 20');
end
if gen < 5
    error('Minimum number of generations is 5');
end
% 确保pop和gen是整数
% round函数用于舍入到最接近的整数
pop = round(pop);
gen = round(gen);


%% 目标函数
%M是目标空间的维数,V是决策变量空间的维数。min_range和max_range是决策变量空间中变量的范围
%用户必须使用决策变量定义目标函数。确保编辑函数“ evaluate_objective”以适合您的需求。
[M, V, min_range, max_range] = objective_description_function();

截止到这里,nsga_2.m文件没有完----1
objective_description_function()是另一个.m文件,在下边
1----接nsga_2.m文件

%% 初始化种群
%在特定范围内的随机值来进行种群的初始化,每个染色体都是由决策变量组成,同时目标函数,rank等级和拥挤距离信息的值也被添加到染色体向量中
%但是只有当中含有函数决策变量的向量元素才会进行遗传的操作,比如交叉变异(这一步不是全部都要执行的)

chromosome = initialize_variables(pop, M, V, min_range, max_range);


%% 初始化种群的排序
%使用非支配排序对总体进行排序。 会为每个个体返回两列,这两列的内容是所处位置对应的rank等级和拥挤度距离
%对每条染色体来说,添加rank等级和拥挤度距离到染色体向量中,以便于计算

chromosome = non_domination_sort_mod(chromosome, M, V);

%% 开始进化过程
% 在每一代中执行以下操作
% * 选择适合繁殖的父代
% * 对选定的父代执行交叉和变异的操作
% * 从父代和其后代中进行选择
% * 用适合的个体替换不适合的个体,以维持恒定的人口规模。

for i = 1 : gen
    % 选取父代,产生子代,原始的NSGA-II是基于拥挤度比较算子通过binary tournament selection二进制竞标赛选择
    % The arguments are 
    % pool - 交配池的大小,通常来说是种群数量的一半
    % tour - 竞标赛大小. 二级制竞标赛选择,但是要查看这个竞标赛大小的影响,这个是任意的,是由用户决定的
    pool = round(pop/2);
    tour = 2;
    % 选择过程
    %二进制随机数和它们的适应度进行比较,适应度高的个体被选为作为父代,比赛选择一直到交配池满为止,
    %一般来说池的大小就是被选择作为父代的个数
    %函数tournament_selection输入的参数是 染色体、交配池大小、竞标赛大小
    
    %该函数仅使用来自染色体向量中最后两个元素的信息。最后一个元素具有拥挤距离信息,而倒数第二个元素rank等级的信息。
    %选择基于rank等级,如果遇到具有相同等级的个人,则比较拥挤距离。 较低的等级和较高的拥挤距离是选择标准。
    
    
    parent_chromosome = tournament_selection(chromosome, pool, tour);

    % 进行交叉和变异操作
    %原始的NSGA-II算法使用模拟二进制交叉(SBX)和多项式变异。 交叉概率pc = 0.9,变异概率为pm = 1 / n,
    %其中n是决策变量的数量。 在原始算法中同时实现了实编码GA和二进制编码GA,而在此程序中,仅考虑了实编码GA。 
    %交叉算子和变异算子的分布指数分别为mu = 20和mum = 20。
    % The original NSGA-II algorithm uses Simulated Binary Crossover (SBX) and
    % Polynomial  mutation. Crossover probability pc = 0.9 and mutation
    % probability is pm = 1/n, where n is the number of decision variables.
    % Both real-coded GA and binary-coded GA are implemented in the original
    % algorithm, while in this program only the real-coded GA is considered.
    % The distribution indeices for crossover and mutation operators as mu = 20
    % and mum = 20 respectively.
    mu = 20;
    mum = 20;
    offspring_chromosome = ...
        genetic_operator(parent_chromosome, ...
        M, V, mu, mum, min_range, max_range);

    % Intermediate population(中间种群)
    %中间种群是当前这一代父母和后代的总人口。 人口规模是初始人口的两倍。
    
    [main_pop,temp] = size(chromosome);
    [offspring_pop,temp] = size(offspring_chromosome);
    % temp 是一个虚拟变量.
    clear temp
    % intermediate_chromosome 是当前种群和后代种群的串联(中间种群)
    intermediate_chromosome(1:main_pop,:) = chromosome;
    intermediate_chromosome(main_pop + 1 : main_pop + offspring_pop,1 : M+V) = ...
        offspring_chromosome;

    % 中间种群的非支配排序
    %在对中间种群进行替换操作之前,中间种群再一次进行排序,这次的排序是基于非支配排序的
    
    intermediate_chromosome = ...
        non_domination_sort_mod(intermediate_chromosome, M, V);
    % 执行选择
    %一旦对中间种群进行排序,根据rank等级和拥挤度距离来进行选优的
    %每个前沿都以升序填充,直到达到人口总数为止。
    
    
    %种群的最后一层,是根据拥挤度距离判断的
    %(这个注意,在填充最后一层的时候,一般都是在一个同一个大的等级中去选择,这时候比较的就是拥挤度距离了,这也是这个算法拥挤度距离的使用之处)
    
    
    % The last front is included in the population based on the individuals with
    % least crowding distance
    chromosome = replace_chromosome(intermediate_chromosome, M, V, pop);
    if ~mod(i,100)
        clc
        fprintf('%d generations completed\n',i);
    end
end

%% Result结果
% Save the result in ASCII text format.将结果保存为ASCII文本格式。
save solution.txt chromosome -ASCII

%% Visualize可视化
% 如果目标空间的尺寸是可视的,则以下内容用于可视化结果。
if M == 2
    plot(chromosome(:,V + 1),chromosome(:,V + 2),'*');
elseif M ==3
    plot3(chromosome(:,V + 1),chromosome(:,V + 2),chromosome(:,V + 3),'*');
end
  1. objective_description_function.m
function [number_of_objectives, number_of_decision_variables, min_range_of_decesion_variable, max_range_of_decesion_variable] = objective_description_function()
% 四个返回的值是:目标函数个数、决策变量个数、决策变量最小范围、最大范围
%  %sprintf函数将数据格式化为字符串或字符向量。估计意思就是提醒用户输入目标函数维度
g = sprintf('Input the number of objective: ');
% 获得目标函数数
% Obtain the number of objective function
%  %input输入的东西当成数字或者矩阵;就是把字符串的g转化成数字
number_of_objectives = input(g);
if number_of_objectives < 2
   error('This is a multi-objective optimization function hence the minimum number of objectives is two');
end
g = sprintf('\nInput the number of decision variables: ');
% 获取决策变量的数量
% Obtain the number of decision variables
number_of_decision_variables = input(g);
clc
for i = 1 : number_of_decision_variables
   clc
   g = sprintf('\nInput the minimum value for decision variable %d : ', i);
   % 获得每个决策变量的最小可能值
   % Obtain the minimum possible value for each decision variable
   min_range_of_decesion_variable(i) = input(g);
   g = sprintf('\nInput the maximum value for decision variable %d : ', i);
   % 获得每个决策变量的最大可能值
   % Obtain the maximum possible value for each decision variable
   max_range_of_decesion_variable(i) = input(g);
   clc
end
g = sprintf('\n Now edit the function named "evaluate_objective" appropriately to match your needs.\n Make sure that the number of objective functions and decision variables match your numerical input. \n Make each objective function as a corresponding array element. \n After editing do not forget to save. \n Press "c" and enter to continue... ');
%提示用户编辑evaluate_objective函数,并等待直到按下“ c”。
% Prompt the user to edit the evaluate_objective function and wait until
% 'c' is pressed.
x = input(g, 's');%输入的东西当成字符串存起来;
if isempty(x)
   x = 'x';
end
while x ~= 'c'% ~=是不等于的意思
   clc
   x = input(g, 's');
   if isempty(x)
       x = 'x';
   end
end    

  1. initialize_variables.m
function f = initialize_variables(N, M, V, min_range, max_range)

%% function f = initialize_variables(N, M, V, min_tange, max_range) 
%这个函数来初始化种群的,每个染色体都有着如下的步骤
% This function initializes the chromosomes. Each chromosome has the
% following at this stage
%       * set of decision variables 设定决策变量
%       * objective function values  目标函数值
% 
% where,
% N - Population size 种群的大小
% M - Number of objective functions 目标函数的数量
% V - Number of decision variables 决策变量的数量
% min_range - A vector of decimal values which indicate the minimum value
% for each decision variable.十进制值的向量,指示每个决策变量的最小值
% max_range - Vector of maximum possible values for decision
% variables.决策变量的最大值  


min = min_range;
max = max_range;
%K是数组元素的总数。为了便于计算,将决策变量和目标函数连接
%在一起以形成单个数组。 对于交叉和变异,仅使用决策变量,而对于选择,仅使用目标变量。
% K is the total number of array elements. For ease of computation decision
% variables and objective functions are concatenated to form a single
% array. For crossover and mutation only the decision variables are used
% while for selection, only the objective variable are utilized.

K = M + V;

%% Initialize each chromosome 初始化每条染色体
%每条染色体都会执行以下操作
% For each chromosome perform the following (N is the population size)
for i = 1 : N
    %根据最小值和最大值初始化决策变量可能的值。 
    %V是决策变量的数量。 在每个决策变量的最小和最大值之间选择一个随机数。
    % Initialize the decision variables based on the minimum and maximum
    % possible values. V is the number of decision variable. A random
    % number is picked between the minimum and maximum possible values for
    % the each decision variable.
    for j = 1 : V
        f(i,j) = min(j) + (max(j) - min(j))*rand(1);
    end
    %为了方便计算,染色体最后连接了目标函数的值,元素V + 1 到 K是具有目标函数值的
    % For ease of computation and handling data the chromosome also has the
    % vlaue of the objective function concatenated at the end. The elements
    % V + 1 to K has the objective function valued. 
    
    
    %函数evaluate_objective每次只获取一条染色体
    %实际上,只有决策变量与有关已处理目标函数数目的信息一起传递给函数,并返回目标函数的值。 这些
    %值现在存储在染色体本身的末尾。
    % The function evaluate_objective takes one chromosome at a time,
    % infact only the decision variables are passed to the function along
    % with information about the number of objective functions which are
    % processed and returns the value for the objective functions. These
    % values are now stored at the end of the chromosome itself.
    f(i,V + 1: K) = evaluate_objective(f(i,:), M, V);
end

  1. non_domination_sort_mod.m
function f = non_domination_sort_mod(x, M, V)

%% function f = non_domination_sort_mod(x, M, V)
%这个函数进行非支配排序,所有个体在第一层的rank等级是1,在第二层的rank等级是2,以此类推
%等级分配完成后,计算每个前沿的拥挤度


[N, m] = size(x);
clear m

%初始化当前的层级号为1
% Initialize the front number to 1.
front = 1;

%此作业没有任何内容,仅用于轻松操作的MATLAB
% There is nothing to this assignment, used only to manipulate easily in
% MATLAB.
F(front).f = [];
individual = [];

%% Non-Dominated sort. 非支配排序
%初始化的种群基于非支配性进行排序。 快速排序算法[1]如下所述
% The initialized population is sorted based on non-domination. The fast
% sort algorithm [1] is described as below for each

%对于每个种群P当中的个体p都有着如下的操作
% ? for each individual p in main population P do the following
%  Sp是一个集合,代表着你在支配着谁,这个[]里面写的是种群的个体
%  该集合包含着所有由p支配的个体
%   ? Initialize Sp = []. This set would contain all the individuals that is
%     being dominated by p.
%  np是一个数,代表着有多少人支配着你
%  这就是支配p的个体数量。
%   ? Initialize np = 0. This would be the number of individuals that domi-
%     nate p.
%   对于P种群的个体q来说(种群的另一个个体)
%   ? for each individual q in P
%  如果p支配q,那么就把q放进Sp的集合中
%       * if p dominated q then
%           ? add q to the set Sp i.e. Sp = Sp ? {q}
%  如果q支配p,那么np的数量就加一了
%       * else if q dominates p then
%           ? increment the domination counter for p i.e. np = np + 1
% 如果np为0,说明没有个体支配p,那么p就是属于第一层级
%把个体p放入当rank=1的层级,更新层级


%   ? if np = 0 i.e. no individuals dominate p then p belongs to the first
%     front; Set rank of individual p to one i.e prank = 1. Update the first
%     front set by adding p to front one i.e F1 = F1 ? {p}
%  这是对种群P中所有个体进行执行的
%  初始化层级的计数为1

% ? This is carried out for all the individuals in main population P.
% ? Initialize the front counter to one. i = 1
% 接下来是当第i层Fi不等于空的时候执行的
%Q = []这个集合是用来储存在第i+1层的个体

%对于每个在Fi层的Sp(受p支配的个体的集合)集合的p中
%nq。。。减少个体的支配数
%nq=0 没有个体在随后接下来的前沿中支配q,因此设置q的等级为i+1,更新Q
%前沿计数加一,集合Q就是下一层,因此Fi=Q

% ? following is carried out while the ith front is nonempty i.e. Fi != []
%   ? Q = []. The set for storing the individuals for (i + 1)th front.
%   ? for each individual p in front Fi
%       * for each individual q in Sp (Sp is the set of individuals
%         dominated by p)
%           ? nq = nq?1, decrement the domination count for individual q.
%           ? if nq = 0 then none of the individuals in the subsequent
%             fronts would dominate q. Hence set qrank = i + 1. Update
%             the set Q with individual q i.e. Q = Q ? q.
%   ? Increment the front counter by one.
%   ? Now the set Q is the next front and hence Fi = Q.
%
% This algorithm is better than the original NSGA ([2]) since it utilize
% the informatoion about the set that an individual dominate (Sp) and
% number of individuals that dominate the individual (np).

%
for i = 1 : N
    %支配这个个体的个体数
    % Number of individuals that dominate this individual
    individual(i).n = 0;
    %站主导地位的个体(支配别人的个体)
    % Individuals which this individual dominate
    individual(i).p = [];
    for j = 1 : N
        dom_less = 0;
        dom_equal = 0;
        dom_more = 0;
        for k = 1 : M
            if (x(i,V + k) < x(j,V + k))
                dom_less = dom_less + 1;
            elseif (x(i,V + k) == x(j,V + k))
                dom_equal = dom_equal + 1;
            else
                dom_more = dom_more + 1;
            end
        end
        if dom_less == 0 && dom_equal ~= M
            individual(i).n = individual(i).n + 1;
        elseif dom_more == 0 && dom_equal ~= M
            individual(i).p = [individual(i).p j];
        end
    end   
    if individual(i).n == 0
        x(i,M + V + 1) = 1;
        F(front).f = [F(front).f i];
    end
end
%找到之后的前沿
% Find the subsequent fronts
while ~isempty(F(front).f)
   Q = [];
   for i = 1 : length(F(front).f)
       if ~isempty(individual(F(front).f(i)).p)
        	for j = 1 : length(individual(F(front).f(i)).p)
            	individual(individual(F(front).f(i)).p(j)).n = ...
                	individual(individual(F(front).f(i)).p(j)).n - 1;
        	   	if individual(individual(F(front).f(i)).p(j)).n == 0
               		x(individual(F(front).f(i)).p(j),M + V + 1) = ...
                        front + 1;
                    Q = [Q individual(F(front).f(i)).p(j)];
                end
            end
       end
   end
   front =  front + 1;
   F(front).f = Q;
end

[temp,index_of_fronts] = sort(x(:,M + V + 1));
for i = 1 : length(index_of_fronts)
    sorted_based_on_front(i,:) = x(index_of_fronts(i),:);
end
current_index = 0;

%% Crowding distance拥挤度距离
%The crowing distance is calculated as below计算方式如下
%对于每一个前沿Fi来说,n是个体的数量
% ? For each front Fi, n is the number of individuals.
%对于所有的个体来说,初始化距离是0
%j对应的是在前沿Fi上 的第j个个体
%   ? initialize the distance to be zero for all the individuals i.e. Fi(dj ) = 0,
%     where j corresponds to the jth individual in front Fi.
%对于每一个目标函数m来说
%   ? for each objective function m
%       是基于目标函数m来对Fi上的个体进行排序
%       * Sort the individuals in front Fi based on objective m i.e. I =
%         sort(Fi,m).
%       为每个个体的边界值分配无限距离(距离为无穷大)
%       * Assign infinite distance to boundary values for each individual
%         in Fi i.e. I(d1) = ? and I(dn) = ?
%       * for k = 2 to (n ? 1)
%           ? I(dk) = I(dk) + (I(k + 1).m ? I(k ? 1).m)/fmax(m) - fmin(m)
%           ? I(k).m is the value of the mth objective function of the kth
%             individual in I   第I前沿中,第k个个体的第m个目标函数值

%在每个前沿中为每个个体找出它的拥挤度距离
% Find the crowding distance for each individual in each front
for front = 1 : (length(F) - 1)
%    objective = [];
    distance = 0;
    y = [];
    previous_index = current_index + 1;
    for i = 1 : length(F(front).f)
        y(i,:) = sorted_based_on_front(current_index + i,:);
    end
    current_index = current_index + i;
    %对每个个体基于它的目标函数进行排序
    % Sort each individual based on the objective
    sorted_based_on_objective = [];
    for i = 1 : M
        [sorted_based_on_objective, index_of_objectives] = ...
            sort(y(:,V + i));
        sorted_based_on_objective = [];
        for j = 1 : length(index_of_objectives)
            sorted_based_on_objective(j,:) = y(index_of_objectives(j),:);
        end
        f_max = ...
            sorted_based_on_objective(length(index_of_objectives), V + i);
        f_min = sorted_based_on_objective(1, V + i);
        y(index_of_objectives(length(index_of_objectives)),M + V + 1 + i)...
            = Inf;
        y(index_of_objectives(1),M + V + 1 + i) = Inf;
         for j = 2 : length(index_of_objectives) - 1
            next_obj  = sorted_based_on_objective(j + 1,V + i);
            previous_obj  = sorted_based_on_objective(j - 1,V + i);
            if (f_max - f_min == 0)
                y(index_of_objectives(j),M + V + 1 + i) = Inf;
            else
                y(index_of_objectives(j),M + V + 1 + i) = ...
                     (next_obj - previous_obj)/(f_max - f_min);
            end
         end
    end
    distance = [];
    distance(:,1) = zeros(length(F(front).f),1);
    for i = 1 : M
        distance(:,1) = distance(:,1) + y(:,M + V + 1 + i);
    end
    y(:,M + V + 2) = distance;
    y = y(:,1 : M + V + 2);
    z(previous_index:current_index,:) = y;
end
f = z();

你可能感兴趣的:(flag高高立起,flag)