Skip to content

Commit 14d5af5

Browse files
authored
[Bridges] restrict when ToScalarNonlinearBridge applies and simplify tests (#2835)
1 parent 8b6e9ef commit 14d5af5

File tree

4 files changed

+64
-125
lines changed

4 files changed

+64
-125
lines changed

src/Bridges/Objective/bridges/FunctionConversionBridge.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ function supports_objective_function(
4545
::Type{<:FunctionConversionBridge{T,F}},
4646
::Type{G},
4747
) where {T,F,G<:MOI.AbstractFunction}
48-
return isfinite(MOI.Bridges.Constraint.conversion_cost(F, G))
48+
return MOI.Utilities.is_coefficient_type(G, T) &&
49+
isfinite(MOI.Bridges.Constraint.conversion_cost(F, G))
4950
end
5051

5152
function MOI.Bridges.bridging_cost(

test/Bridges/Constraint/ScalarFunctionizeBridge.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,20 @@ function test_approx_convert(T = Float64)
364364
return
365365
end
366366

367+
function test_supports_ScalarNonlinearFunction()
368+
for T in (Int, Float64)
369+
model = MOI.instantiate(MOI.Utilities.Model{T}; with_bridge_type = T)
370+
for (F, flag) in [
371+
MOI.ScalarNonlinearFunction => true,
372+
MOI.ScalarAffineFunction{Float64} => (T == Float64),
373+
MOI.ScalarAffineFunction{Int} => (T == Int),
374+
]
375+
@test MOI.supports_constraint(model, F, MOI.EqualTo{T}) == flag
376+
end
377+
end
378+
return
379+
end
380+
367381
end # module
368382

369383
TestConstraintFunctionize.runtests()

test/Bridges/Objective/FunctionConversionBridge.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ struct VariableDifference <: MOI.AbstractScalarFunction
2828
y::MOI.VariableIndex
2929
end
3030

31+
function MOI.Utilities.is_coefficient_type(
32+
::Type{VariableDifference},
33+
::Type{T},
34+
) where {T}
35+
return true
36+
end
37+
3138
function MOI.Bridges.Constraint.conversion_cost(
3239
::Type{<:MOI.ScalarAffineFunction},
3340
::Type{VariableDifference},

test/Bridges/Objective/ToScalarNonlinearBridge.jl

Lines changed: 41 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -21,140 +21,57 @@ function runtests()
2121
return
2222
end
2323

24-
include("../utilities.jl")
25-
26-
function test_solve_singlevariable_obj()
27-
mock = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}())
28-
model = MOI.Bridges.Objective.ToScalarNonlinear{Float64}(mock)
29-
MOI.Utilities.set_mock_optimize!(
30-
mock,
31-
(mock::MOI.Utilities.MockOptimizer) ->
32-
MOI.Utilities.mock_optimize!(mock, [1.0], MOI.FEASIBLE_POINT),
33-
)
34-
MOI.Test.test_objective_ObjectiveFunction_duplicate_terms(
35-
model,
36-
MOI.Test.Config(;
37-
exclude = Any[MOI.DualObjectiveValue, MOI.ConstraintDual],
38-
),
39-
)
40-
@test MOI.get(mock, MOI.ObjectiveFunctionType()) ==
41-
MOI.ScalarNonlinearFunction
42-
@test MOI.get(model, MOI.ObjectiveFunctionType()) ==
43-
MOI.ScalarAffineFunction{Float64}
44-
@test MOI.get(mock, MOI.ObjectiveSense()) == MOI.MIN_SENSE
45-
@test MOI.get(model, MOI.ObjectiveSense()) == MOI.MIN_SENSE
46-
vis = MOI.get(model, MOI.ListOfVariableIndices())
47-
func = 3.0 * vis[1] + 0.0
48-
49-
@test MOI.get(
50-
model,
51-
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
52-
) func
53-
MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)
54-
@test MOI.get(mock, MOI.ObjectiveSense()) == MOI.MAX_SENSE
55-
@test MOI.get(model, MOI.ObjectiveSense()) == MOI.MAX_SENSE
56-
57-
_test_delete_objective(model, 1, tuple())
58-
return
59-
end
60-
61-
function test_solve_result_index()
62-
mock = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}())
63-
model = MOI.Bridges.Objective.ToScalarNonlinear{Float64}(mock)
64-
MOI.Utilities.set_mock_optimize!(
65-
mock,
66-
(mock::MOI.Utilities.MockOptimizer) -> MOI.Utilities.mock_optimize!(
67-
mock,
68-
MOI.OPTIMAL,
69-
(MOI.FEASIBLE_POINT, [1.0]),
70-
MOI.FEASIBLE_POINT,
71-
(MOI.VariableIndex, MOI.GreaterThan{Float64}) => [1.0],
72-
),
73-
)
74-
MOI.Test.test_solve_result_index(
75-
model,
76-
MOI.Test.Config(;
77-
exclude = Any[MOI.DualObjectiveValue, MOI.ConstraintDual],
78-
),
79-
)
80-
81-
return
82-
end
83-
8424
function test_runtests()
8525
MOI.Bridges.runtests(
8626
MOI.Bridges.Objective.ToScalarNonlinearBridge,
87-
model -> begin
88-
x = MOI.add_variable(model)
89-
aff = MOI.ScalarAffineFunction(
90-
MOI.ScalarAffineTerm.([2.0], [x]),
91-
1.0,
92-
)
93-
MOI.set(
94-
model,
95-
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
96-
aff,
97-
)
98-
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
99-
end,
100-
model -> begin
101-
x = MOI.add_variable(model)
102-
exp = MOI.ScalarNonlinearFunction(
103-
:+,
104-
[
105-
MOI.ScalarNonlinearFunction(
106-
:*,
107-
[2.0, MOI.VariableIndex(1)],
108-
),
109-
1.0,
110-
],
111-
)
112-
MOI.set(
113-
model,
114-
MOI.ObjectiveFunction{MOI.ScalarNonlinearFunction}(),
115-
exp,
116-
)
117-
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
118-
end,
27+
"""
28+
variables: x
29+
minobjective: 2.0 * x + 1.0
30+
""",
31+
"""
32+
variables: x
33+
minobjective: ScalarNonlinearFunction(2.0 * x + 1.0)
34+
""",
35+
)
36+
MOI.Bridges.runtests(
37+
MOI.Bridges.Objective.ToScalarNonlinearBridge,
38+
"""
39+
variables: x
40+
maxobjective: 2.0 * x + 1.0
41+
""",
42+
"""
43+
variables: x
44+
maxobjective: ScalarNonlinearFunction(2.0 * x + 1.0)
45+
""",
11946
)
12047
MOI.Bridges.runtests(
12148
MOI.Bridges.Objective.ToScalarNonlinearBridge,
122-
model -> begin
123-
x = MOI.add_variable(model)
124-
aff = MOI.ScalarAffineFunction(
125-
MOI.ScalarAffineTerm.([2.0], [x]),
126-
1.0,
127-
)
128-
MOI.set(
129-
model,
130-
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
131-
aff,
132-
)
133-
MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)
134-
end,
135-
model -> begin
136-
x = MOI.add_variable(model)
137-
exp = MOI.ScalarNonlinearFunction(
138-
:+,
139-
[
140-
MOI.ScalarNonlinearFunction(
141-
:*,
142-
[2.0, MOI.VariableIndex(1)],
143-
),
144-
1.0,
145-
],
146-
)
147-
MOI.set(
148-
model,
149-
MOI.ObjectiveFunction{MOI.ScalarNonlinearFunction}(),
150-
exp,
151-
)
152-
MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)
153-
end,
49+
"""
50+
variables: x, y
51+
minobjective: 1.0 * x * x + 2.0 * x * y + 3.0 * y + 4.0
52+
""",
53+
"""
54+
variables: x, y
55+
minobjective: ScalarNonlinearFunction(1.0 * x * x + 2.0 * x * y + 3.0 * y + 4.0)
56+
""",
15457
)
15558
return
15659
end
15760

61+
function test_supports()
62+
for T in (Int, Float64)
63+
model = MOI.instantiate(MOI.Utilities.Model{T}; with_bridge_type = T)
64+
for (F, flag) in [
65+
MOI.ScalarNonlinearFunction => true,
66+
MOI.ScalarAffineFunction{Float64} => (T == Float64),
67+
MOI.ScalarAffineFunction{Int} => (T == Int),
68+
]
69+
@test MOI.supports(model, MOI.ObjectiveFunction{F}()) == flag
70+
end
71+
end
72+
return
73+
end
74+
15875
end # module
15976

16077
TestObjectiveToScalarNonlinear.runtests()

0 commit comments

Comments
 (0)