PyOmo / Ipopt терпит неудачу из-за невозможности оценки мощности

Я использую 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 действительно сработало).

Как я могу это решить?


person Richard    schedule 17.06.2016    source источник


Ответы (2)


В сообщении об ошибке указано, что pow'(0,0.75) не может быть оценено. Символ ' в этой функции указывает на первую производную ('' будет указывать на вторую производную). Сообщение фактически говорит, что первая производная не существует или приводит к бесконечности в нуле.

Устранить проблему легко: привяжите переменные к ненулевому значению следующим образом:

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

Я бы добавил к ответу Ричарда:

вам также может потребоваться обновить начальное значение вашей переменной, поскольку 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 в качестве инициализации вы можете использовать значение, более подходящее для вашей проблемы

person Jean Martin    schedule 18.06.2020