Search code examples
optimizationipoptpyomo

PyOmo/Ipopt fails with "can't evaluate pow"


I am using PyOmo to generate a nonlinear model which will ultimately be solved with Ipopt. The model is as follows:

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)

Running the model results in the following error:

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

The first part of the error comes from Ipopt whereas the second part comes from PyOmo. Evidently the issue has something ot do with the term M.P[i]**0.75 in the constraints, but changing the power does not resolve the issue (though 2.0 did work).

How can I resolve this?


Solution

  • The error message states that pow'(0,0.75) cannot be evaluated. The ' character in this function indicates the first derivative ('' would indiate the second derivative). The message is effectively saying that the first derivative does not exist or results in an infinity at zero.

    Resolving the issue is easy: bound your variables to a non-zero value as follows:

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