多目标优化(二)简单的 NSGA-Ⅲ

多目标优化(二)简单的 NSGA-Ⅲ

写在前面:

1、最近好多人收藏了我的文章啊!那就把其他多目标优化学习内容也整理一下!!

2、本文主要介绍自己理解的 NSGA-III Matlab 程序实现,在学习中迷糊的地方都会点出来!!

3、本文程序基于 上一篇 NSGA-II  改编;

4、欢迎指正。

算法概要:

1、基础 Pareto 概念请转:
2、算法目标:我们知道遗传算法会构建一个带有 NP 个个体的种群,单目标输出的就是迭代后种群中最好的 个体。但在多目标中,输出的是迭代后整个种群作为 NP 个 Pareto 最优解,构成一个 Pareto 实际前沿面。(单目标是要找最优个体,多目标是要找最接近理论前沿面的实际前沿面)
3、快速非支配排序:将当代种群根据各个目标函数值进行 Pareto 等级分层(用到非支配解的概念)
4、基于参考点分类个体:在空间中(几个目标就是几维空间),生成一组参考点(参考点个数自定,建议选择和种群大小相同,每个解对应一个参考点是最理想的)
5、选择、交叉、变异:GA基本操作,NSGA-III论文并没有限定选用哪种方法,我觉得可以随意选用
6、精英保留:就是将生成的候选种群和原种群合并,重新 Pareto 分层和计算各个个体归属的参考点,然后按照 Pareto 层级和参考点所拥有的个体数选择前NP 个个体进入下一循环(就是让新种群中个体归属的参考点尽可能均匀分布)

NSGA-II 与 NSGA-III 的区别:

NSGA-II中根据拥挤度来选择个体,NSGA-III根据参考点来选择个体;

拥挤度是一个数值呀,一维上能精确的表示长度,二维上能表示无数种形状的面积,三维上能表示无数的无数种的体积,所以对于多目标(大于3)是不合理的。

参考点是在空间中均匀的选择点位置,画出两目标和三目标的图,应该能理解了吧??

主程序:

clear; close all; clc
global NP x_num f_num iter_max fun bound f_min  % 定义全局变量
% NP:种群大小
% iter_max:最大迭代次数
% f_num:目标个数
% x_num:解得维数
% f_min: 当前寻找到的各目标函数的最小值

%% 测试ZDT1函数,参数如下:
f_num = 2; % 目标函数个数
x_num = 30; % 决策变量个数
x_min = zeros(1,x_num); % 决策变量的最小值
x_max = ones(1,x_num); % 决策变量的最大值
f_min = ones(1, f_num) * inf;
NP = 100; iter_max = 500;
    
% 初始化种群
chromo_ori = x_min + rand(NP, x_num) .* (x_max - x_min);  % 初始化种群
chromo_ori = fun(chromo_ori);  % 计算适应度函数值
[F0, chromo] = non_domination_sort(chromo_ori);  % 子函数:非支配排序
Ref_Points = Gen_RefPoints();  % 子函数:生成参考点

% 开始迭代
for i = 1:iteration

    chromo_parent = chromo(:,1:x_num+f_num+2); % 定义父代种群,最后两列放pareto等级和参考点归属类
    % 交叉 变异
    chromo_cro = crossover(pick_sel, chromo_parent); 
    chromo_mut = mutation(chromo_parent);
    chromo_off = [chromo_cro; chromo_mut]; 

    % 种群合并
    chromo_co = [chromo_parent(:,1:x_num+f_num); chromo_off(:,1:x_num+f_num)]; % 种群个数 2*NP
    [F_i, chromo_co] = non_domination_sort(chromo_co); % 非支配排序
    f_min_new = min(chromo_co(:, x_num+1:x_num+f_num)); % 看看各目标的最小值有没有更新
    if sum(f_min > f_min_new)
        f_min = min(f_min, f_min_new); % 更新各目标最小值
    end
    
    % 精英保留
    chromo_co = Classify_RefPoint(); % 将合并后的种群个体分属于参考点中
    chromo = elitism(chromo_co); % 按 Pareto 等级和拥挤度从2*NP个个体中选出NP个个体进入下一代

end

 

子程序原理:

1、 大部分子程序原理同NSGA-II一样,请转https://blog.csdn.net/weixin_41942547/article/details/102527352

2、 Gen_RefPoints:

① 参考点生成一次就行了,默认是各目标均等的分成几份,然后在多维空间上均匀分布参考点。

② 有几个目标,参考点就是一个几维向量。

function RefPoints = Gen_RefPoints()
    global f_num
    n_div = floor(f_num * 3); % 各目标分成几份
    RefPoints = Get_Matrix(f_num, n_div)' / n_div;
end

function A = Get_Matrix(f_num, n_div)
    if f_num < 1
        error('f_num cannot be less than 1.');
    end
    if floor(f_num) ~= f_num
        error('f_num must be an integer.');
    end
    if f_num == 1
        A = n_div;
        return;
    end
    A = [];
    for i = 0:n_div
        B = Get_Matrix(f_num-1, n_div-i);
        A = [A; i*ones(size(B,1),1) B];
    end
end

3、 Classify_RefPoint:

① 这部分就是NSGA-III的核心也是难点。

② 由于参考点是按标准化计算的,所以我们需要将各目标所在的目标空间转换成和参考点的空间一致。

③ 首先,是改变“原点”,将当前寻找到的个目标值的最小值作为原点,即将目标空间进行平移变换。

④ 其次,由于各目标的取值的区间差异很大,所以将其归一化。(因为参考点也相当于是归一化后取得的)

上两步骤可参考(标准化目标空间)https://zhuanlan.zhihu.com/p/124917159

⑤ 经过上述步骤,就能将参考点完全匹配到目标空间上啦,接下来就是计算每个个体所属的参考点。

⑥ 判断归属的参考点就是计算每个个体到各个参考点向量(“原点”与参考点的连线)的距离,选择最短的那个。

function chromo = Classify_RefPoint(chromo)

    global f_min x_num f_num RefPoints habitat
    
    fit = chromo(:, x_num+1:x_num+f_num);
    fit = fit - f_min; % 函数目标坐标变换
    for i = 1:f_num
        w = 10-6 * ones(1, f_num); w(i) = 1;
        [f_max(i), ~] = min(max(fit ./ w, [], 2));
    end
    fit = fit ./ f_max; % 坐标归一化
    
    for i = 1:numel(habitat)
        w = RefPoints(:, i) / norm(RefPoints(:, i));
        for j = 1:size(chromo, 1)
            dis(j, i) = norm(fit(j, :)' - w'*fit(j, :)'*w);
        end
    end
    [~, idx] = min(dis, [], 2);
    chromo(:, x_num+f_num+2) = idx; % 各个个体归属到哪个参考点

end

4、 elitism:

① 变异后的种群就是子代种群了,和父代种群合并以下吧(变成 2NP 个个体了)
将这 2NP 个个体 Pareto 分层和计算拥挤度吧,
③ 先将 Pareto 等级为1的选中,再选 Pareto 等级为2的,……
④ 选 NP 个就够啦,比如 Pareto 等级为1的个体有 NP/2 个,Pareto等级为2的个体有NP个,那么就需要从Pareto等级为2的个体中挑选出NP/2个。

⑤ 首先,挑选出Pareto等级为1的个体有NP/2个,统计这NP/2个个体归属的参考点各有几个。

⑥ 选择归属的参考点个数最少的参考点,从Pareto等级为2的个体中挑选出一个归属于那个参考点的个体。重复这个过程直到挑出NP/2个个体。

function chromo = elitism(chromo_co)
    
    global NP f_num x_num habitat
    habitat = min(habitat, 0);
    chromo_co_sort = sortrows(chromo_co, x_num+f_num+1); % 按 pareto_rank 排序
    
    chromo = [];
    pareto_rank = 1;
    while size(chromo, 1) < NP
        
        % 取出 pareto_rank 整层
        temp = chromo_co_sort(chromo_co_sort(:,x_num+f_num+1)==pareto_rank,:);
        if (size(temp, 1) + size(chromo, 1)) < NP
            chromo = [chromo; temp];
            for i = 1:size(temp, 1)
               habitat(temp(i, x_num+f_num+2)) = habitat(temp(i, x_num+f_num+2)) + 1; 
            end
        else
            while size(chromo, 1) < NP
                [~, idx] = min(habitat); % 找出小生境中数量最少的
                pick = find(temp(:, x_num+f_num+2)==idx);
                if isempty(pick)
                    habitat(idx) = inf;
                else
                    chromo = [chromo; temp(pick(1), :)];
                    temp(pick(1), :) = [];
                    habitat(idx) = habitat(idx) + 1;
                end
            end
        end
        pareto_rank = pareto_rank + 1;
    end
 
end

可执行的完整代码见:https://download.csdn.net/download/weixin_41942547/15467105

  • 7
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值