Closed
Description
Hi.
I found this issue with deleting and adding indicator constraints. Consider:
using JuMP
using Gurobi
mdl = JuMP.Model()
set_optimizer(mdl, Gurobi.Optimizer)
b1 = @variable(mdl, binary = true)
x1 = @variable(mdl, lower_bound = -1.0, upper_bound = 1.0)
x2 = @variable(mdl, lower_bound = -1.0, upper_bound = 1.0)
c1 = @constraint(mdl, b1 => {x1 + x2 == 0.1})
c2 = @constraint(mdl, !b1 => {x1 + x2 == -0.1})
@objective(mdl, Max, x1 - x2)
optimize!(mdl)
This works as expected. Note that output of Gurobi shows that there are 2 general contrains in the problem:
Set parameter Username
Gurobi Optimizer version 10.0.0 build v10.0.0rc2 (linux64)
CPU model: 12th Gen Intel(R) Core(TM) i9-12900H, instruction set [SSE2|AVX|AVX2]
Thread count: 20 physical cores, 20 logical processors, using up to 20 threads
Optimize a model with 0 rows, 3 columns and 0 nonzeros
Model fingerprint: 0xa8016401
Model has 2 general constraints
Variable types: 2 continuous, 1 integer (1 binary)
Coefficient statistics:
Matrix range [0e+00, 0e+00]
Objective range [1e+00, 1e+00]
Bounds range [1e+00, 1e+00]
RHS range [0e+00, 0e+00]
GenCon rhs range [1e-01, 1e-01]
GenCon coe range [1e+00, 1e+00]
Presolve added 1 rows and 0 columns
Presolve time: 0.00s
Presolved: 1 rows, 3 columns, 3 nonzeros
Variable types: 2 continuous, 1 integer (1 binary)
Found heuristic solution: objective 1.9000000
Root relaxation: objective 2.000000e+00, 1 iterations, 0.00 seconds (0.00 work units)
Nodes | Current Node | Objective Bounds | Work
Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time
0 0 2.00000 0 1 1.90000 2.00000 5.26% - 0s
Explored 1 nodes (1 simplex iterations) in 0.00 seconds (0.00 work units)
Thread count was 20 (of 20 available processors)
Solution count 1: 1.9
Optimal solution found (tolerance 1.00e-04)
Best objective 1.900000000000e+00, best bound 1.900000000000e+00, gap 0.0000%
User-callback calls 373, time in user-callback 0.00 sec
Now, lets delete and add back the same constraints:
JuMP.delete(mdl, c1)
JuMP.delete(mdl, c2)
c1 = @constraint(mdl, b1 => {x1 + x2 == 0.1})
c2 = @constraint(mdl, !b1 => {x1 + x2 == -0.1})
@objective(mdl, Max, x1 - x2)
optimize!(mdl)
now, Gurobi sees 3 general constraints:
Optimize a model with 0 rows, 3 columns and 0 nonzeros
Model fingerprint: 0xe65febfe
Model has 3 general constraints
...
If we repeat that last section of julia code, number of general constraints reported by Gurobi will constantly increase:
... Model has 4 general constraints ...
... Model has 5 general constraints ...
and so on. Though number of constraints reported by JuMP.all_constraints(mdl, include_variable_in_set_constraints=true)
stays the same.
If we delete/add different constraints, there will be conflicts, though only after second delete
using JuMP
using Gurobi
mdl = JuMP.Model()
set_optimizer(mdl, Gurobi.Optimizer)
b1 = @variable(mdl, binary = true)
x1 = @variable(mdl, lower_bound = -1.0, upper_bound = 1.0)
x2 = @variable(mdl, lower_bound = -1.0, upper_bound = 1.0)
c1 = @constraint(mdl, b1 => {x1 + x2 == 0.1})
c2 = @constraint(mdl, !b1 => {x1 + x2 == -0.1})
@objective(mdl, Max, x1 - x2)
optimize!(mdl)
@assert JuMP.termination_status(mdl) == MOI.OPTIMAL
JuMP.delete(mdl, c1)
JuMP.delete(mdl, c2)
c1 = @constraint(mdl, b1 => {x1 + x2 == 0.2}) # ! changing right hand side
c2 = @constraint(mdl, !b1 => {x1 + x2 == -0.2}) # ! changing right hand side
@objective(mdl, Max, x1 - x2)
optimize!(mdl)
@assert JuMP.termination_status(mdl) == MOI.OPTIMAL
JuMP.delete(mdl, c1)
JuMP.delete(mdl, c2)
c1 = @constraint(mdl, b1 => {x1 + x2 == 0.1})
c2 = @constraint(mdl, !b1 => {x1 + x2 == -0.1})
@objective(mdl, Max, x1 - x2)
optimize!(mdl)
@assert JuMP.termination_status(mdl) == MOI.OPTIMAL # ! throws
currently, the last model is infeasible.
Metadata
Metadata
Assignees
Labels
No labels