Skip to content

Commit

Permalink
[FileFormats.LP] fix reading off-diagonals of quadratic functions (#2182
Browse files Browse the repository at this point in the history
)
  • Loading branch information
odow authored May 31, 2023
1 parent a189a89 commit 207b153
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 6 deletions.
7 changes: 4 additions & 3 deletions src/FileFormats/LP/LP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -596,11 +596,12 @@ function _parse_function(
push!(f.terms, term::MOI.ScalarAffineTerm{Float64})
elseif term isa MOI.ScalarQuadraticTerm{Float64}
push!(cache.quad_terms, term::MOI.ScalarQuadraticTerm{Float64})
if tokens[offset-1] == "]"
if tokens[offset-1] in ("]", "]/2")
scale = tokens[offset-1] == "]/2" ? 0.5 : 1
for (i, term) in enumerate(cache.quad_terms)
x, y = term.variable_1, term.variable_2
scale = (x == y ? 2 : 1) * term.coefficient
cache.quad_terms[i] = MOI.ScalarQuadraticTerm(scale, x, y)
coef = scale * (x == y ? 2 : 1) * term.coefficient
cache.quad_terms[i] = MOI.ScalarQuadraticTerm(coef, x, y)
end
end
else
Expand Down
61 changes: 58 additions & 3 deletions test/FileFormats/LP/LP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ function test_read_model1_tricky()
seekstart(io)
file = read(io, String)
@test occursin("maximize", file)
@test occursin("obj: -1 Var4 + 1 V5 + [ 1 Var4 ^ 2 - 2.4 V5 * V1 ]/2", file)
@test occursin("obj: -1 Var4 + 1 V5 + [ 1 Var4 ^ 2 - 1.2 V5 * V1 ]/2", file)
@test occursin("CON3: 1 V3 <= 2.5", file)
@test occursin("CON4: 1 V5 + 1 V6 + 1 V7 <= 1", file)
@test occursin("CON1: 1 V1 >= 0", file)
Expand Down Expand Up @@ -632,8 +632,8 @@ function test_read_tricky_quadratic()
@test occursin("minimize", file)
@test occursin("obj: [ 2 x ^ 2 + 2 x * y ]/2", file)
@test occursin("c1: [ 1 x ^ 2 - 1 x * y ] <= 0", file)
@test occursin("c2: [ 0.5 x ^ 2 - 1 x * y ] <= 0", file)
@test occursin("c3: [ 0.5 x ^ 2 - 1 x * y ] <= 0", file)
@test occursin("c2: [ 0.5 x ^ 2 - 0.5 x * y ] <= 0", file)
@test occursin("c3: [ 0.5 x ^ 2 - 0.5 x * y ] <= 0", file)
@test occursin("x free", file)
@test occursin("y free", file)
return
Expand Down Expand Up @@ -832,6 +832,61 @@ function test_reading_bounds()
return
end

function _test_read_quadratic(input::String, output::String = input)
io = IOBuffer()
input_text = """
minimize
obj: $input
subject to
Bounds
x >= 0
y >= 0
End
"""
write(io, input_text)
model = MOI.FileFormats.LP.Model()
seekstart(io)
read!(io, model)
out = IOBuffer()
write(out, model)
seekstart(out)
output_text = """
minimize
obj: $output
subject to
Bounds
x >= 0
y >= 0
End
"""
@test read(out, String) == output_text
return
end

function test_read_quadratic()
_test_read_quadratic("1 x + 1 y + [ 1 x * y + 1 y ^ 2 ]/2")
_test_read_quadratic("1 x + 1 y + [ 2 x * y + 1 y ^ 2 ]/2")
_test_read_quadratic("1 x + 1 y + [ 1 x * y + 2 y ^ 2 ]/2")
_test_read_quadratic("1 x + 1 y + [ 2 x * y + 2 y ^ 2 ]/2")
_test_read_quadratic(
"1 x + 1 y + [ 1 x * y + 1 y ^ 2 ]",
"1 x + 1 y + [ 2 x * y + 2 y ^ 2 ]/2",
)
_test_read_quadratic(
"1 x + 1 y + [ 2 x * y + 1 y ^ 2 ]",
"1 x + 1 y + [ 4 x * y + 2 y ^ 2 ]/2",
)
_test_read_quadratic(
"1 x + 1 y + [ 1 x * y + 2 y ^ 2 ]",
"1 x + 1 y + [ 2 x * y + 4 y ^ 2 ]/2",
)
_test_read_quadratic(
"1 x + 1 y + [ 2 x * y + 2 y ^ 2 ]",
"1 x + 1 y + [ 4 x * y + 4 y ^ 2 ]/2",
)
return
end

function runtests()
for name in names(@__MODULE__, all = true)
if startswith("$(name)", "test_")
Expand Down

0 comments on commit 207b153

Please sign in to comment.