Skip to content

Commit dcc9264

Browse files
odowmlubin
authored andcommitted
Add tests for ObjectiveBound (#446)
* Add tests for ObjectiveBound * Clean up some nits.
1 parent b92af7b commit dcc9264

File tree

4 files changed

+117
-1
lines changed

4 files changed

+117
-1
lines changed

src/Test/UnitTests/solve.jl

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
"""
2+
solve_objbound_edge_cases(model::MOI.ModelLike, config::TestConfig)
3+
4+
Test a variety of edge cases related to the ObjectiveBound attribute.
5+
"""
6+
function solve_objbound_edge_cases(model::MOI.ModelLike, config::TestConfig)
7+
@testset "Min IP with constant" begin
8+
MOI.empty!(model)
9+
@test MOI.isempty(model)
10+
MOIU.loadfromstring!(model, """
11+
variables: x
12+
minobjective: 2.0x + -1.0
13+
c1: x >= 1.5
14+
c2: x in Integer()
15+
""")
16+
x = MOI.get(model, MOI.VariableIndex, "x")
17+
test_model_solution(model, config;
18+
objective_value = 3.0,
19+
variable_primal = [(x, 2.0)]
20+
)
21+
if config.solve
22+
@test MOI.get(model, MOI.ObjectiveBound()) <= 3.0
23+
end
24+
end
25+
26+
@testset "Max IP with constant" begin
27+
MOI.empty!(model)
28+
@test MOI.isempty(model)
29+
MOIU.loadfromstring!(model, """
30+
variables: x
31+
maxobjective: 2.0x + 1.0
32+
c1: x <= 1.5
33+
c2: x in Integer()
34+
""")
35+
x = MOI.get(model, MOI.VariableIndex, "x")
36+
test_model_solution(model, config;
37+
objective_value = 3.0,
38+
variable_primal = [(x, 1.0)]
39+
)
40+
if config.solve
41+
@test MOI.get(model, MOI.ObjectiveBound()) >= 3.0
42+
end
43+
end
44+
45+
@testset "Min LP with constant" begin
46+
MOI.empty!(model)
47+
@test MOI.isempty(model)
48+
MOIU.loadfromstring!(model, """
49+
variables: x
50+
minobjective: 2.0x + -1.0
51+
c1: x >= 1.5
52+
""")
53+
x = MOI.get(model, MOI.VariableIndex, "x")
54+
test_model_solution(model, config;
55+
objective_value = 2.0,
56+
variable_primal = [(x, 1.5)]
57+
)
58+
if config.solve
59+
@test MOI.get(model, MOI.ObjectiveBound()) <= 2.0
60+
end
61+
end
62+
63+
@testset "Max LP with constant" begin
64+
MOI.empty!(model)
65+
@test MOI.isempty(model)
66+
MOIU.loadfromstring!(model, """
67+
variables: x
68+
maxobjective: 2.0x + 1.0
69+
c1: x <= 1.5
70+
""")
71+
x = MOI.get(model, MOI.VariableIndex, "x")
72+
test_model_solution(model, config;
73+
objective_value = 4.0,
74+
variable_primal = [(x, 1.5)]
75+
)
76+
if config.solve
77+
@test MOI.get(model, MOI.ObjectiveBound()) >= 4.0
78+
end
79+
end
80+
end
81+
unittests["solve_objbound_edge_cases"] = solve_objbound_edge_cases

src/Test/UnitTests/unit_tests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,6 @@ include("objectives.jl")
9898
include("constraints.jl")
9999
include("basic_constraint_tests.jl")
100100
include("modifications.jl")
101+
include("solve.jl")
101102

102103
@moitestset unit

src/Utilities/mockoptimizer.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ mutable struct MockOptimizer{MT<:MOI.ModelLike} <: MOI.AbstractOptimizer
2828
resultcount::Int
2929
evalobjective::Bool # Computes ObjectiveValue by evaluation ObjectiveFunction with VariablePrimal
3030
objectivevalue::Float64
31+
objectivebound::Float64 # set this using MOI.set!(model, MOI.ObjectiveBound(), value)
3132
primalstatus::MOI.ResultStatusCode
3233
dualstatus::MOI.ResultStatusCode
3334
varprimal::Dict{MOI.VariableIndex,Float64}
@@ -57,6 +58,7 @@ MockOptimizer(inner_model::MOI.ModelLike; needsallocateload=false, evalobjective
5758
0,
5859
evalobjective,
5960
NaN,
61+
NaN,
6062
MOI.UnknownResultStatus,
6163
MOI.UnknownResultStatus,
6264
Dict{MOI.VariableIndex,Float64}(),
@@ -180,6 +182,13 @@ MOI.get(mock::MockOptimizer, attr::MOI.AbstractConstraintAttribute, idx::MOI.Con
180182
MOI.get(mock::MockOptimizer, ::MOI.ConstraintDual, idx::MOI.ConstraintIndex) = mock.condual[xor_index(idx)]
181183
MOI.get(mock::MockOptimizer, ::MockConstraintAttribute, idx::MOI.ConstraintIndex) = mock.conattribute[xor_index(idx)]
182184

185+
MOI.supports(mock::MockOptimizer, ::MOI.ObjectiveBound) = true
186+
MOI.canget(mock::MockOptimizer, ::MOI.ObjectiveBound) = !isnan(mock.objectivebound)
187+
MOI.get(mock::MockOptimizer, ::MOI.ObjectiveBound) = mock.objectivebound
188+
function MOI.set!(mock::MockOptimizer, ::MOI.ObjectiveBound, value::Float64)
189+
mock.objectivebound = value
190+
end
191+
183192
function MOI.empty!(mock::MockOptimizer)
184193
MOI.empty!(mock.inner_model)
185194
mock.attribute = 0
@@ -191,6 +200,7 @@ function MOI.empty!(mock::MockOptimizer)
191200
mock.terminationstatus = MOI.Success
192201
mock.resultcount = 0
193202
mock.objectivevalue = NaN
203+
mock.objectivebound = NaN
194204
mock.primalstatus = MOI.UnknownResultStatus
195205
mock.dualstatus = MOI.UnknownResultStatus
196206
mock.varprimal = Dict{MOI.VariableIndex,Float64}()
@@ -206,6 +216,7 @@ function MOI.isempty(mock::MockOptimizer)
206216
!mock.solved && !mock.hasprimal && !mock.hasdual &&
207217
mock.terminationstatus == MOI.Success &&
208218
mock.resultcount == 0 && isnan(mock.objectivevalue) &&
219+
isnan(mock.objectivebound) &&
209220
mock.primalstatus == MOI.UnknownResultStatus &&
210221
mock.dualstatus == MOI.UnknownResultStatus
211222
end

test/Test/unit.jl

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ end
2121
"solve_qcp_edge_cases",
2222
"solve_affine_deletion_edge_cases",
2323
"solve_duplicate_terms_obj",
24-
"solve_integer_edge_cases"
24+
"solve_integer_edge_cases",
25+
"solve_objbound_edge_cases"
2526
])
2627

2728
@testset "solve_blank_obj" begin
@@ -209,6 +210,28 @@ end
209210
)
210211
MOIT.solve_integer_edge_cases(mock, config)
211212
end
213+
@testset "solve_objbound_edge_cases" begin
214+
MOIU.set_mock_optimize!(mock,
215+
(mock::MOIU.MockOptimizer) -> begin
216+
MOI.set!(mock, MOI.ObjectiveBound(), 3.0)
217+
MOIU.mock_optimize!(mock, MOI.Success, (MOI.FeasiblePoint, [2.0]))
218+
end,
219+
(mock::MOIU.MockOptimizer) -> begin
220+
MOI.set!(mock, MOI.ObjectiveBound(), 3.0)
221+
MOIU.mock_optimize!(mock, MOI.Success, (MOI.FeasiblePoint, [1.0]))
222+
end,
223+
(mock::MOIU.MockOptimizer) -> begin
224+
MOI.set!(mock, MOI.ObjectiveBound(), 2.0)
225+
MOIU.mock_optimize!(mock, MOI.Success, (MOI.FeasiblePoint, [1.5]))
226+
end,
227+
(mock::MOIU.MockOptimizer) -> begin
228+
MOI.set!(mock, MOI.ObjectiveBound(), 4.0)
229+
MOIU.mock_optimize!(mock, MOI.Success, (MOI.FeasiblePoint, [1.5]))
230+
end
231+
)
232+
MOIT.solve_objbound_edge_cases(mock, config)
233+
end
234+
212235
end
213236

214237
@testset "modifications" begin

0 commit comments

Comments
 (0)