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

[FileFormats.MPS] fix issue #2479 #2490

Merged
merged 1 commit into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/FileFormats/MPS/MPS.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,7 @@ mutable struct TempMPSModel
obj_constant::Float64
col_lower::Vector{Float64}
col_upper::Vector{Float64}
col_bounds_default::Vector{Bool}
row_lower::Vector{Float64}
row_upper::Vector{Float64}
sense::Vector{Sense}
Expand All @@ -1050,6 +1051,7 @@ function TempMPSModel()
0.0, # obj_constant
Float64[], # col_lower
Float64[], # col_upper
Bool[], # col_bounds_default
Float64[], # row_lower
Float64[], # row_upper
Sense[], # sense
Expand Down Expand Up @@ -1465,6 +1467,7 @@ function _add_new_column(data, column_name)
push!(data.c, 0.0)
push!(data.col_lower, 0.0)
push!(data.col_upper, Inf)
push!(data.col_bounds_default, true)
push!(data.vtype, VTYPE_CONTINUOUS)
return
end
Expand Down Expand Up @@ -1641,6 +1644,13 @@ function _parse_single_bound(data, column_name::String, bound_type::String)
if col === nothing
error("Column name $(column_name) not found.")
end
if data.col_bounds_default[col] && data.vtype[col] == VTYPE_INTEGER
# This column was part of an INTORG...INTEND block, so it gets a default
# bound of [0, 1]. However, since it now has a bound, it reverts to a
# default of [0, inf).
data.col_upper[col] = Inf
end
data.col_bounds_default[col] = false
if bound_type == "PL"
data.col_upper[col] = Inf
elseif bound_type == "MI"
Expand All @@ -1667,6 +1677,13 @@ function _parse_single_bound(
if col === nothing
error("Column name $(column_name) not found.")
end
if data.col_bounds_default[col] && data.vtype[col] == VTYPE_INTEGER
# This column was part of an INTORG...INTEND block, so it gets a default
# bound of [0, 1]. However, since it now has a bound, it reverts to a
# default of [0, inf).
data.col_upper[col] = Inf
end
data.col_bounds_default[col] = false
if bound_type == "FX"
data.col_lower[col] = value
data.col_upper[col] = value
Expand Down
39 changes: 39 additions & 0 deletions test/FileFormats/MPS/MPS.jl
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,45 @@ function test_integer_default_bounds()
return
end

function test_integer_default_bounds_LI()
model = MPS.Model()
filename = joinpath(@__DIR__, "integer_default_bounds_LI.mps")
MOI.read_from_file(model, filename)
x = only(MOI.get(model, MOI.ListOfVariableIndices()))
c_types = MOI.get(model, MOI.ListOfConstraintTypesPresent())
@test length(c_types) == 2
@test (MOI.VariableIndex, MOI.Integer) in c_types
F, S = MOI.VariableIndex, MOI.GreaterThan{Float64}
@test (F, S) in c_types
ci = MOI.ConstraintIndex{F,S}(x.value)
@test MOI.get(model, MOI.ConstraintSet(), ci) == MOI.GreaterThan(1.0)
return
end

function test_integer_default_bounds_MI()
model = MPS.Model()
filename = joinpath(@__DIR__, "integer_default_bounds_MI.mps")
MOI.read_from_file(model, filename)
@test MOI.get(model, MOI.ListOfConstraintTypesPresent()) ==
[(MOI.VariableIndex, MOI.Integer)]
return
end

function test_integer_default_bounds_PL()
model = MPS.Model()
filename = joinpath(@__DIR__, "integer_default_bounds_PL.mps")
MOI.read_from_file(model, filename)
x = only(MOI.get(model, MOI.ListOfVariableIndices()))
c_types = MOI.get(model, MOI.ListOfConstraintTypesPresent())
@test length(c_types) == 2
@test (MOI.VariableIndex, MOI.Integer) in c_types
F, S = MOI.VariableIndex, MOI.GreaterThan{Float64}
@test (F, S) in c_types
ci = MOI.ConstraintIndex{F,S}(x.value)
@test MOI.get(model, MOI.ConstraintSet(), ci) == MOI.GreaterThan(0.0)
return
end

function test_free_integer()
model = MPS.Model()
MOI.read_from_file(model, joinpath(@__DIR__, "free_integer.mps"))
Expand Down
12 changes: 12 additions & 0 deletions test/FileFormats/MPS/integer_default_bounds_LI.mps
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
NAME
OBJSENSE MIN
ROWS
N obj
COLUMNS
MARKER 'MARKER' 'INTORG'
x obj 1
MARKER 'MARKER' 'INTEND'
RHS
BOUNDS
LI BND1 x 1
ENDATA
12 changes: 12 additions & 0 deletions test/FileFormats/MPS/integer_default_bounds_MI.mps
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
NAME
OBJSENSE MIN
ROWS
N obj
COLUMNS
MARKER 'MARKER' 'INTORG'
x obj 1
MARKER 'MARKER' 'INTEND'
RHS
BOUNDS
MI BND1 x
ENDATA
12 changes: 12 additions & 0 deletions test/FileFormats/MPS/integer_default_bounds_PL.mps
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
NAME
OBJSENSE MIN
ROWS
N obj
COLUMNS
MARKER 'MARKER' 'INTORG'
x obj 1
MARKER 'MARKER' 'INTEND'
RHS
BOUNDS
PL BND1 x
ENDATA
Loading