多目标进化算法——(python实现)

由于NSGA-II是基于遗传算法的,所以在讲解NSGA-II之前,我们先对遗传算法有一些基本的了解——遗传算法经常用于单目标优化问题,所进行操作的基本流程如下

NSGA-II所做的其实就是把排序的依据改变——就是“如何评判一个解的优劣”,在传统遗传算法中,使用的是适应度函数值,这也是因为传统遗传算法多用在单目标的优化问题中,使用能够使用这一个指标来判断。 下面是遗传算法中一些名词的对应关系:

但对于一个多目标优化问题来说,它的最优解不再是一个值,而是在多维空间中的一个pareto前沿:一个最优解的集合。因此对于迭代过程中未到达pareto前沿的解来说,评判其优劣应当从两个方面来入手——收敛性——解靠近pareto前沿的程度(或速度)分布性——当前解集是否尽可能地覆盖到了pareto前沿。 所以NSGA-II的作者Deb提出了评价当前解集合优劣的两个指标:

下面为了方便讲解,我们以双目标的最小化优化问题举例说明,因为这样能够在几何意义上,放在二维平面图中帮助我们去理解。 m i n F ( x ) = { f 1 ( x ) , f 2 ( x ) } T s t . x ∈ X X ⊂ R 2 min \quad F(x)=\{f_1(x),f_2(x)\}^T\\ st. \quad x\in X \\ \quad \quad X \subset\mathbb R^2 minF(x)={f1​(x),f2​(x)}Tst.x∈XX⊂R2

首先,需要了解两个解的支配关系。我们举例来说明,如果两个目标都是最小化目标的话,说明目标函数值越小,越好。则假设 给定个体 x 0 x_0 x0​, 目标函数值 F ( x 0 ) = ( f 1 ( x 0 ) , f 2 ( x 0 ) ) = ( 1 , 1 ) F(x_0) =(f_1(x_0),f_2(x_0))=(1,1) F(x0​)=(f1​(x0​),f2​(x0​))=(1,1) 再给定另外的个体 x 1 x_1 x1​, 目标函数值 F ( x 1 ) = ( f 1 ( x 1 ) , f 2 ( x 1 ) ) = ( 2 , 2 ) F(x_1) =(f_1(x_1),f_2(x_1))=(2,2) F(x1​)=(f1​(x1​),f2​(x1​))=(2,2)   我们可以发现, 在两个目标函数方向(objective), x 0 x_0 x0​ 所求的目标函数值 ( 1 , 1 ) (1,1) (1,1) 都比 x 1 x_1 x1​ 的目标函数值 ( 2 , 2 ) (2,2) (2,2) 小,而同时两个优化方向都是最小化。所以 x 0 x_0 x0​ 所得解的效果要要好于 x 1 x_1 x1​ ,即 x 0 x_0 x0​ 支配 x 1 x_1 x1​。   同样的,当一个方向上相等,支配关系又另一个方向目标函数值的大小来决定,例如: ( 1 , 2 ) (1,2) (1,2) 支配 ( 2 , 2 ) (2,2) (2,2)。   如果在二维平面图上用几何意义来理解的话,就是由原点开始向外做同心圆,内侧圆上的点支配外侧圆上的点。(当然仅限于两个目标,且优化方向都是最小化)

但是我们会遇到另外一种情况,例如 ( 1 , 2 ) (1,2) (1,2) 和 ( 2 , 1 ) (2,1) (2,1) ,显然在一个方向上2 > 1,但在另一个方向上1 < 2,对应在几何意义上,就是这两个点在同一个圆上。像这种彼此没有明确的支配关系,即双方无法支配对方的时候,两者的关系就是非支配关系。    综上对于两个个体而言,他们的大小关系便可以对应为两者的支配关系。所以在类定义中,我重载了小于号的方法,方便在代码中比较两个个体的支配关系。

由上,显然支配关系能够作为一个指标来衡量这个解的优劣程度,因此我们利用个体间的支配关系,将现有种群进行分层。最靠近pareto前沿的解它的等级(rank)最高,为第一层。然后依次判断每个个体处在第几层中,给每个个体的rank赋值。几何上来看,类似于画同心圆,看看这个解在第几个同心圆中。然后依据每个个体的rank值来进排序选择。

这里面需要了解其中几个变量的含义—— n p n_p np​:解 p p p 被几个解所支配,是一个数值(左下部分点的个数) S p S_p Sp​:解 p p p 支配哪些解,是一个解集合(右上部分点的内容) F i F_i Fi​:第 i i i 层的解集合(显然同一层内的解互相都是非支配解) p r a n k p_{rank} prank​:解 p p p 所在层的等级(越小越好) 伪代码主要进行了两步:

上面描述的非支配排序方法从解的收敛性,或者说靠近pareto的前沿的程度来衡量解的优劣。以此,我们假设现在待选择种群个体有120个,我们的种群规模为100,即要选择前100个作为父代进入下一次迭代。   通过非支配排序,若得到 F 1 F_1 F1​ 有30个, F 2 F_2 F2​ 有60个, F 3 F_3 F3​ 有10个, F 4 F_4 F4​ 有20个。很显然,我们只选择 F 1 F_1 F1​ , F 2 F_2 F2​ , F 3 F_3 F3​ 中的个体就可以了。但上述情况是刚刚好的,我们需要考虑比较一般的情况—— 如果划分的线切在了 F i F_i Fi​ 层中,即如果 F 3 F_3 F3​ 有30个,要从中选择10个,剔除20个,这种情况该如何选择呢?即对于处在同一层中,rank属性值相同的个体,我们应当依据什么来对他们进行排序呢?

由此,作者为了保证种群的多样性,即保留解的分布的稀疏程度,放在图上来看的话就是尽可能得让解分散。在这一原则之下,位于两端的解是必留的,而处于中间的点,则通过定义拥挤度距离来进行判断。形象一些来理解的话,就是“你身边距离比较近的同类太多了,只留下你一个能够代表这一段就行了”。

由此介绍完“非支配排序”和“拥挤度距离分配”之后,对于一个已有种群的排序选择的基本流程便可以确定下来——

以上流程便是 “二元锦标赛”选择的基本策略。(二元锦标赛:随机选择两个个体,依据某种指标策略进行比较,较优的个体胜出,作为进行交叉的父本中的一个) 其对应代码如下

首先,在传统的遗传算法中,在某一次迭代中,只有该次迭代的父代参与选择交叉变异,从而产生子代,作为下一次迭代的父代。   而在NSGA-II中,为了保证最优解的不丢失,提高算法的收敛速度,作者提出了“精英选择策略”,即将父代 P t P_t Pt​ 和子代 Q t Q_t Qt​ 种群,合并为一个种群 R t R_t Rt​ ,对其整体进行非支配排序和拥挤度距离计算,根据上述方法进行排序和选择作为下一届的父代 P t + 1 P_{t+1} Pt+1​ 。父代再通过一般的方法进行选择交叉排序产生子代 Q t + 1 Q_{t+1} Qt+1​ 。   这里同样也是循环的主流程所在!

随机从种群中选择两个个体,让其进行过渡2所说的“二元锦标赛”,获胜的作为父本1;同样操作,再得到一个父本2。之后,为了避免遗传算法中的早熟现象,多增加一步判断,使得父本1和父本2不相同。

对于得到的两个子代,其中一个进行变异操作,另一个不变(千万不要两个都变,会引起一种早熟现象——所有的个体都过早的陷于某几个极值而停止变化,具体原因未明,待解决),这里选择的变异算子是“多项式变异”(PM) x j = x j + Δ j     Δ j = { ( 2 μ i ) 1 η + 1 μ i < 0.5 1 − [ 2 ( 1 − μ i ) ] 1 η + 1 μ i ≥ 0.5 x_j=x_j+ \Delta_j \\ ~\\ ~\\ \Delta_j = \begin{cases} (2\mu_i)^{\frac{1}{\eta + 1}} & \mu_i<0.5 \\ 1-[2(1-\mu_i)]^{\frac{1}{\eta + 1}} & \mu_i\ge0.5 \end{cases} xj​=xj​+Δj​  Δj​={(2μi​)η+11​1−[2(1−μi​)]η+11​​μi​<0.5μi​≥0.5​ μ i \mu_i μi​ 是满足(0,1)均匀分布的随机数, η \eta η 是变异分布参数。

THE END
0.竞赛问题题目描述对一维数组按照从小到大的顺序排序。程序定义函数sort()来实现数组a的排序。函数原型如下: void sort(int a[], int n); 数组元素的输出调用PrintArr()。输入第一行输入一个整数n(1<=n<=10),表示数组有n个整数;第二行输入n个整数。输出输出占一行。对这n个整数数按照从小到大的顺序输出,数据之间jvzq<84ql0€{p~3gfw4dp8hqpvktvhutqdrfo7ujrAijfF6567,qkmB3
1.C语言所有经典排序方法的实现代码C语言这篇文章给大家分享C语言所有经典排序方法,文章给大家提供完整的实例代码帮助大家快速学习掌握C语言排序方法,感兴趣的朋友一起看看吧GPT4.0+Midjourney绘画+国内大模型 会员永久免费使用!【 如果你想靠AI翻身,你先需要一个靠谱的工具!】 运行结果正确 还是快速排序难一些。 完整代码 1 2 3 4 5 6 7 8 9 10 jvzquC41yy}/lk:30pku1jwvkerf1;65;48/j}r
2.1366.通过投票对团队排名请你返回能表示按排名系统排序后的所有团队排名的字符串。 示例1: 输入:votes = ["ABC","ACB","ABC","ACB","ACB"]输出:"ACB"解释:A 队获得五票「排位第一」,没有其他队获得「排位第一」,所以 A 队排名第一。 B 队获得两票「排位第二」,三票「排位第三」。 C 队获得三票「排位第二」,两票「jvzquC41ngkuexig0eun1ywqdnknu8wcpm3ugjru/d.xxygu1