Skip to content

Commit 9970dbd

Browse files
authored
Merge pull request #715 from JuliaOpt/bl/improve_tests
Refactor tests
2 parents 7337108 + 3633e2a commit 9970dbd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2458
-2299
lines changed

test/Bridges/Bridges.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using Test
2+
3+
@testset "BridgeOptimizer" begin
4+
include("bridgeoptimizer.jl")
5+
end
6+
@testset "LazyBridgeOptimizer" begin
7+
include("lazybridgeoptimizer.jl")
8+
end
9+
@testset "Separate bridges" begin
10+
include("flip_sign_bridge.jl")
11+
include("vectorizebridge.jl")
12+
include("scalarizebridge.jl")
13+
include("slackbridge.jl")
14+
include("functionize_bridge.jl")
15+
include("intervalbridge.jl")
16+
include("rsocbridge.jl")
17+
include("quadtosocbridge.jl")
18+
include("geomeanbridge.jl")
19+
include("squarepsdbridge.jl")
20+
include("detbridge.jl")
21+
include("soctopsdbridge.jl")
22+
end
23+
include("external.jl")

test/Bridges/bridgeoptimizer.jl

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using Test
2+
3+
using MathOptInterface
4+
const MOI = MathOptInterface
5+
const MOIT = MathOptInterface.Test
6+
const MOIU = MathOptInterface.Utilities
7+
const MOIB = MathOptInterface.Bridges
8+
9+
include("simple_model.jl")
10+
include("utilities.jl")
11+
12+
struct UnknownConstraintAttribute <: MOI.AbstractConstraintAttribute end
13+
MOI.is_set_by_optimize(::UnknownConstraintAttribute) = true
14+
15+
mock = MOIU.MockOptimizer(SimpleModel{Float64}())
16+
bridged_mock = MOIB.SplitInterval{Float64}(mock)
17+
18+
@testset "Unsupported constraint attribute" begin
19+
attr = UnknownConstraintAttribute()
20+
err = ArgumentError(
21+
"Constraint bridge of type `MathOptInterface.Bridges.SplitIntervalBridge{Float64,MathOptInterface.SingleVariable}` " *
22+
"does not support accessing the attribute `$attr`.")
23+
x = MOI.add_variable(bridged_mock)
24+
ci = MOI.add_constraint(bridged_mock, MOI.SingleVariable(x),
25+
MOI.Interval(0.0, 1.0))
26+
@test_throws err MOI.get(bridged_mock, attr, ci)
27+
end
28+
29+
@testset "Issue #453" begin
30+
MOI.empty!(bridged_mock)
31+
MOIU.loadfromstring!(bridged_mock, """
32+
variables: x
33+
maxobjective: 3.0x
34+
c: 2.0x in Interval(1.0, 4.0)
35+
d: x in LessThan(1.5)
36+
""")
37+
x = MOI.get(bridged_mock, MOI.VariableIndex, "x")
38+
@test isa(x, MOI.VariableIndex)
39+
c1 = MOI.get(bridged_mock, MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}}, "c")
40+
@test isa(c1, MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}})
41+
c2 = MOI.get(bridged_mock, MOI.ConstraintIndex, "c")
42+
@test c1 == c2
43+
d1 = MOI.get(bridged_mock, MOI.ConstraintIndex{MOI.SingleVariable, MOI.LessThan{Float64}}, "d")
44+
@test isa(d1, MOI.ConstraintIndex{MOI.SingleVariable, MOI.LessThan{Float64}})
45+
d2 = MOI.get(bridged_mock, MOI.ConstraintIndex, "d")
46+
@test d1 == d2
47+
end
48+
49+
MOI.empty!(bridged_mock)
50+
51+
@testset "Name test" begin
52+
MOIT.nametest(bridged_mock)
53+
end
54+
55+
@testset "Copy test" begin
56+
MOIT.failcopytestc(bridged_mock)
57+
MOIT.failcopytestia(bridged_mock)
58+
MOIT.failcopytestva(bridged_mock)
59+
MOIT.failcopytestca(bridged_mock)
60+
MOIT.copytest(bridged_mock, SimpleModel{Float64}())
61+
end
62+
63+
@testset "Custom test" begin
64+
model = MOIB.SplitInterval{Int}(SimpleModel{Int}())
65+
@test !MOIB.supports_bridging_constraint(model, MOI.VectorAffineFunction{Float64}, MOI.Interval{Float64})
66+
67+
x, y = MOI.add_variables(model, 2)
68+
@test MOI.get(model, MOI.NumberOfVariables()) == 2
69+
70+
f1 = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(3, x)], 7)
71+
c1 = MOI.add_constraint(model, f1, MOI.Interval(-1, 1))
72+
73+
@test MOI.get(model, MOI.ListOfConstraints()) == [(MOI.ScalarAffineFunction{Int},MOI.Interval{Int})]
74+
test_noc(model, MOI.ScalarAffineFunction{Int}, MOI.GreaterThan{Int}, 0)
75+
test_noc(model, MOI.ScalarAffineFunction{Int}, MOI.Interval{Int}, 1)
76+
@test (@inferred MOI.get(model, MOI.ListOfConstraintIndices{MOI.ScalarAffineFunction{Int},MOI.Interval{Int}}())) == [c1]
77+
78+
f2 = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([2, -1], [x, y]), 2)
79+
c2 = MOI.add_constraint(model, f1, MOI.GreaterThan(-2))
80+
81+
@test MOI.get(model, MOI.ListOfConstraints()) == [(MOI.ScalarAffineFunction{Int},MOI.GreaterThan{Int}), (MOI.ScalarAffineFunction{Int},MOI.Interval{Int})]
82+
test_noc(model, MOI.ScalarAffineFunction{Int}, MOI.GreaterThan{Int}, 1)
83+
test_noc(model, MOI.ScalarAffineFunction{Int}, MOI.Interval{Int}, 1)
84+
@test (@inferred MOI.get(model, MOI.ListOfConstraintIndices{MOI.ScalarAffineFunction{Int},MOI.Interval{Int}}())) == [c1]
85+
@test (@inferred MOI.get(model, MOI.ListOfConstraintIndices{MOI.ScalarAffineFunction{Int},MOI.GreaterThan{Int}}())) == [c2]
86+
87+
@test MOI.is_valid(model, c2)
88+
MOI.delete(model, c2)
89+
90+
@test MOI.get(model, MOI.ListOfConstraints()) == [(MOI.ScalarAffineFunction{Int},MOI.Interval{Int})]
91+
test_noc(model, MOI.ScalarAffineFunction{Int}, MOI.GreaterThan{Int}, 0)
92+
test_noc(model, MOI.ScalarAffineFunction{Int}, MOI.Interval{Int}, 1)
93+
@test (@inferred MOI.get(model, MOI.ListOfConstraintIndices{MOI.ScalarAffineFunction{Int},MOI.Interval{Int}}())) == [c1]
94+
end
95+
96+
@testset "Continuous Linear" begin
97+
exclude = ["partial_start"] # VariablePrimalStart not supported.
98+
MOIT.contlineartest(bridged_mock, MOIT.TestConfig(solve=false), exclude)
99+
end

test/Bridges/detbridge.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
@testset "LogDet" begin
2+
bridged_mock = MOIB.LogDet{Float64}(mock)
3+
mock.optimize! = (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 1, 0, 1, 1, 0, 1, 0, 0, 1])
4+
MOIT.logdett1vtest(bridged_mock, config)
5+
MOIT.logdett1ftest(bridged_mock, config)
6+
# Dual is not yet implemented for LogDet bridge
7+
ci = first(MOI.get(bridged_mock, MOI.ListOfConstraintIndices{MOI.VectorAffineFunction{Float64}, MOI.LogDetConeTriangle}()))
8+
test_delete_bridge(bridged_mock, ci, 5, ((MOI.VectorAffineFunction{Float64}, MOI.ExponentialCone, 0), (MOI.VectorAffineFunction{Float64}, MOI.PositiveSemidefiniteConeTriangle, 0)))
9+
end
10+
11+
@testset "RootDet" begin
12+
bridged_mock = MOIB.RootDet{Float64}(mock)
13+
mock.optimize! = (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1, 1, 0, 1, 1, 0, 1])
14+
MOIT.rootdett1vtest(bridged_mock, config)
15+
MOIT.rootdett1ftest(bridged_mock, config)
16+
# Dual is not yet implemented for RootDet bridge
17+
ci = first(MOI.get(bridged_mock, MOI.ListOfConstraintIndices{MOI.VectorAffineFunction{Float64}, MOI.RootDetConeTriangle}()))
18+
test_delete_bridge(bridged_mock, ci, 4, ((MOI.VectorAffineFunction{Float64}, MOI.RotatedSecondOrderCone, 0),
19+
(MOI.VectorAffineFunction{Float64}, MOI.GeometricMeanCone, 0),
20+
(MOI.VectorAffineFunction{Float64}, MOI.PositiveSemidefiniteConeTriangle, 0)))
21+
end

test/Bridges/external.jl

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using Test
2+
3+
using MathOptInterface
4+
const MOI = MathOptInterface
5+
const MOIU = MathOptInterface.Utilities
6+
7+
include("simple_model.jl")
8+
9+
# We need to test this in a module at the top level because it can't be defined
10+
# in a testset. If it runs without error, then we're okay.
11+
module TestExternalBridge
12+
using MathOptInterface
13+
14+
struct StrictlyGreaterThan <: MathOptInterface.AbstractScalarSet end
15+
struct StrictlyGreaterBridge{T} <: MathOptInterface.Bridges.AbstractBridge end
16+
17+
function StrictlyGreaterBridge(
18+
model,
19+
func::MathOptInterface.SingleVariable,
20+
set::StrictlyGreaterThan)
21+
return StrictlyGreaterBridge{Float64}()
22+
end
23+
24+
function MathOptInterface.supports_constraint(
25+
::Type{StrictlyGreaterBridge{T}},
26+
::Type{MathOptInterface.SingleVariable},
27+
::Type{StrictlyGreaterThan}) where {T}
28+
return true
29+
end
30+
31+
function MathOptInterface.Bridges.added_constraint_types(
32+
::Type{StrictlyGreaterBridge{T}},
33+
::Type{MathOptInterface.SingleVariable},
34+
::Type{StrictlyGreaterThan}) where {T}
35+
return [(
36+
MathOptInterface.SingleVariable,
37+
MathOptInterface.GreaterThan{T}
38+
)]
39+
end
40+
41+
MathOptInterface.Bridges.@bridge(StrictlyGreater, StrictlyGreaterBridge,
42+
(StrictlyGreaterThan, ),
43+
(),
44+
(),
45+
(),
46+
(MathOptInterface.SingleVariable, ),
47+
(),
48+
(),
49+
()
50+
)
51+
end
52+
53+
@testset "@bridge with external components" begin
54+
model = SimpleModel{Float64}();
55+
@test MOI.supports_constraint(model, MOI.SingleVariable, MOI.GreaterThan{Float64})
56+
@test !MOI.supports_constraint(model, MOI.SingleVariable, TestExternalBridge.StrictlyGreaterThan)
57+
58+
bridge = TestExternalBridge.StrictlyGreater{Float64}(model);
59+
@test MOI.supports_constraint(bridge, MOI.SingleVariable, MOI.GreaterThan{Float64})
60+
@test MOI.supports_constraint(bridge, MOI.SingleVariable, TestExternalBridge.StrictlyGreaterThan)
61+
end

test/Bridges/flip_sign_bridge.jl

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
include("simple_model.jl")
2+
3+
mock = MOIU.MockOptimizer(SimpleModel{Float64}())
4+
config = MOIT.TestConfig()
5+
config_with_basis = MOIT.TestConfig(basis = true)
6+
7+
@testset "GreaterToLess" begin
8+
bridged_mock = MOIB.GreaterToLess{Float64}(mock)
9+
10+
MOIU.set_mock_optimize!(mock,
11+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 0]),
12+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, 0]),
13+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, -100]))
14+
MOIT.linear6test(bridged_mock, config)
15+
16+
ci = first(MOI.get(bridged_mock, MOI.ListOfConstraintIndices{MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}}()))
17+
test_delete_bridge(bridged_mock, ci, 2,
18+
((MOI.ScalarAffineFunction{Float64},
19+
MOI.LessThan{Float64}, 1),))
20+
end
21+
22+
@testset "LessToGreater" begin
23+
bridged_mock = MOIB.LessToGreater{Float64}(mock)
24+
25+
MOIU.set_mock_optimize!(mock,
26+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
27+
MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0]),
28+
MOI.FEASIBLE_POINT,
29+
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [1.0]
30+
),
31+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
32+
MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [2.0]),
33+
MOI.FEASIBLE_POINT,
34+
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [1.0]
35+
)
36+
)
37+
MOIT.solve_set_scalaraffine_lessthan(bridged_mock, config)
38+
39+
MOIU.set_mock_optimize!(mock,
40+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
41+
MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0]),
42+
MOI.FEASIBLE_POINT,
43+
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [1.0]
44+
),
45+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
46+
MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [0.5]),
47+
MOI.FEASIBLE_POINT,
48+
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [0.5]
49+
)
50+
)
51+
MOIT.solve_coef_scalaraffine_lessthan(bridged_mock, config)
52+
53+
ci = first(MOI.get(bridged_mock, MOI.ListOfConstraintIndices{MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}}()))
54+
test_delete_bridge(bridged_mock, ci, 1,
55+
((MOI.ScalarAffineFunction{Float64},
56+
MOI.GreaterThan{Float64}, 0),))
57+
end
58+
59+
@testset "NonnegToNonpos" begin
60+
bridged_mock = MOIB.NonnegToNonpos{Float64}(mock)
61+
62+
MOIU.set_mock_optimize!(mock,
63+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 0]),
64+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, 0]),
65+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, -100]))
66+
MOIT.linear7test(bridged_mock, config)
67+
68+
ci = first(MOI.get(bridged_mock, MOI.ListOfConstraintIndices{MOI.VectorAffineFunction{Float64}, MOI.Nonnegatives}()))
69+
test_delete_bridge(bridged_mock, ci, 2,
70+
((MOI.VectorAffineFunction{Float64},
71+
MOI.Nonpositives, 1),))
72+
end
73+
74+
@testset "NonposToNonneg" begin
75+
bridged_mock = MOIB.NonposToNonneg{Float64}(mock)
76+
77+
MOIU.set_mock_optimize!(mock,
78+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 0]),
79+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, 0]),
80+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, -100]))
81+
MOIT.linear7test(bridged_mock, config)
82+
83+
MOIU.set_mock_optimize!(mock,
84+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
85+
MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [0.0, 0.0])
86+
),
87+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock,
88+
MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0, 0.75])
89+
)
90+
)
91+
MOIT.solve_const_vectoraffine_nonpos(bridged_mock, config)
92+
93+
MOIU.set_mock_optimize!(mock,
94+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
95+
mock, MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [0.5])
96+
),
97+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
98+
mock, MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [0.25])
99+
)
100+
)
101+
MOIT.solve_multirow_vectoraffine_nonpos(bridged_mock, config)
102+
103+
ci = first(MOI.get(bridged_mock, MOI.ListOfConstraintIndices{MOI.VectorAffineFunction{Float64}, MOI.Nonpositives}()))
104+
test_delete_bridge(bridged_mock, ci, 1,
105+
((MOI.VectorAffineFunction{Float64},
106+
MOI.Nonnegatives, 0),))
107+
end

0 commit comments

Comments
 (0)