因为multi-objective optimization已经被做烂了,现在学者们都在做many-objective optimization,也就是5个以上的目标函数(悄悄说一句,我觉得这个也要被做烂了)。此次我是用python复现的,这篇文章也主要以python代码讲解为主。
代码链接matlab和Python(需要软妹币):
多目标优化算法(四)NSGA3的代码(MATLAB)_套用nsga3程序代码matlab,nsga3matlab-机器学习代码类资源-CSDN下载download.csdn.net摘要:NSGAIII的主要思路是在NSGAII的基础上,引入参考点机制,对于那些非支配并且接近参考点的种群个体进行保留。此次复现处理的优化问题是具有3到15个目标的DTLZ系列,仿真结果反应了NSGAIII良好的搜索帕累托最优解集的能力。
总体上来说,NSGAIII和NSGAII具有类似的框架,二者区别主要在于选择机制的改变,NSGAII主要靠拥挤度进行排序,其在高维目标空间显然作用不太明显,而NSGAIII对拥挤度排序进行了大刀阔斧的改编,通过引入广泛分布参考点来维持种群的多样性。
以下总结NSGAIII的第t代的步骤:
第一步将子代和父代结合:
主程序python代码如下:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # 空间三维画图
from utils import uniformpoint,funfun,cal,GO,envselect,IGD
import copy
import random
#参数设置
N_GENERATIONS = 400 # 迭代次数
POP_SIZE = 100 # 种群大小
name = 'DTLZ1' # 测试函数选择,目前可供选择DTLZ1,DTLZ2,DTLZ3
M = 3 # 目标个数
t1 = 20 # 交叉参数t1
t2 = 20 # 变异参数t2
pc = 1 # 交叉概率
pm = 1 # 变异概率
#画图部分
if(M<=3):
fig = plt.figure()
ax = Axes3D(fig)
###################################################################################################################################################################
#产生一致性的参考点和随机初始化种群
Z,N = uniformpoint(POP_SIZE,M)#生成一致性的参考解
pop,popfun,PF,D = funfun(M,N,name)#生成初始种群及其适应度值,真实的PF,自变量个数
popfun = cal(pop,name,M,D)#计算适应度函数值
Zmin = np.array(np.min(popfun,0)).reshape(1,M)#求理想点
#ax.scatter(Z[:,0],Z[:,1],Z[:,2],c='r')
#ax.scatter(PF[:,0],PF[:,1],PF[:,2],c='b')
#迭代过程
for i in range(N_GENERATIONS):
print("第{name}次迭代".format(name=i))
matingpool=random.sample(range(N),N)
off = GO(pop[matingpool,:],t1,t2,pc,pm)#遗传算子,模拟二进制交叉和多项式变异
offfun = cal(off,name,M,D)#计算适应度函数
mixpop = copy.deepcopy(np.vstack((pop, off)))
Zmin = np.array(np.min(np.vstack((Zmin,offfun)),0)).reshape(1,M)#更新理想点
pop = envselect(mixpop,N,Z,Zmin,name,M,D)
popfun = cal(pop,name,M,D)
if(M<=3):
ax.cla()
type1 = ax.scatter(popfun[:,0],popfun[:,1],popfun[:,2],c='g')
plt.pause(0.00001)
# 绘制PF
if(M<=3):
type2 = ax.scatter(PF[:,0],PF[:,1],PF[:,2],c='r',marker = 'x',s=200)
plt.legend((type1, type2), (u'Non-dominated solution', u'PF'))
else:
fig1 = plt.figure()
plt.xlim([0,M])
for i in range(pop.shape[0]):
plt.plot(np.array(pop[i,:]))
plt.show()
#IGD
score = IGD(popfun,PF)
程序中pc是交叉概率,pm是变异概率。
1.将种群按照非支配层进行划分
将非支配层等级1到
非支配排序的python代码如下:
from scipy.special import comb
from itertools import combinations
import numpy as np
import copy
import math
def NDsort(mixpop,N,M):
nsort = N#排序个数
N,M = mixpop.shape[0],mixpop.shape[1]
Loc1=np.lexsort(mixpop[:,::-1].T)#loc1为新矩阵元素在旧矩阵中的位置,从第一列依次进行排序
mixpop2=mixpop[Loc1]
Loc2=Loc1.argsort()#loc2为旧矩阵元素在新矩阵中的位置
frontno=np.ones(N)*(np.inf)#初始化所有等级为np.inf
#frontno[0]=1#第一个元素一定是非支配的
maxfno=0#最高等级初始化为0
while (np.sum(frontno < np.inf) < min(nsort,N)):#被赋予等级的个体数目不超过要排序的个体数目
maxfno=maxfno+1
for i in range(N):
if (frontno[i] == np.inf):
dominated = 0
for j in range(i):
if (frontno[j] == maxfno):
m=0
flag=0
while (m<M and mixpop2[i,m]>=mixpop2[j,m]):
if(mixpop2[i,m]==mixpop2[j,m]):#相同的个体不构成支配关系
flag=flag+1
m=m+1
if (m>=M and flag < M):
dominated = 1
break
if dominated == 0:
frontno[i] = maxfno
frontno=frontno[Loc2]
return frontno,maxfno
frontno=np.ones(N)*(np.inf) #初始化所有等级为np.inf。
maxfno=0 #最高等级初始化为0。
N就是要排序的个数。
2.超平面上参考点的确定
NSGAIII使用一组预定义的参考点以确保解的多样性,这一组参考点可以结构化的方式定义,也可以用户根据自己的参考点。以下介绍一种产生结构化参考点的方法叫Das and Dennis’s method,此方法来源于田野老师对产生参考点方法的综述论文。其参考点在一个(M-1)维的超平面上,M是目标空间的维度,即优化目标的个数。如果我们将每个目标划分为
例如对于一个H=4的3目标问题,其参考点构成了一个三角形,根据公式可知其产生15个参考点,见图1所示。