python - 当约束在 OpenMDAO 中计算为无穷大时,最好的处理方法是什么?
问题描述
正如问题所述,我想知道当约束或函数通常评估为无穷大时的最佳实践。
例如,假设我们将安全系数限制在一个零件上,该零件的系数计算为
safety_factor = np.divide(allowable_force, applied_force)
在施加的力为 0 的情况下,safety_factor 评估为无穷大。由于施加的力接近 0 时安全系数的极限是无穷大,所以从数学上来说,这是可以验证的。假设安全系数被约束在 2 以上,无穷大大于 2,因此应该满足约束。然而在实践中,这会导致设计变量在下一次迭代中变为 NaN。
这可以在下面的简单示例代码中看到
import openmdao.api as om
import numpy as np
class A(om.ExplicitComponent):
def setup(self):
self.add_input('x')
self.add_output('y')
self.add_output('y2')
def compute(self, inputs, outputs):
outputs['y'] = inputs['x']**2
outputs['y2']= np.inf
if __name__ == '__main__':
prob = om.Problem()
model = prob.model
idv = model.add_subsystem('idv', om.IndepVarComp(), promotes=['*'])
idv.add_output('x')
model.add_subsystem('A', A(), promotes=['*'])
model.add_design_var('x')
model.add_constraint('x', lower=2)
model.add_constraint('y2', lower=2)
model.add_objective('y')
# Setup Optimization
prob.driver = om.ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
prob.driver.options['maxiter'] = 5
prob.driver.options['debug_print'] = ['desvars', 'nl_cons', 'objs', 'totals']
model.approx_totals()
prob.setup()
prob.run_driver()
print('---')
print(prob['y'])
尽管 y2 始终大于 2,但设计变量 x 的计算结果仍为 NaN。我已经做了一个快速修复,我只检查约束是否是无限的,并将其替换为一个通用的非常大的浮点数(例如 999999999),但这似乎不是很pythonic,因此我很好奇最佳实践。
解决方案
我认为处理它的最好方法是通过重新排列方程来避免它。代替
con1: (allowable_force / applied_force) > 2
尝试:
con1: applied_force < 0.5 * allowable_force
那里没有除法,所以你没有任何除以零。
您肯定希望避免 inf 或 NaN 经常出现在变量中的情况,因为您的求解器和优化器可能无法收敛或找到正确的搜索方向。
但是,对于无法避免的组件输出计算,有时我们不得不用一个太接近零的小值替换输出。这也引入了导数的不连续性,这也可能是一个问题。
推荐阅读
- javascript - 如何在 ASP.NET 中获取 JavaScript 的价值
- reactjs - 循环遍历数组时反应状态不更新
- python - 计算长面板日期集中的百分比变化
- javascript - 如何在复选框检查时将 div 移动到其父级的顶部?
- arrays - 切换二维数组值作为对 vb.net 中点击事件的响应
- angular - 具有默认页面的离子选项卡不在选项卡的堆栈中
- c# - LinqToSQL 递归选择
- python - 如何在 pandas 上单独计算特征重复(或 Ridit 特征工程)
- node.js - GCE、带有 Socket.IO 的 Kubernetes、NodeJs 资源不足
- php - PHP如何解释这段代码?