这个函数是用来执行非支配排序的,可以分层构建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 HV
from copy import deepcopy
assert 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 *= -1
ndf, 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])] = 0
plabel = 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 space
plabel = 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)