Skip to content

Commit f82c7e9

Browse files
authored
[FileFormats] read double-sided variable bounds separately (#2548)
1 parent 2401296 commit f82c7e9

File tree

4 files changed

+39
-11
lines changed

4 files changed

+39
-11
lines changed

src/FileFormats/LP/LP.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,10 @@ function _parse_section(
916916
return
917917
elseif -Inf < lb < ub < Inf
918918
_delete_default_lower_bound_if_present(model, cache, x)
919-
MOI.add_constraint(model, x, MOI.Interval(lb, ub))
919+
# Do not add MOI.Interval constraints because we want to follow
920+
# JuMP's convention of adding separate lower and upper bounds.
921+
MOI.add_constraint(model, x, MOI.GreaterThan(lb))
922+
MOI.add_constraint(model, x, MOI.LessThan(ub))
920923
return
921924
elseif lb == -Inf
922925
_delete_default_lower_bound_if_present(model, cache, x)

src/FileFormats/MPS/MPS.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1287,7 +1287,12 @@ function _add_variable(model, data, variable_map, i, name)
12871287
variable_map[name] = x
12881288
MOI.set(model, MOI.VariableName(), x, name)
12891289
set = bounds_to_set(data.col_lower[i], data.col_upper[i])
1290-
if set !== nothing
1290+
if set isa MOI.Interval
1291+
# Do not add MOI.Interval constraints because we want to follow JuMP's
1292+
# convention of adding separate lower and upper bounds.
1293+
MOI.add_constraint(model, x, MOI.GreaterThan(set.lower::Float64))
1294+
MOI.add_constraint(model, x, MOI.LessThan(set.upper::Float64))
1295+
elseif set !== nothing
12911296
MOI.add_constraint(model, x, set)
12921297
end
12931298
if data.vtype[i] == VTYPE_INTEGER

test/FileFormats/LP/LP.jl

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ module TestLP
99
using Test
1010

1111
import MathOptInterface as MOI
12-
const LP = MOI.FileFormats.LP
12+
import MathOptInterface.FileFormats: LP
13+
1314
const LP_TEST_FILE = "test.lp"
1415

1516
function test_show()
@@ -464,7 +465,8 @@ function test_read_example_lo1()
464465
@test (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) in
465466
constraints
466467
@test (MOI.VariableIndex, MOI.GreaterThan{Float64}) in constraints
467-
@test (MOI.VariableIndex, MOI.Interval{Float64}) in constraints
468+
@test (MOI.VariableIndex, MOI.LessThan{Float64}) in constraints
469+
@test !((MOI.VariableIndex, MOI.Interval{Float64}) in constraints)
468470
io = IOBuffer()
469471
write(io, model)
470472
seekstart(io)
@@ -525,7 +527,8 @@ function test_read_model1()
525527
@test (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) in
526528
constraints
527529
@test (MOI.VariableIndex, MOI.GreaterThan{Float64}) in constraints
528-
@test (MOI.VariableIndex, MOI.Interval{Float64}) in constraints
530+
@test (MOI.VariableIndex, MOI.LessThan{Float64}) in constraints
531+
@test !((MOI.VariableIndex, MOI.Interval{Float64}) in constraints)
529532
@test (MOI.VariableIndex, MOI.Integer) in constraints
530533
@test (MOI.VariableIndex, MOI.ZeroOne) in constraints
531534
@test (MOI.VectorOfVariables, MOI.SOS1{Float64}) in constraints
@@ -543,9 +546,17 @@ function test_read_model2()
543546
@test (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) in
544547
constraints
545548
@test (MOI.VariableIndex, MOI.GreaterThan{Float64}) in constraints
546-
@test (MOI.VariableIndex, MOI.Interval{Float64}) in constraints
549+
@test (MOI.VariableIndex, MOI.LessThan{Float64}) in constraints
550+
@test !((MOI.VariableIndex, MOI.Interval{Float64}) in constraints)
547551
@test (MOI.VariableIndex, MOI.Integer) in constraints
548552
@test (MOI.VariableIndex, MOI.ZeroOne) in constraints
553+
@test MOI.get(model, MOI.VariableName(), MOI.VariableIndex(2)) == "V5"
554+
ci = MOI.ConstraintIndex{MOI.VariableIndex,MOI.LessThan{Float64}}(2)
555+
@test MOI.get(model, MOI.ConstraintSet(), ci) == MOI.LessThan(1.0)
556+
ci = MOI.ConstraintIndex{MOI.VariableIndex,MOI.GreaterThan{Float64}}(2)
557+
@test MOI.get(model, MOI.ConstraintSet(), ci) == MOI.GreaterThan(0.0)
558+
ci = MOI.ConstraintIndex{MOI.VariableIndex,MOI.Interval{Float64}}(2)
559+
@test !MOI.is_valid(model, ci)
549560
@test MOI.get(model, MOI.VariableName(), MOI.VariableIndex(8)) == "V8"
550561
@test model.variables.lower[8] == -Inf
551562
@test model.variables.upper[8] == -3

test/FileFormats/MPS/MPS.jl

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ function test_stacked_data()
170170
con3: 1.0 * x in Interval(3.0, 7.0)
171171
con4: 2.0 * x in Interval(4.0, 8.0)
172172
y in Integer()
173-
y in Interval(1.0, 4.0)
173+
y >= 1.0
174+
y <= 4.0
174175
z in ZeroOne()
175176
""",
176177
)
@@ -182,7 +183,8 @@ function test_stacked_data()
182183
["blank_obj", "con1", "con2", "con3", "con4"],
183184
[
184185
("y", MOI.Integer()),
185-
("y", MOI.Interval{Float64}(1.0, 4.0)),
186+
("y", MOI.GreaterThan{Float64}(1.0)),
187+
("y", MOI.LessThan{Float64}(4.0)),
186188
("z", MOI.ZeroOne()),
187189
],
188190
)
@@ -193,8 +195,13 @@ function test_integer_default_bounds()
193195
model = MPS.Model()
194196
MOI.read_from_file(model, joinpath(@__DIR__, "integer_default_bounds.mps"))
195197
x = only(MOI.get(model, MOI.ListOfVariableIndices()))
198+
ci =
199+
MOI.ConstraintIndex{MOI.VariableIndex,MOI.GreaterThan{Float64}}(x.value)
200+
@test MOI.get(model, MOI.ConstraintSet(), ci) == MOI.GreaterThan(0.0)
201+
ci = MOI.ConstraintIndex{MOI.VariableIndex,MOI.LessThan{Float64}}(x.value)
202+
@test MOI.get(model, MOI.ConstraintSet(), ci) == MOI.LessThan(1.0)
196203
ci = MOI.ConstraintIndex{MOI.VariableIndex,MOI.Interval{Float64}}(x.value)
197-
@test MOI.get(model, MOI.ConstraintSet(), ci) == MOI.Interval(0.0, 1.0)
204+
@test !MOI.is_valid(model, ci)
198205
return
199206
end
200207

@@ -482,7 +489,8 @@ function test_nonzero_variable_bounds()
482489
x == 1.0
483490
y >= 2.0
484491
z <= 3.0
485-
w in Interval(4.0, 5.0)
492+
w >= 4.0
493+
w <= 5.0
486494
""",
487495
)
488496
io = IOBuffer()
@@ -499,7 +507,8 @@ function test_nonzero_variable_bounds()
499507
("x", MOI.EqualTo{Float64}(1.0)),
500508
("y", MOI.GreaterThan{Float64}(2.0)),
501509
("z", MOI.LessThan{Float64}(3.0)),
502-
("w", MOI.Interval{Float64}(4.0, 5.0)),
510+
("w", MOI.GreaterThan{Float64}(4.0)),
511+
("w", MOI.LessThan{Float64}(5.0)),
503512
],
504513
)
505514
return

0 commit comments

Comments
 (0)