Skip to content

Commit 3633e2a

Browse files
committed
Finish Bridges
1 parent 52f379f commit 3633e2a

20 files changed

+933
-931
lines changed

test/Bridges/Bridges.jl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
include("bridge.jl")
2-
include("bridgeoptimizer.jl")
3-
include("singlebridgeoptimizer.jl")
4-
include("lazybridgeoptimizer.jl")
1+
using Test
2+
3+
@testset "BridgeOptimizer" begin
4+
include("bridgeoptimizer.jl")
5+
end
6+
@testset "LazyBridgeOptimizer" begin
7+
include("lazybridgeoptimizer.jl")
8+
end
59
@testset "Separate bridges" begin
610
include("flip_sign_bridge.jl")
711
include("vectorizebridge.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: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
using Test
2+
3+
using MathOptInterface
4+
const MOI = MathOptInterface
5+
const MOIU = MathOptInterface.Utilities
6+
7+
include("simple_model.jl")
8+
19
# We need to test this in a module at the top level because it can't be defined
210
# in a testset. If it runs without error, then we're okay.
311
module TestExternalBridge

test/Bridges/flip_sign_bridge.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
include("simple_model.jl")
2+
13
mock = MOIU.MockOptimizer(SimpleModel{Float64}())
24
config = MOIT.TestConfig()
35
config_with_basis = MOIT.TestConfig(basis = true)

test/Bridges/functionize_bridge.jl

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
@testset "Scalar functionize" begin
2+
MOI.empty!(mock)
3+
bridged_mock = MOIB.ScalarFunctionize{Float64}(mock)
4+
x = MOI.add_variable(bridged_mock)
5+
y = MOI.add_variable(bridged_mock)
6+
sx = MOI.SingleVariable(x)
7+
sy = MOI.SingleVariable(y)
8+
ci = MOI.add_constraint(bridged_mock, sx, MOI.GreaterThan(0.0))
9+
@test MOI.get(bridged_mock, MOI.ConstraintFunction(), ci) sx
10+
MOI.set(bridged_mock, MOI.ConstraintFunction(), ci, sy)
11+
@test MOI.get(bridged_mock, MOI.ConstraintFunction(), ci) sy
12+
@test MOI.get(bridged_mock, MOI.ConstraintSet(), ci) == MOI.GreaterThan(0.0)
13+
MOI.set(bridged_mock, MOI.ConstraintSet(), ci, MOI.GreaterThan(1.0))
14+
@test MOI.get(bridged_mock, MOI.ConstraintSet(), ci) == MOI.GreaterThan(1.0)
15+
test_delete_bridge(bridged_mock, ci, 2, ((MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}, 0),))
16+
17+
MOIT.basic_constraint_tests(bridged_mock, config,
18+
include=[(F, S) for
19+
F in [MOI.SingleVariable],
20+
S in [MOI.GreaterThan{Float64},
21+
MOI.LessThan{Float64}]
22+
])
23+
24+
for T in [Int, Float64], S in [MOI.GreaterThan{T}, MOI.LessThan{T}]
25+
@test MOIB.added_constraint_types(MOIB.ScalarFunctionizeBridge{T, S}) ==
26+
[(MOI.ScalarAffineFunction{T}, S)]
27+
end
28+
29+
30+
@testset "linear2" begin
31+
MOI.empty!(bridged_mock)
32+
MOIU.set_mock_optimize!(mock,
33+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1, 0],
34+
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-1],
35+
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [0, 1],
36+
con_basis =
37+
[(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.NONBASIC],
38+
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.NONBASIC]]))
39+
MOIT.linear2test(bridged_mock, config_with_basis)
40+
41+
for (i, ci) in enumerate(MOI.get(
42+
bridged_mock,
43+
MOI.ListOfConstraintIndices{MOI.SingleVariable,
44+
MOI.GreaterThan{Float64}}()))
45+
test_delete_bridge(bridged_mock, ci, 2,
46+
((MOI.ScalarAffineFunction{Float64},
47+
MOI.GreaterThan{Float64}, 0),),
48+
num_bridged = 3 - i)
49+
end
50+
end
51+
end
52+
53+
@testset "Vector functionize" begin
54+
MOI.empty!(mock)
55+
bridged_mock = MOIB.VectorFunctionize{Float64}(mock)
56+
x = MOI.add_variable(bridged_mock)
57+
y = MOI.add_variable(bridged_mock)
58+
z = MOI.add_variable(bridged_mock)
59+
v1 = MOI.VectorOfVariables([x,y,z])
60+
v2 = MOI.VectorOfVariables([x,y,y])
61+
ci = MOI.add_constraint(bridged_mock, v1, MOI.PowerCone(0.1))
62+
@test MOI.get(bridged_mock, MOI.ConstraintFunction(), ci) v1
63+
MOI.set(bridged_mock, MOI.ConstraintFunction(), ci, v2)
64+
@test MOI.get(bridged_mock, MOI.ConstraintFunction(), ci) v2
65+
@test MOI.get(bridged_mock, MOI.ConstraintSet(), ci) == MOI.PowerCone(0.1)
66+
MOI.set(bridged_mock, MOI.ConstraintSet(), ci, MOI.PowerCone(0.2))
67+
@test MOI.get(bridged_mock, MOI.ConstraintSet(), ci) == MOI.PowerCone(0.2)
68+
test_delete_bridge(bridged_mock, ci, 3, ((MOI.VectorAffineFunction{Float64}, MOI.Nonnegatives, 0),))
69+
70+
MOIT.basic_constraint_tests(bridged_mock, config,
71+
include=[(F, S) for
72+
F in [MOI.VectorOfVariables],
73+
S in [MOI.Nonnegatives,
74+
MOI.Nonpositives]
75+
])
76+
77+
for T in [Int, Float64], S in [MOI.Nonnegatives, MOI.Nonpositives]
78+
@test MOIB.added_constraint_types(MOIB.VectorFunctionizeBridge{T, S}) ==
79+
[(MOI.VectorAffineFunction{T}, S)]
80+
end
81+
82+
@testset "lin1v" begin
83+
mock.optimize! = (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
84+
mock, [1.0, 0.0, 2.0],
85+
(MOI.VectorAffineFunction{Float64}, MOI.Nonnegatives) => [[0, 2, 0]],
86+
(MOI.VectorAffineFunction{Float64}, MOI.Zeros) => [[-3, -1]])
87+
MOIT.lin1vtest(bridged_mock, config)
88+
ci = first(MOI.get(
89+
bridged_mock,
90+
MOI.ListOfConstraintIndices{MOI.VectorOfVariables,
91+
MOI.Nonnegatives}()))
92+
test_delete_bridge(bridged_mock, ci, 3,
93+
((MOI.VectorAffineFunction{Float64},
94+
MOI.Nonnegatives, 0),))
95+
end
96+
end

test/Bridges/geomeanbridge.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@testset "GeoMean" begin
2+
mock.optimize! = (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [ones(4); 2; 2; 2])
3+
bridged_mock = MOIB.GeoMean{Float64}(mock)
4+
MOIT.geomean1vtest(bridged_mock, config)
5+
MOIT.geomean1ftest(bridged_mock, config)
6+
# Dual is not yet implemented for GeoMean bridge
7+
ci = first(MOI.get(bridged_mock, MOI.ListOfConstraintIndices{MOI.VectorAffineFunction{Float64}, MOI.GeometricMeanCone}()))
8+
test_delete_bridge(bridged_mock, ci, 4, ((MOI.VectorAffineFunction{Float64}, MOI.RotatedSecondOrderCone, 0),
9+
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}, 1)))
10+
end

test/Bridges/intervalbridge.jl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
@testset "Interval" begin
2+
bridged_mock = MOIB.SplitInterval{Float64}(mock)
3+
MOIT.basic_constraint_tests(bridged_mock, config,
4+
include=[(MOI.SingleVariable,
5+
MOI.Interval{Float64}),
6+
(MOI.ScalarAffineFunction{Float64},
7+
MOI.Interval{Float64}),
8+
(MOI.ScalarQuadraticFunction{Float64},
9+
MOI.Interval{Float64})])
10+
MOIU.set_mock_optimize!(mock,
11+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [5.0, 5.0], con_basis =
12+
[(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [MOI.BASIC],
13+
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.NONBASIC],
14+
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC]],
15+
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [0],
16+
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-1]),
17+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [2.5, 2.5], con_basis =
18+
[(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [MOI.NONBASIC],
19+
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.BASIC],
20+
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC]],
21+
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [1],
22+
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [0]),
23+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1.0, 1.0], con_basis =
24+
[(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [MOI.NONBASIC],
25+
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.BASIC],
26+
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC]]),
27+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [6.0, 6.0], con_basis =
28+
[(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [MOI.BASIC],
29+
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.NONBASIC],
30+
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC]]))
31+
MOIT.linear10test(bridged_mock, config_with_basis)
32+
MOIU.set_mock_optimize!(mock,
33+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0.0, 0.0], con_basis =
34+
[(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [MOI.BASIC],
35+
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.BASIC],
36+
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.NONBASIC, MOI.NONBASIC]],
37+
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [0],
38+
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [0]))
39+
MOIT.linear10btest(bridged_mock, config_with_basis)
40+
41+
ci = first(MOI.get(bridged_mock, MOI.ListOfConstraintIndices{MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}}()))
42+
newf = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([1.0, -1.0], MOI.get(bridged_mock, MOI.ListOfVariableIndices())), 0.0)
43+
MOI.set(bridged_mock, MOI.ConstraintFunction(), ci, newf)
44+
@test MOI.get(bridged_mock, MOI.ConstraintFunction(), ci) newf
45+
test_delete_bridge(bridged_mock, ci, 2, ((MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}, 0),
46+
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}, 0)))
47+
end

0 commit comments

Comments
 (0)