这个函数是用来执行非支配排序的,可以分层构建Pareto,并返回每一层的解以及每个解支配其他解的索引、解被其他解支配的次数、解所在的非支配层级。这个函数对这些解进行非支配排序,并返回四个数组:ndf, dl, dc, 和 ndr。
-
ndf (Non-Dominated Fronts): 这是一个整数列表,表示非支配层级。每个非支配层包含一组互不支配的解。例如,第一个非支配层(ndf[0])包含所有不被任何其他解支配的解,第二个非支配层(ndf[1])包含所有只被第一层中的解支配的解,依此类推。
-
dl (Domination List): 这是一个列表,其中每个元素是一个整数列表,表示解支配的其他解的索引。
-
dc (Domination Counts): 这是一个整数数组,每个元素表示解被其他解支配的次数。
-
ndr (Non-Dominated Ranks): 这是一个整数数组,每个元素表示解所在的非支配层级。
示例:返回值:
import pygmo as pg
import numpy as np# 假设我们有一组解,每个解包含多个目标函数的值
# 这里我们创建一个假设的解集,每行代表一个解,列代表目标函数的值
solutions = np.array([[2.0, 4.0],[3.0, 3.5],[1.5, 5.0],[2.5, 2.0],[3.0, 2.5]
])# 使用 fast_non_dominated_sorting 对这些解进行非支配排序
ndf, dl, dc, ndr = pg.fast_non_dominated_sorting(points=solutions)
算出每个解被其他解支配的次数是多少:
id_dict = {}
for i in range(len(dc)):id_dict[i] = dc[i]print(id_dict)
{0: 0,
1: 2,
2: 0,
3: 0,
4: 1}
利用支配关系,将解分为两类
def dominance_learn_clusters(self):"""基于每个解的支配关系,将这些解划分为两类,分别用0,1表示step:计算每个解被其他解支配的数量 --> 对这些解的索引进行排序 --> 除以2,以划分为两类"""### this version is for HVfrom copy import deepcopyassert len(self.samples) >= 2, "samples must > 0"x = self.samples[0]fX = self.samples[1]# botorch_hv = Hypervolume(ref_point=self.func.ref_point)obj_list = deepcopy(fX.cpu().numpy())obj_list *= -1ndf, dl, dc, ndr = pg.fast_non_dominated_sorting(points=obj_list)id_dict = {}for i in range(len(dc)):id_dict[i] = dc[i]sorted_domi = np.array(sorted(id_dict.items(), key=lambda kv: (kv[1])))[:, 0]plabel = [1] * len(sorted_domi)for i in range(len(sorted_domi)):if i <= (len(sorted_domi) // 2):plabel[int(sorted_domi[i])] = 0plabel = np.array(plabel)return plabel
学习一个SVM分类器:
self.svm = SVC(kernel=args.kernel, gamma=args.gamma, degree=args.degree)
def learn_boundary(self, plabel):"""通过SVM学习到一个边界(预测器)"""assert len(plabel) == len(self.samples[0])#fitting a boundary in search space#plabel is from objective space#plabel_ss is from the search spaceplabel = plabel.ravel()X = self.samples[0]if torch.cuda.is_available():X = X.cpu().data.numpy()else:X = X.data.numpy()self.svm.fit(X, plabel)