geatpy icon indicating copy to clipboard operation
geatpy copied to clipboard

【已解决】python利用geatpy库实现【并行】【多目标】【多约束】优化,获得帕累托边界

Open SYH0323 opened this issue 1 year ago • 3 comments

【已解决】原文往下翻 geatpy官方文档演示并行优化时,是单目标,并且没有约束的,所以有些地方我理解错了。 官方文档 后来重新理解了一遍,发现并行的原理其实就是,先把种群(比如NIND=200,就是200个决策变量)全部输进subAimFunc里计算一遍,算出所有种群对应的目标函数值和约束值(我们只能手动调节让这部分实现并行),然后在evalVars函数里,以numpy数组的形式返回所有目标函数值和约束值。 所以我把subAimFunc的代码改成了这样:

def subAimFunc(x):
    a, b, c = operation(x)
    ObjV_CV = np.hstack([a, b, c - 0.1])
    return ObjV_CV  # 目标函数值和约束值作为一个numpy数组一起返回

即:把目标函数和约束的值都放进一个numpy数组里,等后面在evalVars再把两部分拆开。 evalVars部分的代码如下:

def evalVars(Vars):  # 定义目标函数(含约束)
        result = []
        with concurrent.futures.ProcessPoolExecutor(max_workers=20) as executor:
            results = [executor.submit(subAimFunc, var) for var in Vars]
            for f in concurrent.futures.as_completed(results):
                result.append(f.result())
        ObjV = np.array(result)[:, :Objnum]  # 前Objnum列是目标函数
        CV = np.array(result)[:, Objnum:]  # 其余的是约束
        return ObjV, CV

注意: 1.我是用concurrent.futures模块实现并行的,因为这个模块并行更直观。具体可以看这个B站视频(英文的,但是我感觉把python并行原理讲的不能再清楚了,比中文视频好太多了) 2.Objnum需要自行设定,我这里因为目标函数有两个,所以就是Objnum=2,这样并行计算出来的结果有200行3列,前2列是目标函数值ObjV ,后面的都是约束值CV。 3.注意CV里面的[:, Objnum:]这部分,这里没用[:,-1]直接取最后一个,是因为**[:,-1]生成的数组是一维的,也会报错**(因为不满足2维数组的要求)。所以干脆用[:, Objnum:],这种写法会额外增加一个维度(就我这个例子而言,维度变成了200*1,就避开了检查维度时,发现不是2维数组而报错的问题)

【原文如下】 我是做整数规划的,目标函数如下,优化目标有两个,约束有一个。

def subAimFunc(x):
    a, b, c = operation(x)
    ObjV = np.hstack([a, b])
    CV = np.hstack([c - 0.1])
    return ObjV, CV

决策变量是一个四维数组,每执行一次目标函数需要0.25秒左右,虽然执行比较快,但是因为搜索空间很大(1000×1000×10000×120),所以打算采用并行模式提高效率。 但是报了下面的错,查了一些资料,说是数组错位了,但我是真的看不懂,求大家懂行的回答一下吧。

Traceback (most recent call last):
  File "D:/SYH/PV_CFPP/多目标优化测试/MyProblem-并行.py", line 106, in <module>
    res = ea.optimize(algorithm, verbose=True, drawing=1, outputMsg=True, drawLog=False, saveFlag=True)
  File "D:\anoconda\lib\site-packages\geatpy\optimize.py", line 104, in optimize
    [optPop, lastPop] = algorithm.run(prophetPop)
  File "D:\anoconda\lib\site-packages\geatpy\algorithms\moeas\nsga2\moea_NSGA2_templet.py", line 87, in run
    [levels, _] = self.ndSort(population.ObjV, NIND, None, population.CV, self.problem.maxormins)  # 对NIND个个体进行非支配分层
File "core\c\ndsortESS.pyx", line 170, in ndsortESS.ndsortESS
ValueError: setting an array element with a sequence.

SYH0323 avatar Mar 04 '23 17:03 SYH0323