8

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]
Jwem93
  • 333
  • 1
  • 8
  • 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). – Nate Diamond Sep 28 '21 at 16:39
  • 1
    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' – Jwem93 Sep 28 '21 at 22:18

1 Answers1

7

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.

worldsmithhelper
  • 4,007
  • 6
  • 21
  • 1
    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. – Jwem93 Sep 28 '21 at 22:20