Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/Utilities/universalfallback.jl
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,45 @@
return _get(uf, attr)
end

# `UniversalFallback` claims to support every `(F, S)` constraint pair and every
# constrained-variable set via its catch-all `supports_constraint` /
# `supports_add_constrained_variable(s)`. The bridging-cost attributes must
# agree with that: if the inner model genuinely supports the pair/set, defer to
# it; otherwise, `UniversalFallback` itself supports it (by caching the
# constraint in its own dict), so the cost is `0.0`. The generic
# `AbstractModelAttribute` getter above would otherwise forward to the inner
# model — whose `get_fallback` returns `Inf` for unsupported pairs — even

Check failure on line 382 in src/Utilities/universalfallback.jl

View workflow job for this annotation

GitHub Actions / build

[vale] reported by reviewdog 🐶 [Google.EmDash] Don't put a space before or after a dash. Raw Output: {"message": "[Google.EmDash] Don't put a space before or after a dash.", "location": {"path": "src/Utilities/universalfallback.jl", "range": {"start": {"line": 382, "column": 67}}}, "severity": "ERROR"}
# though `UniversalFallback` claims support.
function MOI.get(
uf::UniversalFallback,
attr::MOI.ConstraintBridgingCost{F,S},
) where {F,S}
if MOI.supports_constraint(uf.model, F, S)
return MOI.get(uf.model, attr)
end
return 0.0
end

function MOI.get(
uf::UniversalFallback,
attr::MOI.VariableBridgingCost{S},
) where {S<:MOI.AbstractScalarSet}
if MOI.supports_add_constrained_variable(uf.model, S)
return MOI.get(uf.model, attr)
end
return 0.0
end

function MOI.get(
uf::UniversalFallback,
attr::MOI.VariableBridgingCost{S},
) where {S<:MOI.AbstractVectorSet}
if MOI.supports_add_constrained_variables(uf.model, S)
return MOI.get(uf.model, attr)
end
return 0.0
end

function MOI.get(
uf::UniversalFallback,
attr::MOI.AbstractConstraintAttribute,
Expand Down
42 changes: 42 additions & 0 deletions test/Utilities/test_universalfallback.jl
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,48 @@ function test_set_inner_constraint_attribute()
return
end

function test_bridging_cost_consistent_with_supports()
# `UniversalFallback.supports_constraint` and
# `supports_add_constrained_variable(s)` accept absolutely anything by
# forwarding through their `is_bridged`-style catch-all. The bridging-cost
# attributes must agree: they should never return `Inf` for a pair that
# `supports_*` claims to support, because that would make
# `LazyBridgeOptimizer` treat the node as unreachable and break graph
# construction. Use `Model{BigFloat}` so the inner model genuinely does
# not support `*Cone{Float64}`, exercising the case where
# `UniversalFallback` extends support beyond the inner.
model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{BigFloat}())
for (F, S) in (
# inner supports natively
(MOI.ScalarAffineFunction{BigFloat}, MOI.LessThan{BigFloat}),
(MOI.VectorOfVariables, MOI.PowerCone{BigFloat}),
# inner does not support; UF stores in its own dict
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}),
(MOI.VectorOfVariables, MOI.PowerCone{Float64}),
(MOI.VectorAffineFunction{BigFloat}, MOI.Test.UnknownVectorSet),
)
@test MOI.supports_constraint(model, F, S)
@test MOI.get(model, MOI.ConstraintBridgingCost{F,S}()) < Inf
end
for S in (
MOI.GreaterThan{BigFloat},
MOI.Integer,
MOI.GreaterThan{Float64}, # not natively supported by Model{BigFloat}
)
@test MOI.supports_add_constrained_variable(model, S)
@test MOI.get(model, MOI.VariableBridgingCost{S}()) < Inf
end
for S in (
MOI.Nonnegatives,
MOI.PowerCone{BigFloat},
MOI.PowerCone{Float64}, # not natively supported by Model{BigFloat}
)
@test MOI.supports_add_constrained_variables(model, S)
@test MOI.get(model, MOI.VariableBridgingCost{S}()) < Inf
end
return
end

end # module

TestUniversalFallback.runtests()
Loading