Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different best objective reports for mixed ILP #411

Closed
rootjalex opened this issue May 23, 2021 · 2 comments
Closed

Different best objective reports for mixed ILP #411

rootjalex opened this issue May 23, 2021 · 2 comments

Comments

@rootjalex
Copy link

rootjalex commented May 23, 2021

For the following example, Gurobi is reporting a best objective value of 4:

using JuMP
using Gurobi
model = Model(Gurobi.Optimizer);

@variable(model, extent)
@variable(model, y)
@variable(model, yo)
@variable(model, _t0)
@variable(model, _t4)
@variable(model, _t2, Bin)
@variable(model, _t3)

@constraint(model, _t0 <= ((((y * 4) + yo) * 2) + 2))
@constraint(model, _t0 <= extent)
@constraint(model, _t4 <= (((y * 4) + yo) * 2))
@constraint(model, _t4 <= extent)

@constraint(model, _t2 => { (1 <= yo) })
@constraint(model, !_t2 => { (yo <= 0) })
@constraint(model, _t2 => { _t3 == (_t4 + 4)})
@constraint(model, !_t2 => { _t3 == (((y * 4) + yo) * 2)})

@objective(model, Max, ((_t0 - _t3) + 4))
print(model)
optimize!(model)

Output:

Gurobi Optimizer version 9.1.1 build v9.1.1rc0 (mac64)
Thread count: 6 physical cores, 12 logical processors, using up to 12 threads
Optimize a model with 4 rows, 7 columns and 10 nonzeros
Model fingerprint: 0x2ca96aa2
Model has 4 general constraints
Variable types: 6 continuous, 1 integer (1 binary)
Coefficient statistics:
  Matrix range     [1e+00, 8e+00]
  Objective range  [1e+00, 1e+00]
  Bounds range     [0e+00, 0e+00]
  RHS range        [2e+00, 2e+00]
Found heuristic solution: objective 4.0000000
Presolve removed 4 rows and 6 columns
Presolve time: 0.00s

Explored 0 nodes (0 simplex iterations) in 0.00 seconds
Thread count was 1 (of 12 available processors)

Solution count 1: 4 
No other solutions better than 0

Model is unbounded
Best objective 4.000000000000e+00, best bound -, gap -

User-callback calls 45, time in user-callback 0.00 sec

Now, if I add a single constraint to force a higher best objective:

@constraint(model, extent == 2)

Then a higher best objective is obtained:

Gurobi Optimizer version 9.1.1 build v9.1.1rc0 (mac64)
Thread count: 6 physical cores, 12 logical processors, using up to 12 threads
Optimize a model with 5 rows, 7 columns and 11 nonzeros
Model fingerprint: 0xfdbf4857
Model has 4 general constraints
Variable types: 6 continuous, 1 integer (1 binary)
Coefficient statistics:
  Matrix range     [1e+00, 8e+00]
  Objective range  [1e+00, 1e+00]
  Bounds range     [0e+00, 0e+00]
  RHS range        [2e+00, 2e+00]
Presolve added 2 rows and 4 columns
Presolve time: 0.00s
Presolved: 7 rows, 11 columns, 19 nonzeros
Presolved model has 4 SOS constraint(s)
Variable types: 8 continuous, 3 integer (3 binary)
Found heuristic solution: objective 6.0000000

Root relaxation: unbounded, 2 iterations, 0.00 seconds

    Nodes    |    Current Node    |     Objective Bounds      |     Work
 Expl Unexpl |  Obj  Depth IntInf | Incumbent    BestBd   Gap | It/Node Time

     0     0  postponed    0         6.00000          -      -     -    0s
     0     0  postponed    0         6.00000          -      -     -    0s
     0     2  postponed    0         6.00000          -      -     -    0s

Explored 3 nodes (9 simplex iterations) in 0.00 seconds
Thread count was 12 (of 12 available processors)

Solution count 1: 6 

Model is unbounded
Best objective 6.000000000000e+00, best bound 6.000000000000e+00, gap 0.0000%

User-callback calls 60, time in user-callback 0.00 sec

I am a bit confused as to why the first example is reporting a best objective for an unbounded model in the first place, instead of simply not calculating/reporting an objective value.

@odow
Copy link
Member

odow commented May 23, 2021

Gurobi is reporting a best objective value of 4:

This is not what it is saying. Before proving the model is unbounded, Gurobi detected an objective of 4. This is expected behavior and not a bug.

Use termination_status(model) and primal_status(model) to understand the solution returned by the solver. In this case, you get:

julia> termination_status(model)
DUAL_INFEASIBLE::TerminationStatusCode = 3

julia> primal_status(model)
NO_SOLUTION::ResultStatusCode = 0

The fact that

julia> objective_value(model)
4.0

is meaningless because the problem is unbounded.

@rootjalex
Copy link
Author

Ah, that makes sense, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants