I am trying to understand how ipopt_zL_out
and ipopt_zU_out
are assigned particularly for fixed variable (i.e., the variable with the same lower and upper bounds). I found that the Suffixes values (ipopt_zL_out
and ipopt_zU_out
) were None
's sometimes, depending on the problem data. Here is a minimum example modified from one of the pyomo examples.
import numpy as np
import pyomo.environ
from pyomo.core import *
from pyomo.opt import SolverFactory
solver = 'ipopt'
solver_io = 'nl'
stream_solver = False # True prints solver output to screen
keepfiles = False # True prints intermediate file names (.nl,.sol,...)
opt = SolverFactory(solver, solver_io=solver_io, tee=False)
model = ConcreteModel()
model.x_set = RangeSet(5)
x5_val = 0.0
var_lb = {1:1, 2:1, 3:2, 4:1, 5:x5_val}
var_ub = {1:5, 2:5, 3:2, 4:5, 5:x5_val}
def var_bounds(model, i):
return (var_lb[i], var_ub[i])
model.x = Var(model.x_set, bounds=var_bounds)
model.x[1] = 1
model.x[2] = 1
model.x[3] = 2
model.x[4] = 1
model.x[5] = x5_val
model.obj = Objective(
expr=model.x[1] * model.x[4] * (model.x[1] + model.x[2] + model.x[3]) + model.x[3] + model.x[5]**2
)
model.constraints = ConstraintList()
model.constraints.add(model.x[1] * model.x[2] * model.x[3] * model.x[4] >= 25.0)
model.constraints.add(model.x[1]**2 + model.x[2]**2 + model.x[3]**2 + model.x[4]**2 + model.x[5]**2 == 40.0)
model.ipopt_zL_out = Suffix(direction=Suffix.IMPORT)
model.ipopt_zU_out = Suffix(direction=Suffix.IMPORT)
model.dual = Suffix(direction=Suffix.IMPORT_EXPORT)
opt.options['linear_solver']='ma27'
opt.options['fixed_variable_treatment']='make_parameter'
results = opt.solve(model, keepfiles=keepfiles, tee=stream_solver)
model.ipopt_zL_out.display()
model.ipopt_zU_out.display()
In the example above, both ipopt_zL_out
and ipopt_zU_out
are None for model.x[5]
. But, if I set x5_val = 1.0
, then ipopt_zU_out
has a value for model.x[5]
.
So this is my question. If these Suffixes are None
, is the corresponding reduced cost zero? What is the best practice to get the reduced cost for variables?