Skip to content

Commit ede6d1c

Browse files
blegatodow
andauthored
Run all tests against bridged SDPA model (#2357)
* Run all tests against bridged SDPA model * Exclude failing tests for now * [Bridges] fix BoundAlreadySet errors (#2376) * Fix format * Update --------- Co-authored-by: odow <[email protected]> Co-authored-by: Oscar Dowson <[email protected]>
1 parent b82d161 commit ede6d1c

File tree

4 files changed

+111
-39
lines changed

4 files changed

+111
-39
lines changed

src/Bridges/bridge_optimizer.jl

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,7 @@ function MOI.delete(b::AbstractBridgeOptimizer, ci::MOI.ConstraintIndex)
697697
else
698698
MOI.delete(b.model, ci)
699699
end
700+
return
700701
end
701702

702703
function MOI.delete(
@@ -1732,28 +1733,71 @@ function add_bridged_constraint(b, BridgeType, f, s)
17321733
return ci
17331734
end
17341735

1736+
function _throw_if_bound_already_set(b, x, ::S2, ::Type{S1}) where {S1,S2}
1737+
ErrorType = _bound_error_type(S1, S2)
1738+
if ErrorType === nothing
1739+
return
1740+
end
1741+
ci = MOI.ConstraintIndex{MOI.VariableIndex,S1}(x.value)
1742+
if (is_bridged(b, S1) && MOI.is_valid(b, ci)) || MOI.is_valid(b.model, ci)
1743+
throw(ErrorType(x))
1744+
end
1745+
return
1746+
end
1747+
1748+
function _bound_error_type(
1749+
::Type{S1},
1750+
::Type{S2},
1751+
) where {S1<:MOI.LessThan,S2<:MOI.LessThan}
1752+
return MOI.UpperBoundAlreadySet{S1,S2}
1753+
end
1754+
1755+
function _bound_error_type(::Type{S1}, ::Type{S2}) where {S1<:MOI.LessThan,S2}
1756+
return MOI.UpperBoundAlreadySet{S1,S2}
1757+
end
1758+
1759+
function _bound_error_type(::Type{S1}, ::Type{S2}) where {S1,S2<:MOI.LessThan}
1760+
return MOI.UpperBoundAlreadySet{S1,S2}
1761+
end
1762+
1763+
function _bound_error_type(::Type{S1}, ::Type{S2}) where {S1,S2}
1764+
return MOI.LowerBoundAlreadySet{S1,S2}
1765+
end
1766+
1767+
_bound_error_type(::Type{<:MOI.LessThan}, ::Type{<:MOI.GreaterThan}) = nothing
1768+
1769+
_bound_error_type(::Type{<:MOI.GreaterThan}, ::Type{<:MOI.LessThan}) = nothing
1770+
17351771
function _check_double_single_variable(
17361772
b::AbstractBridgeOptimizer,
1737-
func::MOI.VariableIndex,
1738-
set,
1739-
)
1740-
if !is_bridged(b, typeof(set))
1741-
# The variable might have been constrained in `b.model` to a set of type
1742-
# `typeof(set)` on creation.
1743-
ci = MOI.ConstraintIndex{MOI.VariableIndex,typeof(set)}(func.value)
1744-
if MOI.is_valid(b.model, ci)
1745-
error(
1746-
"The variable `$(func)` was constrained on creation ",
1747-
"to a set of type `$(typeof(set))`. Therefore, a ",
1748-
"`VariableIndex`-in-`$(typeof(set))` cannot be added on this ",
1749-
"variable. Use `MOI.set` with `MOI.ConstraintSet()` instead.",
1750-
)
1751-
end
1752-
end
1773+
x::MOI.VariableIndex,
1774+
s::S,
1775+
) where {
1776+
T,
1777+
S<:Union{
1778+
MOI.Interval{T},
1779+
MOI.EqualTo{T},
1780+
MOI.Semicontinuous{T},
1781+
MOI.Semiinteger{T},
1782+
MOI.LessThan{T},
1783+
MOI.GreaterThan{T},
1784+
},
1785+
}
1786+
# !!! warning
1787+
# The order here is _very_ important because an Interval constraint
1788+
# might get re-written into a LessThan and GreaterThan. To throw the
1789+
# appropriate error, we _must_ check sets like `Interval` and `EqualTo`
1790+
# _before_ `LessThan` and `GreaterThan`.
1791+
_throw_if_bound_already_set(b, x, s, MOI.Interval{T})
1792+
_throw_if_bound_already_set(b, x, s, MOI.EqualTo{T})
1793+
_throw_if_bound_already_set(b, x, s, MOI.Semicontinuous{T})
1794+
_throw_if_bound_already_set(b, x, s, MOI.Semiinteger{T})
1795+
_throw_if_bound_already_set(b, x, s, MOI.LessThan{T})
1796+
_throw_if_bound_already_set(b, x, s, MOI.GreaterThan{T})
17531797
return
17541798
end
17551799

1756-
_check_double_single_variable(b::AbstractBridgeOptimizer, func, set) = nothing
1800+
_check_double_single_variable(::AbstractBridgeOptimizer, ::Any, ::Any) = nothing
17571801

17581802
function MOI.add_constraint(
17591803
b::AbstractBridgeOptimizer,

src/Utilities/variables_container.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ function MOI.is_valid(
308308
return !iszero(b.set_mask[ci.value] & _single_variable_flag(S))
309309
end
310310

311+
MOI.is_valid(::VariablesContainer, ::MOI.ConstraintIndex) = false
312+
311313
function MOI.get(
312314
model::VariablesContainer,
313315
::MOI.ConstraintFunction,

test/Bridges/lazy_bridge_optimizer.jl

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,15 @@ end
104104
function MOI.supports(
105105
::StandardLPModel{T},
106106
::MOI.ObjectiveFunction{
107-
<:Union{MOI.VariableIndex,MOI.ScalarQuadraticFunction{T}},
107+
<:Union{
108+
MOI.VariableIndex,
109+
MOI.ScalarQuadraticFunction{T},
110+
MOI.ScalarNonlinearFunction,
111+
MOI.VectorOfVariables,
112+
MOI.VectorAffineFunction{T},
113+
MOI.VectorQuadraticFunction{T},
114+
MOI.VectorNonlinearFunction,
115+
},
108116
},
109117
) where {T}
110118
return false
@@ -295,39 +303,49 @@ function test_MOI_runtests_LPModel()
295303
bridged = MOI.Bridges.full_bridge_optimizer(model, Float64)
296304
MOI.Test.runtests(
297305
bridged,
298-
MOI.Test.Config(exclude = Any[MOI.optimize!]),
306+
MOI.Test.Config(exclude = Any[MOI.optimize!]);
299307
include = ["test_model_", "test_constraint_"],
300-
exclude = [
301-
"test_constraint_ConstraintDualStart",
302-
"test_constraint_ConstraintPrimalStart",
303-
"test_model_default_DualStatus",
304-
"test_model_default_PrimalStatus",
305-
"test_model_default_TerminationStatus",
306-
"test_model_LowerBoundAlreadySet",
307-
"test_model_UpperBoundAlreadySet",
308-
],
309308
)
310309
return
311310
end
312311

313312
function test_MOI_runtests_StandardSDPAModel()
314-
model = StandardSDPAModel{Float64}()
315-
bridged = MOI.Bridges.full_bridge_optimizer(model, Float64)
313+
model =
314+
MOI.instantiate(StandardSDPAModel{Float64}; with_bridge_type = Float64)
316315
MOI.Test.runtests(
317-
bridged,
318-
MOI.Test.Config(exclude = Any[MOI.optimize!]),
319-
include = ["ConstraintName", "VariableName"],
316+
model,
317+
MOI.Test.Config(
318+
exclude = Any[MOI.optimize!, MOI.SolverName, MOI.SolverVersion],
319+
);
320+
exclude = String[
321+
# Skip these tests because the bridge reformulates bound
322+
# constraints, so there is no conflict. An error _is_ thrown if two
323+
# sets of the same type are added.
324+
"test_model_LowerBoundAlreadySet",
325+
"test_model_UpperBoundAlreadySet",
326+
# MOI.ScalarFunctionConstantNotZero is thrown, not of the original
327+
# constraint, but of the bridged constraint. This seems okay. The
328+
# fix would require that a bridge optimizer has a try-catch for this
329+
# error.
330+
"test_model_ScalarFunctionConstantNotZero",
331+
# The error is:
332+
# Cannot substitute `MOI.VariableIndex(1)` as it is bridged into `0.0 + 1.0 MOI.VariableIndex(-1)`.
333+
# This seems okay. We can't get a list of variables if they are
334+
# bridged.
335+
"test_model_ListOfVariablesWithAttributeSet",
336+
],
320337
)
321338
return
322339
end
323340

324341
function test_MOI_runtests_GeometricSDPAModel()
325-
model = GeometricSDPAModel{Float64}()
326-
bridged = MOI.Bridges.full_bridge_optimizer(model, Float64)
342+
model =
343+
MOI.instantiate(GeometricSDPAModel{Float64}; with_bridge_type = Float64)
327344
MOI.Test.runtests(
328-
bridged,
329-
MOI.Test.Config(exclude = Any[MOI.optimize!]),
330-
include = ["ConstraintName", "VariableName"],
345+
model,
346+
MOI.Test.Config(
347+
exclude = Any[MOI.optimize!, MOI.SolverName, MOI.SolverVersion],
348+
),
331349
)
332350
return
333351
end

test/Bridges/sdpa_models.jl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,15 @@ end
6262
function MOI.supports(
6363
::StandardSDPAModel{T},
6464
::MOI.ObjectiveFunction{
65-
<:Union{MOI.VariableIndex,MOI.ScalarQuadraticFunction{T}},
65+
<:Union{
66+
MOI.VariableIndex,
67+
MOI.ScalarQuadraticFunction{T},
68+
MOI.ScalarNonlinearFunction,
69+
MOI.VectorOfVariables,
70+
MOI.VectorAffineFunction{T},
71+
MOI.VectorQuadraticFunction{T},
72+
MOI.VectorNonlinearFunction,
73+
},
6674
},
6775
) where {T}
6876
return false

0 commit comments

Comments
 (0)