非支配性排序遗传算法 III
非支配性排序遗传算法 III
落魄君子非支配性排序遗传算法 III—NSGA-III
Github 地址
非支配性排序遗传算法 III(NSGA-III)是用于求解多目标优化问题的一种进化算法,由 Kalyanmoy Deb 和 Harshit Jain 提出的。这种算法是在其前身 NSGA-II 的基础上进行改进和扩展,以更好地处理许多目标(多目标)优化问题。以下是 NSGA-III 的主要特点和工作机制的详细介绍:
主要特点
多目标优化:
- NSGA-III 专门设计用于处理三种或更多目标函数的优化问题,相比于传统的多目标算法,如 NSGA-II,NSGA-III 在处理高维目标空间时表现更佳。
参考点策略:
- NSGA-III 引入了参考点的概念,通过生成固定数量的参考点来引导种群的进化。参考点在目标空间中均匀分布,可以帮助保持解的多样性,并确保最终解在所有目标上的均匀性。
非支配排序:
- 像 NSGA-II 一样,NSGA-III 也采用了非支配排序的方式来评估个体的优劣。个体根据其支配关系被分为不同的等级(前沿)。
精英保留:
- NSGA-III 使用精英策略,通过合并父代和子代种群,确保优秀的个体能够在下一代中得到保留。
选择机制:
- 在选择过程中,NSGA-III 不仅考虑非支配等级,还引入了与参考点的距离,以此来选择更优个体。
工作机制
种群初始化:
- 随机生成初始种群,每个个体有一组决策变量,并计算其目标函数值。
生成参考点:
- 根据目标函数的数量,生成均匀分布的参考点,这些点在目标空间中均匀分布,帮助引导种群的进化。
非支配排序:
- 对种群进行非支配排序,确定每个个体的等级(F1、F2 等),并构建支配关系。
个体关联:
- 将每个个体与最近的参考点关联,计算个体与参考点之间的距离,以便选择更好的个体。
选择与繁殖:
- 根据非支配等级和与参考点的距离进行选择。采用交叉和变异操作生成新个体(子代)。
更新种群:
- 合并父代和子代,重新进行非支配排序,并使用与参考点的距离来选择最终种群。
迭代:
- 重复执行上述步骤,直到满足终止条件(如最大迭代次数或收敛条件)。
应用领域
NSGA-III 被广泛应用于以下领域:
- 工程设计优化
- 资源管理
- 路径规划
- 环境监测和管理
- 财务和投资策略优化
总结
NSGA-III 通过引入参考点和改进选择机制,在处理多目标优化问题时表现出色,能够有效找到分布均匀的Pareto前沿。其优越的性能使其成为现代多目标优化领域中的重要工具。
AssociateToReferencePoint.m
文件代码:
1 | function [pop, d, rho] = AssociateToReferencePoint(pop, params) |
注释说明:
Zr
是参考点矩阵,每一列代表一个参考点。rho
是每个参考点关联的个体数量,初始化为零。d
是个体到参考点的距离矩阵,每一行表示一个个体到所有参考点的距离。- 通过双重循环,程序遍历种群中的每个个体,并计算其到所有参考点的距离,找到距离最小的参考点作为该个体的关联参考点。
- 最终返回更新后的种群、距离矩阵和关联个体数量。
Crossover.m
文件代码:
1 | function [y1, y2] = Crossover(x1, x2) |
注释解释:
- alpha 是一个随机生成的与输入变量
x1
尺寸相同的系数矩阵,用于在两个父代个体之间随机插值。 - y1 和 y2 是两个子代个体,通过线性插值生成的,这种方式通常用于多目标优化算法中的模拟二进制交叉(SBX)操作。
这种交叉操作的优点是能够产生多样化的子代,有助于算法更好地探索解空间。
Dominates.m
文件代码:
1 | function b = Dominates(x, y) |
注释解释:
- 支配定义:在多目标优化中,解
x
被认为支配解y
,如果并且仅如果x
在所有目标上都不劣于y
,并且在至少一个目标上优于y
。这意味着x
要么和y
在所有目标上相等,要么至少有一个目标更好。 - 结构体处理:如果输入
x
或y
是结构体,则提取其Cost
字段,即目标值向量。目标值是算法中用来衡量解优劣的标准。 - 逻辑判断:
all(x <= y)
检查x
是否在所有目标上不劣于y
,any(x < y)
检查是否有至少一个目标上x
优于y
。
这种支配关系在进化算法中用于确定哪些个体能够进入下一代,并影响种群的非支配排序。
GenerateReferencePoints.m
文件代码:
1 | function Zr = GenerateReferencePoints(M, p) |
注释解释:
GenerateReferencePoints 函数:
- 该函数用于生成 NSGA-III 算法中的参考点,通过调用递归函数生成一个固定和的整数矩阵,并进行归一化处理,得到最终的参考点矩阵。
GetFixedRowSumIntegerMatrix 函数:
- 该函数递归生成一个整数矩阵,其中每行元素的和等于给定的
RowSum
。 - 这是通过递归的方式,从
M-1
维开始生成,再依次向高维扩展,确保每行的元素和固定。
- 该函数递归生成一个整数矩阵,其中每行元素的和等于给定的
应用场景:
- 在多目标优化问题中,生成参考点有助于划分解空间,使得解可以在目标空间上均匀分布,从而提高解的多样性。
main.m
文件代码:
1 | % main.m |
注释解释:
main.m
文件的作用是作为入口点,简单地调用nsga3
函数执行主算法。这个文件通常是为了方便用户启动整个算法。- 在实际运行中,用户只需要运行
main.m
文件,所有的初始化和迭代操作将会在nsga3.m
文件中完成。
MOP2.m
文件代码:
1 | function z = MOP2(x) |
注释解释:
函数 MOP2:
- 该函数实现了一个多目标优化问题 (MOP),定义了两个目标函数
z1
和z2
。这些目标函数通常用于测试多目标优化算法的性能。
- 该函数实现了一个多目标优化问题 (MOP),定义了两个目标函数
z1 和 z2 的计算:
- 目标函数
z1
和z2
都是指数函数与平方和的组合。 z1
通过计算x
和常数1/sqrt(n)
之间的差值平方和来确定,z2
则计算x
和-1/sqrt(n)
之间的平方和。两者的计算结构类似,但方向不同,形成了互补的优化目标。
- 目标函数
返回值:
- 返回的
z
是一个列向量,包含了两个目标函数值z1
和z2
,用于在 NSGA-III 算法中进行优化。
- 返回的
Mutate.m
文件代码:
1 | function y = Mutate(x, mu, sigma) |
注释解释:
Mutate 函数:
- 该函数实现了遗传算法中的突变操作,通过对个体(决策变量向量)进行随机扰动,探索新的解空间。这有助于防止算法陷入局部最优解。
参数解释:
mu
是突变率,表示有多少比例的基因会发生突变。根据这个比例,函数会计算需要突变的基因数量nMu
。sigma
是突变的标准差,控制突变强度。突变是通过在基因位置上加入正态分布的随机扰动实现的。
突变过程:
- 首先,函数随机选择若干基因位置(即决策变量中的一些元素),然后对这些位置的基因值进行随机改变。突变的幅度由
sigma
设定,并使用正态分布来生成突变量。
- 首先,函数随机选择若干基因位置(即决策变量中的一些元素),然后对这些位置的基因值进行随机改变。突变的幅度由
NonDominatedSorting.m
文件代码:
1 | function [pop, F] = NonDominatedSorting(pop) |
注释解释:
NonDominatedSorting 函数:
- 该函数实现了非支配排序,用于将种群中的个体分组到不同的等级(前沿),以便在多目标优化中选择最优解。
参数说明:
pop
是输入种群,包含多个个体。F
是输出变量,保存各个前沿的个体索引。
支配关系的建立:
- 每个个体的
DominationSet
用于存储其支配的个体,而DominatedCount
用于记录被支配的个体数量。 - 使用
Dominates
函数比较两个个体,确定它们之间的支配关系。
- 每个个体的
前沿的构建:
- 首先将无支配关系的个体(即被支配计数为0的个体)加入第一前沿。
- 然后通过循环更新每个前沿,直到没有更多的个体可以被加入新的前沿。
NormalizePopulation.m
文件代码:
1 | function [pop, params] = NormalizePopulation(pop, params) |
注释解释:
NormalizePopulation 函数:
- 该函数负责对种群进行归一化处理,使得个体的成本值在同一尺度上进行比较。
参数说明:
pop
是输入种群,包含多个个体。params
是包含优化参数和状态的结构体,包含理想点(zmin
)和其他参数。
理想点的更新:
UpdateIdealPoint
函数用于根据当前种群更新理想点zmin
。
成本的偏差计算:
- 计算每个个体的成本相对于理想点的偏差,生成矩阵
fp
。
- 计算每个个体的成本相对于理想点的偏差,生成矩阵
标量化方法的应用:
PerformScalarizing
函数用于更新标量化参数,确保多目标优化中的权衡。
超平面截距的计算:
FindHyperplaneIntercepts
函数用于计算每个目标的超平面截距,生成向量a
。
归一化处理:
- 将每个个体的成本进行归一化,存储在
NormalizedCost
字段中,以便后续比较和选择。
- 将每个个体的成本进行归一化,存储在
使用场景:
这个函数通常用于多目标优化中的种群更新阶段,确保所有个体的目标值在相同的尺度上进行比较,便于选择最优解。
nsga3.m
文件代码:
1 | % K. Deb and H. Jain, "An Evolutionary Many-Objective Optimization Algorithm |
注释解释:
代码开头注释:
- 提供了算法的参考文献,描述了 NSGA-III 的背景。
问题定义部分:
- 定义了优化问题,包括目标函数、决策变量的数量、变量的范围等。
NSGA-III 参数设置:
- 配置了 NSGA-III 算法所需的参数,包括生成的参考点、最大迭代次数、种群大小、交叉和变异的概率等。
收集参数:
- 将一些算法参数收集到
params
结构体中,便于后续使用。
- 将一些算法参数收集到
初始化部分:
- 初始化种群,包括生成随机个体和计算它们的成本。
NSGA-III 主循环:
- 进行算法的主要迭代过程,包括交叉、变异、合并种群、排序和选择等步骤。
结果输出:
- 显示最终的迭代结果和优化结束信息。
使用场景:
该代码实现了 NSGA-III 算法用于多目标优化问题,适用于希望同时优化多个目标并处理约束的复杂问题。通过迭代更新种群,寻找 Pareto 前沿解集,为决策者提供多样化的解决方案。
PerformScalarizing.m
文件代码:
1 | function params = PerformScalarizing(z, params) |
注释解释:
函数
PerformScalarizing
:- 该函数的主要功能是对多目标优化中的目标函数值进行标量化处理,以便于后续的优化过程。
z
是一个矩阵,表示种群中每个个体在每个目标上的值。params
是一个结构体,用于存储优化过程中的参数和状态。
参数初始化:
nObj
和nPop
分别表示目标函数的数量和种群的大小。zmax
用于存储当前已知的最优目标点,smin
用于记录每个目标的最小标量值。
标量化处理:
- 对于每个目标函数,使用
GetScalarizingVector
函数生成一个权重向量。 - 计算每个个体的标量值,标量值表示该个体在当前目标下的性能。
- 更新最优目标点和最小标量值。
- 对于每个目标函数,使用
辅助函数
GetScalarizingVector
:- 该函数生成一个标量化向量,指定第 j 个目标的权重为 1,其余目标的权重为非常小的值
epsilon
,以避免除零错误。
- 该函数生成一个标量化向量,指定第 j 个目标的权重为 1,其余目标的权重为非常小的值
使用场景:
该代码在多目标优化算法中用于处理目标函数值的标量化,使得不同目标函数的值能够在同一标准下进行比较。这种处理方式在如 NSGA-III 等算法中是必要的,因其可以有效引导搜索过程找到 Pareto 前沿解。
PlotCosts.m
文件代码:
1 | function PlotCosts(pop) |
注释解释:
函数
PlotCosts
:- 该函数用于绘制种群中个体的成本(目标函数值),通常在多目标优化问题中用来可视化目标函数值的分布情况。
参数
pop
:pop
是一个结构数组,包含了优化过程中所有个体的信息,包括其对应的目标函数值。
提取成本值:
Costs = [pop.Cost];
这一行代码将种群中每个个体的目标函数值提取出来,并组合成一个矩阵。矩阵的每一列代表一个个体的目标函数值。
绘图:
plot(Costs(1, :), Costs(2, :), 'r*', 'MarkerSize', 8);
这行代码绘制了一个散点图,x 轴为第一个目标的值,y 轴为第二个目标的值,使用红色星形标记,标记大小为 8。xlabel
和ylabel
用于设置 x 轴和 y 轴的标签,帮助理解图中的数据。grid on;
用于开启图形的网格,使得图形的可读性更高。
使用场景:
该函数通常在多目标优化算法的运行过程中被调用,以可视化当前种群中个体在不同目标上的表现,从而观察优化进程和结果的分布情况。这有助于分析算法的性能和解的多样性。
SortAndSelectPopulation.m
文件代码:
1 | function [pop, F, params] = SortAndSelectPopulation(pop, params) |
注释解释:
函数
SortAndSelectPopulation
:- 该函数负责对当前种群进行归一化处理、非支配排序和选择操作,以生成新的种群。
归一化种群:
- 调用
NormalizePopulation
函数对种群进行归一化,以便后续的处理。
- 调用
非支配排序:
- 使用
NonDominatedSorting
函数对种群进行排序,并返回排序后的种群和前沿集合F
。
- 使用
种群数量判断:
- 如果当前种群数量已达到预设数量,则直接返回。
关联参考点:
- 调用
AssociateToReferencePoint
函数获取个体与参考点的关联信息,包括距离和关联数量。
- 调用
生成新种群:
- 遍历每个前沿
F
,将其个体添加到新种群newpop
,直到达到预设的种群大小nPop
。
- 遍历每个前沿
处理最后一个前沿:
- 在循环中,选择与当前最小
rho
值关联的个体添加到新种群中。如果该值为 0,选择距离最近的个体;否则随机选择。
- 在循环中,选择与当前最小
更新种群:
- 每次添加个体后更新
rho
值,直到新种群达到指定大小。
- 每次添加个体后更新
最终非支配排序:
- 对新种群进行非支配排序,返回最终的种群和前沿集合。
使用场景:
该函数在多目标进化算法中起到关键作用,通过对种群的排序和选择,确保在每一代中保留优秀的解,促进多样性和收敛性,以便于找到更优的多目标解。
UpdateIdealPoint.m
文件代码:
1 | function zmin = UpdateIdealPoint(pop, prev_zmin) |
注释解释:
函数
UpdateIdealPoint
:- 该函数用于更新多目标优化中的理想点(最优解点),通常在每一代进化过程中更新。
输入参数:
pop
: 当前的种群,包含多个个体,每个个体都有对应的成本(目标函数值)。prev_zmin
: 上一代的理想点。如果没有提供,函数会将其初始化为无穷大。
理想点初始化:
- 如果
prev_zmin
没有被提供或为空,函数会将其初始化为与个体成本数组相同大小的无穷大数组。
- 如果
更新理想点:
- 函数遍历种群中的每个个体,通过与当前理想点进行比较,更新理想点为当前个体成本与理想点之间的最小值。
使用场景:
在多目标进化算法(如 NSGA-II 和 NSGA-III)中,理想点用于跟踪当前已知的最优目标函数值,有助于引导进化过程,确保解的多样性和收敛性。每当新一代的个体生成时,都会调用此函数更新理想点,以反映当前最优解。