如何在 OpenMDAO 中使用整数参数进行优化
How to optimize with integer parameters in OpenMDAO
我目前正在尝试使用 OpenMDAO 1.7.2 对地图上的位置进行一些优化。进行计算的(预先存在的)模块仅支持整数坐标(一米的分辨率)。
现在我正在使用 IndepVarComp
对每个方向进行优化,每个方向都包含一个 float
向量。然后在使用这些值之前对其进行四舍五入,但这是非常低效的,因为求解器主要尝试小于一的变化。
当我尝试用整数向量初始化 IndepVarComp
时,第一次迭代工作正常(使用初始值),但在第二次迭代中失败,因为 IndepVarComp
中的数据设置为空 ndarray
.
翻阅OpenMDAO源码发现这是因为
indep_var_comp._init_unknowns_dict['x']['size'] == 0
只要数据类型不可区分,就会在 Component
的 _add_variable()
方法中发生。
这是一个示例问题,它说明了定义整数 IndepVarComp
是如何失败的:
from openmdao.api import Component, Group, IndepVarComp, Problem, ScipyOptimizer
INITIAL_X = 1
class ResultCalculator(Component):
def __init__(self):
super(ResultCalculator, self).__init__()
self.add_param('x', INITIAL_X)
self.add_output('y', 0.)
def solve_nonlinear(self, params, unknowns, resids):
unknowns['y'] = (params['x'] - 3) ** 2 - 4
problem = Problem()
problem.root = Group()
problem.root.add('indep_var_comp', IndepVarComp('x', INITIAL_X))
problem.root.add('calculator', ResultCalculator())
problem.root.connect('indep_var_comp.x', 'calculator.x')
problem.driver = ScipyOptimizer()
problem.driver.options['optimizer'] = 'COBYLA'
problem.driver.add_desvar('indep_var_comp.x')
problem.driver.add_objective('calculator.y')
problem.setup()
problem.run()
失败
ValueError: setting an array element with a sequence.
请注意,如果我设置 INITIAL_X = 0.
,一切正常。
我应该如何针对整数进行优化?
如果你想使用整数变量,你需要选择不同类型的优化器。您无法强制 COBYLA 尊重完整性。此外,如果您确实有某种整数舍入导致分析不连续,那么您真的根本不能使用 COBYLA(或任何其他连续优化器)。他们都对您将违反的功能的平滑性做出了基本假设。
听起来您应该考虑使用粒子群算法或遗传算法来解决您的问题。或者,您可以专注于使分析平滑且可微分,并缩放您的一些输入以获得更合理的分辨率。您还可以放宽优化器的收敛容差,使其在设计变量低于物理意义时停止迭代。
我目前正在尝试使用 OpenMDAO 1.7.2 对地图上的位置进行一些优化。进行计算的(预先存在的)模块仅支持整数坐标(一米的分辨率)。
现在我正在使用 IndepVarComp
对每个方向进行优化,每个方向都包含一个 float
向量。然后在使用这些值之前对其进行四舍五入,但这是非常低效的,因为求解器主要尝试小于一的变化。
当我尝试用整数向量初始化 IndepVarComp
时,第一次迭代工作正常(使用初始值),但在第二次迭代中失败,因为 IndepVarComp
中的数据设置为空 ndarray
.
翻阅OpenMDAO源码发现这是因为
indep_var_comp._init_unknowns_dict['x']['size'] == 0
只要数据类型不可区分,就会在 Component
的 _add_variable()
方法中发生。
这是一个示例问题,它说明了定义整数 IndepVarComp
是如何失败的:
from openmdao.api import Component, Group, IndepVarComp, Problem, ScipyOptimizer
INITIAL_X = 1
class ResultCalculator(Component):
def __init__(self):
super(ResultCalculator, self).__init__()
self.add_param('x', INITIAL_X)
self.add_output('y', 0.)
def solve_nonlinear(self, params, unknowns, resids):
unknowns['y'] = (params['x'] - 3) ** 2 - 4
problem = Problem()
problem.root = Group()
problem.root.add('indep_var_comp', IndepVarComp('x', INITIAL_X))
problem.root.add('calculator', ResultCalculator())
problem.root.connect('indep_var_comp.x', 'calculator.x')
problem.driver = ScipyOptimizer()
problem.driver.options['optimizer'] = 'COBYLA'
problem.driver.add_desvar('indep_var_comp.x')
problem.driver.add_objective('calculator.y')
problem.setup()
problem.run()
失败
ValueError: setting an array element with a sequence.
请注意,如果我设置 INITIAL_X = 0.
,一切正常。
我应该如何针对整数进行优化?
如果你想使用整数变量,你需要选择不同类型的优化器。您无法强制 COBYLA 尊重完整性。此外,如果您确实有某种整数舍入导致分析不连续,那么您真的根本不能使用 COBYLA(或任何其他连续优化器)。他们都对您将违反的功能的平滑性做出了基本假设。
听起来您应该考虑使用粒子群算法或遗传算法来解决您的问题。或者,您可以专注于使分析平滑且可微分,并缩放您的一些输入以获得更合理的分辨率。您还可以放宽优化器的收敛容差,使其在设计变量低于物理意义时停止迭代。