Skip to content

Commit 46f692b

Browse files
committed
Fix BridgingCost for UniversalFallback
1 parent b98b476 commit 46f692b

2 files changed

Lines changed: 81 additions & 0 deletions

File tree

src/Utilities/universalfallback.jl

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,45 @@ function MOI.get(
372372
return _get(uf, attr)
373373
end
374374

375+
# `UniversalFallback` claims to support every `(F, S)` constraint pair and every
376+
# constrained-variable set via its catch-all `supports_constraint` /
377+
# `supports_add_constrained_variable(s)`. The bridging-cost attributes must
378+
# agree with that: if the inner model genuinely supports the pair/set, defer to
379+
# it; otherwise, `UniversalFallback` itself supports it (by caching the
380+
# constraint in its own dict), so the cost is `0.0`. The generic
381+
# `AbstractModelAttribute` getter above would otherwise forward to the inner
382+
# model — whose `get_fallback` returns `Inf` for unsupported pairs — even
383+
# though `UniversalFallback` claims support.
384+
function MOI.get(
385+
uf::UniversalFallback,
386+
attr::MOI.ConstraintBridgingCost{F,S},
387+
) where {F,S}
388+
if MOI.supports_constraint(uf.model, F, S)
389+
return MOI.get(uf.model, attr)
390+
end
391+
return 0.0
392+
end
393+
394+
function MOI.get(
395+
uf::UniversalFallback,
396+
attr::MOI.VariableBridgingCost{S},
397+
) where {S<:MOI.AbstractScalarSet}
398+
if MOI.supports_add_constrained_variable(uf.model, S)
399+
return MOI.get(uf.model, attr)
400+
end
401+
return 0.0
402+
end
403+
404+
function MOI.get(
405+
uf::UniversalFallback,
406+
attr::MOI.VariableBridgingCost{S},
407+
) where {S<:MOI.AbstractVectorSet}
408+
if MOI.supports_add_constrained_variables(uf.model, S)
409+
return MOI.get(uf.model, attr)
410+
end
411+
return 0.0
412+
end
413+
375414
function MOI.get(
376415
uf::UniversalFallback,
377416
attr::MOI.AbstractConstraintAttribute,

test/Utilities/test_universalfallback.jl

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,48 @@ function test_set_inner_constraint_attribute()
530530
return
531531
end
532532

533+
function test_bridging_cost_consistent_with_supports()
534+
# `UniversalFallback.supports_constraint` and
535+
# `supports_add_constrained_variable(s)` accept absolutely anything by
536+
# forwarding through their `is_bridged`-style catch-all. The bridging-cost
537+
# attributes must agree: they should never return `Inf` for a pair that
538+
# `supports_*` claims to support, because that would make
539+
# `LazyBridgeOptimizer` treat the node as unreachable and break graph
540+
# construction. Use `Model{BigFloat}` so the inner model genuinely does
541+
# not support `*Cone{Float64}`, exercising the case where
542+
# `UniversalFallback` extends support beyond the inner.
543+
model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{BigFloat}())
544+
for (F, S) in (
545+
# inner supports natively
546+
(MOI.ScalarAffineFunction{BigFloat}, MOI.LessThan{BigFloat}),
547+
(MOI.VectorOfVariables, MOI.PowerCone{BigFloat}),
548+
# inner does not support; UF stores in its own dict
549+
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}),
550+
(MOI.VectorOfVariables, MOI.PowerCone{Float64}),
551+
(MOI.VectorAffineFunction{BigFloat}, MOI.Test.UnknownVectorSet),
552+
)
553+
@test MOI.supports_constraint(model, F, S)
554+
@test MOI.get(model, MOI.ConstraintBridgingCost{F,S}()) < Inf
555+
end
556+
for S in (
557+
MOI.GreaterThan{BigFloat},
558+
MOI.Integer,
559+
MOI.GreaterThan{Float64}, # not natively supported by Model{BigFloat}
560+
)
561+
@test MOI.supports_add_constrained_variable(model, S)
562+
@test MOI.get(model, MOI.VariableBridgingCost{S}()) < Inf
563+
end
564+
for S in (
565+
MOI.Nonnegatives,
566+
MOI.PowerCone{BigFloat},
567+
MOI.PowerCone{Float64}, # not natively supported by Model{BigFloat}
568+
)
569+
@test MOI.supports_add_constrained_variables(model, S)
570+
@test MOI.get(model, MOI.VariableBridgingCost{S}()) < Inf
571+
end
572+
return
573+
end
574+
533575
end # module
534576

535577
TestUniversalFallback.runtests()

0 commit comments

Comments
 (0)