PyOmo/Ipopt 因“无法评估 pow”而失败

Posted

技术标签:

【中文标题】PyOmo/Ipopt 因“无法评估 pow”而失败【英文标题】:PyOmo/Ipopt fails with "can't evaluate pow" 【发布时间】:2016-10-18 16:36:44 【问题描述】:

我正在使用 PyOmo 生成一个非线性模型,该模型最终将通过 Ipopt 解决。模型如下:

from pyomo.environ import *
from pyomo.dae import *

m = ConcreteModel()

m.t = ContinuousSet(bounds=(0,100)) 

m.T  = Param(default=100,mutable=True)
m.a  = Param(default=0.1)
m.kP = Param(default=20)
m.P  = Var(m.t, bounds=(0,None))
m.S  = Var(m.t, bounds=(0,None))
m.u  = Var(m.t, bounds=(0,1), initialize=0.5)

m.Pdot = DerivativeVar(m.P)
m.Sdot = DerivativeVar(m.S)

m.obj = Objective(expr=m.S[100],sense=maximize)

def _Pdot(M,i):
  if i == 0:
    return Constraint.Skip
  return M.Pdot[i] == (1-M.u[i])*(M.P[i]**0.75)

def _Sdot(M,i):
  if i == 0:
    return Constraint.Skip
  return M.Sdot[i] == M.u[i]*0.2*(M.P[i]**0.75)

def _init(M):
  yield M.P[0] == 2
  yield M.S[0] == 0
  yield ConstraintList.End

m.Pdotcon         = Constraint(m.t, rule=_Pdot)
m.Sdotcon         = Constraint(m.t, rule=_Sdot)
m.init_conditions = ConstraintList(rule=_init)

discretizer = TransformationFactory('dae.collocation')
discretizer.apply_to(m,nfe=100,ncp=3,scheme='LAGRANGE-RADAU')
discretizer.reduce_collocation_points(m,var=m.u,ncp=1,contset=m.t)

solver  = SolverFactory('ipopt')
results = solver.solve(m,tee=False)

运行模型导致以下错误:

Error evaluating constraint 1: can't evaluate pow'(0,0.75).

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.5/dist-packages/pyomo/opt/base/solvers.py", line 577, in solve
    "Solver (%s) did not exit normally" % self.name)
pyutilib.common._exceptions.ApplicationError: Solver (asl) did not exit normally

错误的第一部分来自 Ipopt,而第二部分来自 PyOmo。显然,这个问题与约束中的 M.P[i]**0.75 一词无关,但更改电源并不能解决问题(尽管 2.0 确实有效)。

我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

错误消息指出无法评估pow'(0,0.75)。此函数中的' 字符表示一阶导数('' 表示二阶导数)。该消息实际上是在说一阶导数不存在或导致无穷大为零。

解决问题很简单:将变量绑定到一个非零值,如下所示:

m.P  = Var(m.t, bounds=(1e-20,None))
m.S  = Var(m.t, bounds=(1e-20,None))

【讨论】:

【参考方案2】:

我会补充理查德的回答:

您可能还需要更新变量的初始值,因为如果未指定,ipopt 会假定为 0,因此它将在第一次迭代时将变量评估为 0。

因此:

m.P  = Var(m.t, bounds=(1e-20,None), initialize=1e-20)
m.S  = Var(m.t, bounds=(1e-20,None), initialize=1e-20)

您可以使用与您的问题更相关的值来代替 1e-20 作为初始化值

【讨论】:

以上是关于PyOmo/Ipopt 因“无法评估 pow”而失败的主要内容,如果未能解决你的问题,请参考以下文章

电脑自检 转

为啥这个 PySide2 构建找不到生成的 C++ 包装器?

高效的mysql分页技巧

高效的mysql分页技巧

document.activeElement 过滤选择文件弹窗导致的页面失焦

华为云技术分享根因分析