【发布时间】:2022-01-21 21:32:48
【问题描述】:
使用 openMDAO,我正在使用 FD 导数并尝试使用 SLSQP 方法解决非线性约束优化问题。每当优化器到达违反其中一个约束的点时,它就会崩溃并显示以下消息:
优化失败。线搜索的正向导数
例如,如果我故意将初始点设置为不可行的设计点,优化器执行 1 次迭代并退出并出现上述错误(当我从可行点开始时也会发生同样的情况,但随后优化器到达不可行点经过几次迭代)。
根据In OpenMDAO, is there a way to ensure that the constraints are respected before proceeding with a computation? 中问题的答案,我假设在我的情况下引发AnalysisError 异常将不起作用,对吗?有没有其他方法可以防止优化器进入不可行的区域或至少回溯在线搜索并尝试不同的方向/距离?还是应该只在解析导数可用时才使用 SLSQP 方法?
可重现的测试用例:
import numpy as np
import openmdao.api as om
class d1(om.ExplicitComponent):
def setup(self):
# Global design variables
self.add_input('r', val= [3,3,3])
self.add_input('T', val= 20)
# Coupling output
self.add_output('M', val=0)
self.add_output('cost', val=0)
def setup_partials(self):
# Finite difference all partials.
self.declare_partials('*', '*', method='fd')
def compute(self, inputs, outputs):
# define inputs
r = inputs['r']
T = inputs['T'][0]
cost = 174.42 * T * (r[0]**2 + 2*r[1]**2 + r[2]**2 + r[0]*r[1] + r[1]*r[2])
M = 456.19 * T * (r[0]**2 + 2*r[1]**2 + r[2]**2 + r[0]*r[1] + r[1]*r[2]) - 599718
outputs['M'] = M
outputs['cost'] = cost
class MDA(om.Group):
class ObjCmp(om.ExplicitComponent):
def setup(self):
# Global Design Variable
self.add_input('cost', val=0)
# Output
self.add_output('obj', val=0.0)
def setup_partials(self):
# Finite difference all partials.
self.declare_partials('*', '*', method='fd')
def compute(self, inputs, outputs):
outputs['obj'] = inputs['cost']
class ConCmp(om.ExplicitComponent):
def setup(self):
# Global Design Variable
self.add_input('M', val=0)
# Output
self.add_output('con', val=0.0)
def setup_partials(self):
# Finite difference all partials.
self.declare_partials('*', '*', method='fd')
def compute(self, inputs, outputs):
# assemble outputs
outputs['con'] = inputs['M']
def setup(self):
self.add_subsystem('d1', d1(), promotes_inputs=['r','T'],
promotes_outputs=['M','cost'])
self.add_subsystem('con_cmp', self.ConCmp(), promotes_inputs=['M'],
promotes_outputs=['con'])
self.add_subsystem('obj_cmp', self.ObjCmp(), promotes_inputs=['cost'],
promotes_outputs=['obj'])
# Build the model
prob = om.Problem(model=MDA())
model = prob.model
model.add_design_var('r', lower= [3,3,3], upper= [10,10,10])
model.add_design_var('T', lower= 20, upper= 220)
model.add_objective('obj', scaler=1)
model.add_constraint('con', lower=0)
# Setup the optimization
prob.driver = om.ScipyOptimizeDriver(optimizer='SLSQP', tol=1e-3, disp=True)
prob.setup()
prob.set_solver_print(level=0)
prob.run_driver()
# Printout
print('minimum found at')
print(prob.get_val('T')[0])
print(prob.get_val('r'))
print('constraint')
print(prob.get_val('con')[0])
print('minimum objective')
print(prob.get_val('obj')[0])
【问题讨论】:
-
SLSQP 可以与 FD 一起使用,但随着问题越来越大,通常不是最佳优化器选择。在这种情况下,我们建议使用可通过 pyoptsparse 接口使用的 IPOPT(免费)或 SNOPT(商业)。 SNOPT 尊重 AnalysisError 但 SLSQP 不尊重。第一步是使用
prob.check_partials()验证您的部分是否正确,然后使用prob.check_totals()进行总计。 -
谢谢。由于我没有使用解析导数,而是使用 FD,因此我收到以下警告:“(...)使用与计算组件导数相同的方法和选项检查部分将不会提供任何有关准确性的相关信息” )。总数相同。我在编译 pyOptsparse 时也遇到了问题(f90 扩展的问题),你对如何安装它有什么建议吗? conda-forge 发行版似乎消失了……
标签: optimization constraints openmdao