Skip to content

Commit f5112cc

Browse files
committed
fix(jump): fixed a bug in converting quadratic terms from JuMP to AOCoptimizer; added unit tests
1 parent d3c0c7a commit f5112cc

File tree

6 files changed

+94
-5
lines changed

6 files changed

+94
-5
lines changed

Project.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ JSON = "0.21"
5656
JuMP = "1"
5757
KernelAbstractions = "0.9"
5858
LinearAlgebra = "1.11"
59+
MathOptInterface = "1"
5960
OrderedCollections = "1.8"
6061
Pkg = "1.11"
6162
PrecompileTools = "1"
@@ -71,7 +72,9 @@ julia = "1"
7172
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
7273
CodecBzip2 = "523fee87-0ab8-5b00-afb7-3ecf72e48cfd"
7374
JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b"
75+
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
76+
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
7477
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
7578

7679
[targets]
77-
test = ["Aqua", "CodecBzip2", "JET", "Test"]
80+
test = ["Aqua", "CodecBzip2", "JET", "JuMP", "MathOptInterface", "Test"]

ext/JuMPExt/wrapper.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,13 @@ function _parse_objective(
373373

374374
if continuous[i] || continuous[j]
375375
if i == j
376-
Q[i, j] += T(2.0) * qij
376+
#= The SQF function already has a 0.5 factor,
377+
hence, we do not need to multiply with 2 here.
378+
Hence, there is no need for this special case,
379+
but good to keep (including this comment) to
380+
avoid future errors.
381+
=#
382+
Q[i, j] += qij # * T(2.0)
377383
else
378384
Q[i, j] += qij
379385
Q[j, i] += qij

notebooks/test-jump.jl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,20 @@ model = Model(AOCoptimizer.MOI.Optimizer[])
1515
@objective(model, Min, x + y * z)
1616

1717
# The following will solve with default settings,
18-
# using 60sec as timeout value.
18+
# using 10sec as timeout value.
1919
optimize!(model)
2020

2121
@show termination_status(model)
2222
@show objective_value(model)
2323
@show value(x)
2424
@show value(y)
2525
@show value(z)
26+
27+
let inner_model = unsafe_backend(model)
28+
@show inner_model.sense
29+
@show inner_model.quadratic
30+
@show inner_model.linear
31+
@show inner_model.offset
32+
@show inner_model.aim_attributes
33+
@show inner_model.output
34+
end

src/init.jl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,15 @@ init.jl
66
module MOI
77
Optimizer :: Ref{Any} = nothing
88

9-
function __init()
9+
"""
10+
init()
11+
12+
Enables the AOCoptimizer backend for MathOptInterface (MOI), if available.
13+
Typically, users should not call this explicitly. Instead, the `JuMP` and `MathOptInterface`
14+
packages should be imported before importing `AOCoptimizer` and
15+
calling `AOCoptimizer.init()`.
16+
"""
17+
function init()
1018
__modules = Base.loaded_modules_array()
1119
__index_of_jump_ext = findfirst(x -> nameof(x) == :JuMPExt, __modules)
1220
if __index_of_jump_ext === nothing
@@ -33,7 +41,7 @@ function init()
3341
Solver.__register_engines()
3442
Solver.__register_solvers()
3543

36-
MOI.__init()
44+
MOI.init()
3745

3846
@debug "End of AOCoptimizer initialization."
3947
__init_completed[] = true

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ include("utils.jl")
3333
include("test_reader_simple_graph.jl")
3434
include("test_reader_qio.jl")
3535
include("test_api.jl")
36+
include("test_jump.jl")
3637
end
3738

3839
if !disable_jet

test/test_jump.jl

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#=
2+
test_jump.jl
3+
4+
Unit tests for the JuMP extension of AOCoptimizer.
5+
=#
6+
7+
module TestJump
8+
9+
using Test
10+
using JuMP
11+
using MathOptInterface
12+
using AOCoptimizer
13+
14+
include("utils.jl")
15+
16+
# AOCoptimizer.init()
17+
AOCoptimizer.MOI.init()
18+
19+
const aoc_moi = AOCoptimizer.MOI
20+
21+
@testset verbose=verbose "Test simple JuMP problems" begin
22+
@testset "Test simple QUMO" begin
23+
model = Model(aoc_moi.Optimizer[])
24+
25+
@variable(model, x, Bin)
26+
@variable(model, y, Bin)
27+
@variable(model, -1 <= z <= 1)
28+
@objective(model, Min, x + y * z)
29+
30+
optimize!(model)
31+
32+
@test value(x) == 0
33+
@test value(y) == 1
34+
@test value(z) -1
35+
@test objective_value(model) -1
36+
end
37+
38+
@testset "Test continuous only" begin
39+
model = Model(aoc_moi.Optimizer[])
40+
@variable(model, -1 <= z <= 1)
41+
@objective(model, Min, (z - 0.25)^2)
42+
43+
optimize!(model)
44+
45+
@test isapprox(objective_value(model), 0, atol=1e-6)
46+
@test isapprox(value(z), 0.25, atol=1e-6)
47+
end
48+
49+
@testset "Test two continuous" begin
50+
model = Model(AOCoptimizer.MOI.Optimizer[])
51+
@variable(model, -1 <= x <= 1)
52+
@variable(model, -1 <= y <= 1)
53+
@objective(model, Min, (x - 0.2) * (y - 0.2))
54+
55+
optimize!(model)
56+
57+
@test objective_value(model) -0.96
58+
@test value(x) * value(y) -1
59+
end
60+
end
61+
62+
end # module

0 commit comments

Comments
 (0)