Skip to content

Commit 5ad5269

Browse files
authored
[FileFormats.MPS] fix issue #2479 (#2490)
1 parent eff2982 commit 5ad5269

File tree

5 files changed

+92
-0
lines changed

5 files changed

+92
-0
lines changed

src/FileFormats/MPS/MPS.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,7 @@ mutable struct TempMPSModel
10241024
obj_constant::Float64
10251025
col_lower::Vector{Float64}
10261026
col_upper::Vector{Float64}
1027+
col_bounds_default::Vector{Bool}
10271028
row_lower::Vector{Float64}
10281029
row_upper::Vector{Float64}
10291030
sense::Vector{Sense}
@@ -1050,6 +1051,7 @@ function TempMPSModel()
10501051
0.0, # obj_constant
10511052
Float64[], # col_lower
10521053
Float64[], # col_upper
1054+
Bool[], # col_bounds_default
10531055
Float64[], # row_lower
10541056
Float64[], # row_upper
10551057
Sense[], # sense
@@ -1465,6 +1467,7 @@ function _add_new_column(data, column_name)
14651467
push!(data.c, 0.0)
14661468
push!(data.col_lower, 0.0)
14671469
push!(data.col_upper, Inf)
1470+
push!(data.col_bounds_default, true)
14681471
push!(data.vtype, VTYPE_CONTINUOUS)
14691472
return
14701473
end
@@ -1641,6 +1644,13 @@ function _parse_single_bound(data, column_name::String, bound_type::String)
16411644
if col === nothing
16421645
error("Column name $(column_name) not found.")
16431646
end
1647+
if data.col_bounds_default[col] && data.vtype[col] == VTYPE_INTEGER
1648+
# This column was part of an INTORG...INTEND block, so it gets a default
1649+
# bound of [0, 1]. However, since it now has a bound, it reverts to a
1650+
# default of [0, inf).
1651+
data.col_upper[col] = Inf
1652+
end
1653+
data.col_bounds_default[col] = false
16441654
if bound_type == "PL"
16451655
data.col_upper[col] = Inf
16461656
elseif bound_type == "MI"
@@ -1667,6 +1677,13 @@ function _parse_single_bound(
16671677
if col === nothing
16681678
error("Column name $(column_name) not found.")
16691679
end
1680+
if data.col_bounds_default[col] && data.vtype[col] == VTYPE_INTEGER
1681+
# This column was part of an INTORG...INTEND block, so it gets a default
1682+
# bound of [0, 1]. However, since it now has a bound, it reverts to a
1683+
# default of [0, inf).
1684+
data.col_upper[col] = Inf
1685+
end
1686+
data.col_bounds_default[col] = false
16701687
if bound_type == "FX"
16711688
data.col_lower[col] = value
16721689
data.col_upper[col] = value

test/FileFormats/MPS/MPS.jl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,45 @@ function test_integer_default_bounds()
200200
return
201201
end
202202

203+
function test_integer_default_bounds_LI()
204+
model = MPS.Model()
205+
filename = joinpath(@__DIR__, "integer_default_bounds_LI.mps")
206+
MOI.read_from_file(model, filename)
207+
x = only(MOI.get(model, MOI.ListOfVariableIndices()))
208+
c_types = MOI.get(model, MOI.ListOfConstraintTypesPresent())
209+
@test length(c_types) == 2
210+
@test (MOI.VariableIndex, MOI.Integer) in c_types
211+
F, S = MOI.VariableIndex, MOI.GreaterThan{Float64}
212+
@test (F, S) in c_types
213+
ci = MOI.ConstraintIndex{F,S}(x.value)
214+
@test MOI.get(model, MOI.ConstraintSet(), ci) == MOI.GreaterThan(1.0)
215+
return
216+
end
217+
218+
function test_integer_default_bounds_MI()
219+
model = MPS.Model()
220+
filename = joinpath(@__DIR__, "integer_default_bounds_MI.mps")
221+
MOI.read_from_file(model, filename)
222+
@test MOI.get(model, MOI.ListOfConstraintTypesPresent()) ==
223+
[(MOI.VariableIndex, MOI.Integer)]
224+
return
225+
end
226+
227+
function test_integer_default_bounds_PL()
228+
model = MPS.Model()
229+
filename = joinpath(@__DIR__, "integer_default_bounds_PL.mps")
230+
MOI.read_from_file(model, filename)
231+
x = only(MOI.get(model, MOI.ListOfVariableIndices()))
232+
c_types = MOI.get(model, MOI.ListOfConstraintTypesPresent())
233+
@test length(c_types) == 2
234+
@test (MOI.VariableIndex, MOI.Integer) in c_types
235+
F, S = MOI.VariableIndex, MOI.GreaterThan{Float64}
236+
@test (F, S) in c_types
237+
ci = MOI.ConstraintIndex{F,S}(x.value)
238+
@test MOI.get(model, MOI.ConstraintSet(), ci) == MOI.GreaterThan(0.0)
239+
return
240+
end
241+
203242
function test_free_integer()
204243
model = MPS.Model()
205244
MOI.read_from_file(model, joinpath(@__DIR__, "free_integer.mps"))
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
NAME
2+
OBJSENSE MIN
3+
ROWS
4+
N obj
5+
COLUMNS
6+
MARKER 'MARKER' 'INTORG'
7+
x obj 1
8+
MARKER 'MARKER' 'INTEND'
9+
RHS
10+
BOUNDS
11+
LI BND1 x 1
12+
ENDATA
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
NAME
2+
OBJSENSE MIN
3+
ROWS
4+
N obj
5+
COLUMNS
6+
MARKER 'MARKER' 'INTORG'
7+
x obj 1
8+
MARKER 'MARKER' 'INTEND'
9+
RHS
10+
BOUNDS
11+
MI BND1 x
12+
ENDATA
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
NAME
2+
OBJSENSE MIN
3+
ROWS
4+
N obj
5+
COLUMNS
6+
MARKER 'MARKER' 'INTORG'
7+
x obj 1
8+
MARKER 'MARKER' 'INTEND'
9+
RHS
10+
BOUNDS
11+
PL BND1 x
12+
ENDATA

0 commit comments

Comments
 (0)