使用 pymoo 进行整数随机采样

问题描述 投票:0回答:2

我想使用 pymoo 进行多目标优化并解决离散问题。为此,在 pymoo 的网页上可以看到 IntegerRandomSampling() 类: https://pymoo.org/customization/discrete.html

作为一个例子,我考虑一个测试应用程序来查找 2D 表面地图上 N 个个体的位置,其坐标由索引(整数)描述,并且我希望 pymoo 生成 N 个随机整数来表示每个“迭代”的位置。

我注意到两件事,我很乐意收到社区的意见:

  1. 它看起来并不那么随机,因为每次我重新运行测试时,N 大小的随机整数数组总是遵循相同的序列;
  2. 更多的问题是在某些时候(实际上总是相同的)N 大小的随机整数数组变成浮点数而不是整数,正如人们对 IntegerRandomSampling() 类的返回值所期望的那样。

有谁知道这是一个已识别的错误还是我没有正确做事?下面是一个小脚本,再现了我试图解释的内容。第 43 行左右的 print(x) 指令将显示 N 大小的随机整数数组,始终相同并变成浮点数。

非常感谢。

编辑:

  • 我明白为什么随机整数的序列总是相同的,因为它是由相同的“种子”初始化的,但为什么它会变成浮点数仍然是个谜......
import numpy as np
from pymoo.core.problem import ElementwiseProblem
from pymoo.algorithms.moo.nsga2 import NSGA2
from pymoo.operators.crossover.sbx import SBX
from pymoo.operators.mutation.pm import PM
from pymoo.operators.sampling.rnd import FloatRandomSampling
from pymoo.operators.sampling.rnd import IntegerRandomSampling

class stru:
def __init__(self):
        self.a = 0
class MaskProblem(ElementwiseProblem):
    def __init__(self, data):
        self.xg = data.xg
        self.yg = data.yg
        self.A  = data.A
        self.N = data.N
        # design space
        dsxl = np.zeros((self.N),dtype=int)
        dsxu = np.zeros((self.N), dtype=int)
        for j in range(self.N):
            dsxu[j] = int(len(self.xg)*len(self.yg)-1)
        super().__init__(n_var=self.N,
                         n_obj=self.N-1,
                         n_constr=0,
                         xl=dsxl,
                         xu=dsxu)
    def _evaluate(self, x, out, *args, **kwargs):
        #
        print(x)
        p = np.zeros((self.N,2),dtype=float)
        for k in range(self.N):
            j, i = np.unravel_index(np.abs(self.A - x[k]).argmin(), self.A.shape)
            p[k,0] = self.xg[i]
            p[k,1] = self.yg[j]
        #
        kmid = int(0.5*(self.N-1))
        fobj = np.zeros((self.N-1),dtype=float)
        for k in range(kmid):
            fobj[k] = np.sqrt(np.square(p[k,0]-p[kmid,0])+np.square(p[k,1]-p[kmid,1]))
        for k in range(kmid,self.N):
            fobj[k-kmid] = np.sqrt(np.square(p[k, 0] - p[kmid, 0]) + np.square(p[k, 1] - p[kmid, 1]))
        #print(f'x={x[0][0]}, i={i},j={j}, A(i,j)={data.A[j, i]}')
        #
        # objectives array
        out["F"] = fobj

data = stru()

xmin = 0.0
xmax = 1.0
NX = 3
data.xg = np.linspace(xmin, xmax, NX)

ymin = 0.0
ymax = 1.0
NY = 5
data.yg = np.linspace(ymin, ymax, NY)

data.A = np.zeros((NY,NX),dtype=int)
for jx in range(NX):
    for jy in range(NY):
        data.A[jy,jx] = jy*NX + jx
print(data.A)

data.N = 3

n_population = 40
n_offsprings = 10
n_gen        = 100
crossover_prob = 0.9
crossover_eta  = 15
mutation       = 20

problem = MaskProblem(data)

algorithm = NSGA2(
    pop_size=n_population,
    n_offsprings=n_offsprings,
    sampling=IntegerRandomSampling(),
    crossover=SBX(prob=crossover_prob, eta=crossover_eta),
    mutation=PM(eta=mutation),
    eliminate_duplicates=True
)

from pymoo.optimize import minimize
res = minimize(problem,algorithm,termination=('n_gen', n_gen),seed=1,save_history=True,verbose=False)
pymoo
2个回答
0
投票

我认为问题来自于交叉或突变。我尝试了 SBX、TwoPointCrossover 和 UniformCrossover,但总是一样。但只有在第一代之后整数才变成浮点数。 对于我自己的问题,我将设计特定的交叉和变异类,但在 Pymoo 中实现可能很有趣,值得考虑。


0
投票

为了将数据类型保持为整数,您可以通过

vtype
参数显式指定类型。

super().__init__(n_var=self.N,
                         n_obj=self.N-1,
                         n_constr=0,
                         xl=dsxl,
                         xu=dsxu,
                         vtype=int)
© www.soinside.com 2019 - 2024. All rights reserved.