# Why is Gurobi output in Pyomo returning floating-point values rather than optimal integer solution?

I am hoping someone will be able to point me in the direction of why I am experiencing floating-point outputs rather than simply model.X = [15,15] and model.Z = [15,5] as solutions to this model?

Note that I use a piece-wise constraint to determine the relationship between Z and X.

Scroll down to see the outputs from the model solver.

Code

from pyomo.core import *

# Define the model type
model = ConcreteModel()

# Piecewise components - index and variables
model.INDEX1 = Set(dimen=1, initialize=[0,1])
model.X = Var(model.INDEX1, bounds=(5,15))
model.Z = Var(model.INDEX1)

# For indexed variables, the following must be python dictionaries with keys the same as the variable index

DOMAIN_PTS = {0: [5, 10, 15], 1: [5, 10, 15]}
RANGE_PTS = {0: [30, 20, 15], 1: [5, 5, 5]}

# Set piecewise constraint
model.linearized_constraint = Piecewise(model.INDEX1,        # indexing sets
model.Z,model.X,     # range and domain variables
pw_pts=DOMAIN_PTS,
pw_constr_type='EQ',
pw_repn='INC',
f_rule=RANGE_PTS,
unbounded_domain_var = False)

# Maximize the sumproduct of z and x over the index
model.obj = Objective(expr= sum(model.Z[i] * model.X[i] for i in model.INDEX1) , sense=maximize)
opt = SolverFactory('gurobi')
opt.options['NonConvex'] = 2
obj_val = opt.solve(model)

# Print results
print([value(model.X[i]) for i in model.INDEX1])
print([value(model.Z[i]) for i in model.INDEX1])


Output

**WARNING: Piecewise component 'linearized_constraint[(1,)]' has detected slopes of consecutive piecewise segments to be within 1e-08 of one another. Refer to the Piecewise help documentation for information on how to disable this warning.
[14.890257352941177, 15.0]
[15.109742647058823, 5.0]

• Just making sure, I'm not 100% sure that you're defining the variables as integer variables. You're setting the bounds and pinning them to the index set, but you haven't defined the variables to be integers themselves. For instance, model.X = Var(model.INDEX1, bounds=(5,15), domain=PositiveIntegers). Sep 28 at 16:39
• Thanks Nate. The x variable can actually be floating, so I didn't set it to be integer only. My interest was in why gurobi wasn't giving me the optimal result (which happens to be integers in this example). I now believe the issue is that I should set pw_constr_type = 'UB' Sep 28 at 22:18

I suspect Gurobi actually only gets passed floating point values from the Python API and it only works with floating point values internally so Python or the Python API might implictly convert your integers to floating points value.

If we look at the C function GRBsetpwlobj which is given as example how to define piecewise functions here.

int     GRBsetpwlobj (  GRBmodel    *model,
int     var,
int     npoints,
double  *x,
double  *y )


x and y are arrays of double numbers which are floating point numbers.

The reason why you get floating point values is because Gurobi only gets floating point values to work with.

• Thanks for your help @wordsmithhelper, that makes perfect sense. I have actually found that I can get the desired result in my problem by setting pw_constr_type = 'UB' when I am maximising the objective. Sep 28 at 22:20