【NSGA-II 算法细节】

对于这个算法,需要掌握三大核心机制:(1)快速非支配排序(Fast Non-dominated Sorting) (2)拥挤度距离(Crowding Distance) (3) 精英保留策略(Elitism)

原始论文:Deb et al., 2002, A Fast and Elitist Multiobjective Genetic Algorithm: NSGA-II

算法主要流程:

python 复制代码
1. 初始化种群 P0(规模 N),随机生成
2. 对 P0 进行非支配排序和拥挤度计算
3. 选择、交叉、变异 → 生成子代 Q0
4. 循环直到满足终止条件:
   a. 合并 Rt = Pt ∪ Qt
   b. 对 Rt 快速非支配排序
   c. 逐层选择,最后一层用拥挤度筛选
   d. 得到新父代 Pt+1
   e. 对 Pt+1 选择、交叉、变异 → Qt+1
5. 输出 Pareto 前沿解集

一、快速非支配解排序

将种群分层。第一层是完全不被支配的解,第二层是去掉第一层后不被支配的解,依此类推。

要点:支配判断是"所有目标不劣,且至少一个严格更优"。

这里的复杂度是O(MN^2),用空间换时间,原本的NSGA复杂度为O(MN^3),两两比较的复杂度是O(MN^2),然后每次选完一层又要重新比较一次,最坏的结果是每层只有一个,这样的话复杂度就是 O(MN^3),重复计算带来的复杂度,可以把重复计算的结果记录下来,这样能够降低复杂度。相当于是用了一个列表来维护信息。

Deb 教授引入了两个关键的"列表(空间)"来记录信息,避免重复比较:

  • 列表 1:np(被支配计数)。记录个体 p 被多少个其他个体支配。

  • 列表 2:Sp(支配集合)。记录个体 p 支配了哪些其他个体。

优化后的流程(只扫描一遍两两比较):

  1. 初始化:所有个体的 np=0,Sp=∅。

  2. 两两比较(仅此一次):遍历所有个体对 (p,q)。

    • 如果 p 支配 q:把 q 加入 Sp(记录在列表里),并且 q 的被支配计数 nq += 1。

    • 如果 q 支配 p:把 p 加入 Sq​,并且 np+=1。

    • 这一步只做了 次比较,每次比较 M 个目标。总复杂度:O(MN^2)

  3. 找第 1 层:遍历所有个体,凡是 np==0 的,就是第 1 层。

  4. 找第 2 层(利用列表,无需重新比较!)

    • 遍历第 1 层中的每个个体 p。

    • 查看 p 的支配列表 Sp​。对于 Sp​ 中的每个个体 q,执行 nq−=1(因为支配 q 的 p 已经被移除了)。

    • 如果 nq​ 减到了 0,说明 q 现在没人支配了,把 q 放入第 2 层。

  5. 继续:重复步骤 4,直到所有层划分完毕。

python 复制代码
def fast_non_dominated_sort(self, obj):
    N = obj.shape[0]
    S = [[] for _ in range(N)]      # 每个解支配的解
    n = np.zeros(N, dtype=int)      # 被支配次数
    fronts = [[]]                   # 第一层

    for p in range(N):
        for q in range(N):
            if p == q:
                continue
            # p 支配 q ?
            if np.all(obj[p] <= obj[q]) and np.any(obj[p] < obj[q]):
                S[p].append(q)
            elif np.all(obj[q] <= obj[p]) and np.any(obj[q] < obj[p]):
                n[p] += 1
        if n[p] == 0:
            fronts[0].append(p)

    # 逐层构造
    i = 0
    while fronts[i]:
        next_front = []
        for p in fronts[i]:
            for q in S[p]:
                n[q] -= 1
                if n[q] == 0:
                    next_front.append(q)
        i += 1
        fronts.append(next_front)

    fronts.pop()  # 去掉最后的空层
    return fronts

二、 拥挤度距离

易错点:归一化分母用该目标在当前层内的极差,边界解必须设为无穷大。

python 复制代码
def crowding_distance(self, obj, front):
    l = len(front)
    distance = np.zeros(l)
    if l == 0:
        return distance
    if l <= 2:
        distance[:] = np.inf
        return distance

    obj_front = obj[front]          # (l, n_obj)
    n_obj = obj_front.shape[1]

    for m in range(n_obj):
        idx = np.argsort(obj_front[:, m])
        distance[idx[0]] = np.inf
        distance[idx[-1]] = np.inf

        f_min = obj_front[idx[0], m]
        f_max = obj_front[idx[-1], m]
        if f_max - f_min == 0:
            continue
        for k in range(1, l - 1):
            distance[idx[k]] += (
                obj_front[idx[k + 1], m] - obj_front[idx[k - 1], m]
            ) / (f_max - f_min)
    return distance

三、精英保留

合并父代子代后,逐层选入,最后一层按拥挤度排序。

python 复制代码
def environmental_selection(self, merged_obj):
    fronts = self.fast_non_dominated_sort(merged_obj)
    new_pop_idx = []
    for front in fronts:
        if len(new_pop_idx) + len(front) <= self.pop_size:
            new_pop_idx.extend(front)
        else:
            # 这一层放不下,按拥挤度选
            cd = self.crowding_distance(merged_obj, front)
            sorted_idx = np.argsort(-cd)   # 降序
            remain = self.pop_size - len(new_pop_idx)
            new_pop_idx.extend([front[i] for i in sorted_idx[:remain]])
            break
    return np.array(new_pop_idx)
相关推荐
机器学习之心5 天前
PINN × LSBoost × NSGA-II × 熵权TOPSIS:一套跑通「建模—优化—决策」的多目标优化框架
多目标优化·pinn·lsboost·熵权topsis·nsga-ii
今天吃饺子24 天前
基于MOPGA-NSGA-II 的电动车多目标路径优化研究(考虑路况天气与充电约束)(MATLAB 实现)
电动汽车·多目标·路径规划·nsga-ii
机器学习之心3 个月前
基于Kriging代理模型与NSGA-II的双色注塑成型工艺参数多目标优化实战
nsga-ii·kriging代理模型·双色注塑成型工艺参数多目标优化
IT猿手9 个月前
基于粒子群算法与动态窗口混合的无人机三维动态避障路径规划研究,MATLAB代码
算法·matlab·无人机·多目标优化算法·多目标算法
青云交1 年前
Java 大视界 -- 基于 Java 的大数据可视化在能源互联网全景展示与能源调度决策支持中的应用
java·大数据可视化·智能决策·能源互联网·三维渲染·能源调度·nsga-ii
IT猿手1 年前
2025年最新原创多目标算法:多目标酶作用优化算法(MOEAO)求解MaF1-MaF15及工程应用---盘式制动器设计,提供完整MATLAB代码
算法·数学建模·matlab·多目标优化算法·多目标算法
IT猿手2 年前
多目标优化算法:多目标蛇鹫优化算法(MOSBOA)求解ZDT1、ZDT2、ZDT3、ZDT4、ZDT6,提供完整MATLAB代码
算法·数学建模·matlab·多目标优化·多目标优化算法
IT猿手2 年前
多目标优化算法:多目标黑翅鸢算法(MOBKA)求解ZDT1、ZDT2、ZDT3、ZDT4、ZDT6,提供完整MATLAB代码
开发语言·算法·matlab·多目标优化·多目标优化算法
IT猿手2 年前
多目标应用:基于多目标雾凇算法(MORIME)的移动机器人路径规划研究(提供MATLAB代码)
前端·人工智能·神经网络·matlab·路径规划·多目标优化算法·机器人路径规划