jump-dev / Gurobi.jl

A Julia interface to the Gurobi Optimizer
http://www.gurobi.com/
MIT License
221 stars 80 forks source link

GurobiSolver ignores constant term in objective #111

Closed rdeits closed 6 years ago

rdeits commented 6 years ago

It appears that GurobiSolver ignores any constant terms in the JuMP model's cost function. For example:

using JuMP, Gurobi

model = Model(solver=GurobiSolver(OutputFlag=1))
@variable model x
@objective model Min x^2 - 1
solve(model)

The gurobi output shows:

Optimize a model with 0 rows, 1 columns and 0 nonzeros
Model has 1 quadratic objective term
Coefficient statistics:
  Matrix range     [0e+00, 0e+00]
  Objective range  [0e+00, 0e+00]
  QObjective range [2e+00, 2e+00]
  Bounds range     [0e+00, 0e+00]
  RHS range        [0e+00, 0e+00]
Presolve removed 0 rows and 1 columns
Presolve time: 0.00s
Presolve: All rows and columns removed

Barrier solved model in 0 iterations and 0.00 seconds
Optimal objective 0.00000000e+00

but the optimal objective value is actually -1, as confirmed by JuMP:

getvalue(getobjective(model))
# -1.0

Of course, for most optimization problems this is fine. Any constant term in the objective doesn't affect the minimizer, and JuMP still reports the correct final objective with getvalue().

However, there is one case in which this absolutely does matter: mixed-integer programming. When solving an MIP, Gurobi checks optimality by measuring (among other things), the relative gap between the best incumbent and the best bound. Since this gap is relative to the actual cost value, adding an arbitrary constant offset (or failing to add one) will affect whether the MIP gap is considered small enough.

This is causing some trouble for me, since I see very different solve times depending on how the particular initial state of my system affects the (eliminated) constant term in the cost.

Is there any way to turn this on in Gurobi.jl? I'd be happy to do the work myself, but I'd appreciate some pointers on where to look, since I haven't used the internal Gurobi interface at all.

odow commented 6 years ago

Gurobi doesn't support offsets in the objective(see below comment). Couldn't you just modify the tolerance to account for the constant term?

Alternatively, add a fixed variable, and add a constraint

using JuMP, Gurobi

model = Model(solver=GurobiSolver(OutputFlag=1))
@variable model x
@variable model y
@constraint model y == -1
@objective model Min x^2 + y
solve(model)
rdeits commented 6 years ago

Oh, well, that's a pretty good reason for GurobiSolver to ignore them, then :smile:

Yeah, I definitely could, but was hoping I wouldn't have to. I like the fixed variable idea a lot, too. Thanks!

joehuchette commented 6 years ago

FWIW it looks like Gurobi supports constant offsets through their new multiobjective interface (GRBsetobjectiven in the reference manual).

odow commented 6 years ago

Let's reopen this so it can be implemented in the future.

rdeits commented 6 years ago

Ok, thanks!

odow commented 6 years ago

Gurobi doesn't support offsets in the objective

I was wrong. See http://www.gurobi.com/documentation/7.0/refman/objcon.html#attr:ObjCon