Skip to content

Commit 6641566

Browse files
committed
Update
1 parent 46f692b commit 6641566

8 files changed

Lines changed: 110 additions & 10 deletions

File tree

src/FileFormats/NL/NL.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,14 @@ function MOI.get(model::Model, attr::MOI.AbstractModelAttribute)
880880
return MOI.get(inner, attr)
881881
end
882882

883+
# It doesn't need the inner model
884+
function MOI.get(
885+
model::Model,
886+
attr::Union{MOI.VariableBridgingCost,MOI.ConstraintBridgingCost},
887+
)
888+
return MOI.get_fallback(model, attr)
889+
end
890+
883891
function MOI.get(
884892
model::Model,
885893
attr::MOI.AbstractConstraintAttribute,

src/Test/test_attribute.jl

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,3 +393,55 @@ function test_attribute_unsupported_constraint(model::MOI.ModelLike, ::Config)
393393
end
394394

395395
version_added(::typeof(test_attribute_unsupported_constraint)) = v"1.9.0"
396+
397+
"""
398+
test_attribute_VariableBridgingCost(model::MOI.ModelLike, config::Config)
399+
400+
Test that, for every set `S` that the model claims to support via
401+
`supports_add_constrained_variable(s)`, the corresponding
402+
[`MOI.VariableBridgingCost`](@ref) attribute returns a finite value.
403+
404+
This is the variable-side analog of the `ConstraintBridgingCost` check in
405+
`_basic_constraint_test_helper`.
406+
407+
The fallback works for most model but it may need custom method for some MOI
408+
layers (see https://github.com/jump-dev/MathOptInterface.jl/pull/3001#issuecomment-4468198935).
409+
410+
This test is here to catch that.
411+
"""
412+
function test_attribute_VariableBridgingCost(
413+
model::MOI.ModelLike,
414+
::Config{T},
415+
) where {T}
416+
for S in Any[
417+
MOI.GreaterThan{T},
418+
MOI.LessThan{T},
419+
MOI.EqualTo{T},
420+
MOI.Interval{T},
421+
MOI.Integer,
422+
MOI.ZeroOne,
423+
MOI.Semicontinuous{T},
424+
MOI.Semiinteger{T},
425+
]
426+
if MOI.supports_add_constrained_variable(model, S)
427+
@test MOI.get(model, MOI.VariableBridgingCost{S}()) < Inf
428+
end
429+
end
430+
for S in Any[
431+
MOI.Reals,
432+
MOI.Zeros,
433+
MOI.Nonnegatives,
434+
MOI.Nonpositives,
435+
MOI.SecondOrderCone,
436+
MOI.RotatedSecondOrderCone,
437+
MOI.ExponentialCone,
438+
MOI.PositiveSemidefiniteConeTriangle,
439+
]
440+
if MOI.supports_add_constrained_variables(model, S)
441+
@test MOI.get(model, MOI.VariableBridgingCost{S}()) < Inf
442+
end
443+
end
444+
return
445+
end
446+
447+
version_added(::typeof(test_attribute_VariableBridgingCost)) = v"1.52.0"

src/Test/test_basic_constraint.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,16 @@ function _basic_constraint_test_helper(
255255
###
256256
@requires MOI.supports_constraint(model, F, S)
257257
###
258+
### Test MOI.ConstraintBridgingCost
259+
###
260+
# If `supports_constraint(F, S)` returns `true`, then the model must be
261+
# able to handle that pair (possibly via bridging), so the bridging cost
262+
# must be finite. The fallback works for most model but it may need
263+
# custom method for some MOI layer (see
264+
# https://github.com/jump-dev/MathOptInterface.jl/pull/3001#issuecomment-4468198935)
265+
# This test is here to catch that.
266+
@test MOI.get(model, MOI.ConstraintBridgingCost{F,S}()) < Inf
267+
###
258268
### Test MOI.NumberOfConstraints
259269
###
260270
@test MOI.get(model, MOI.NumberOfConstraints{F,S}()) == 0

src/Utilities/cachingoptimizer.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,16 @@ function MOI.get(model::CachingOptimizer, attr::MOI.AbstractModelAttribute)
897897
return _get_model_attribute(model, attr)
898898
end
899899

900+
function MOI.get(
901+
model::CachingOptimizer,
902+
attr::Union{MOI.VariableBridgingCost,MOI.ConstraintBridgingCost},
903+
)::Float64
904+
if state(model) == NO_OPTIMIZER
905+
return MOI.get(model.model_cache, attr)
906+
end
907+
return MOI.get(model.optimizer, attr)
908+
end
909+
900910
function MOI.get(
901911
model::CachingOptimizer,
902912
attr::MOI.TerminationStatus,

src/Utilities/universalfallback.jl

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -372,15 +372,6 @@ 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.
384375
function MOI.get(
385376
uf::UniversalFallback,
386377
attr::MOI.ConstraintBridgingCost{F,S},

test/Bridges/Constraint/test_IntervalToHyperRectangleBridge.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ function test_basic(T)
3838
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{T}()),
3939
)
4040
bridged_mock = MOI.Bridges.Constraint.IntervalToHyperRectangle{T}(mock)
41-
config = MOI.Test.Config()
41+
config = MOI.Test.Config(T)
4242
MOI.Test.runtests(
4343
bridged_mock,
4444
config,

test/FileFormats/NL/test_NL.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,6 +1542,17 @@ function test_unsupported_kwarg()
15421542
return
15431543
end
15441544

1545+
function test_VariableBridgingCost()
1546+
model = NL.Model()
1547+
attr = MOI.VariableBridgingCost{MOI.LessThan{Float64}}()
1548+
@test MOI.get(model, attr) == 0
1549+
attr = MOI.ConstraintBridgingCost{MOI.VariableIndex,MOI.LessThan{Float64}}()
1550+
@test MOI.get(model, attr) == 0
1551+
attr = MOI.VariableBridgingCost{MOI.SecondOrderCone}()
1552+
@test isinf(MOI.get(model, attr))
1553+
return
1554+
end
1555+
15451556
end
15461557

15471558
TestNLModel.runtests()

test/Utilities/test_cachingoptimizer.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,6 +1465,24 @@ function test_rethrow_set_model_attribute()
14651465
return
14661466
end
14671467

1468+
function test_BridgingCost_NO_OPTIMIZER()
1469+
cache = MOI.Utilities.Model{Float64}()
1470+
model = MOI.Utilities.CachingOptimizer(cache, MOI.Utilities.AUTOMATIC)
1471+
@test MOI.Utilities.state(model) == MOI.Utilities.NO_OPTIMIZER
1472+
@test MOI.get(model, MOI.VariableBridgingCost{MOI.LessThan{Float64}}()) ==
1473+
0.0
1474+
@test MOI.get(model, MOI.VariableBridgingCost{MOI.LessThan{Int}}()) == Inf
1475+
@test MOI.get(
1476+
model,
1477+
MOI.ConstraintBridgingCost{MOI.VariableIndex,MOI.LessThan{Float64}}(),
1478+
) == 0.0
1479+
@test MOI.get(
1480+
model,
1481+
MOI.ConstraintBridgingCost{MOI.VariableIndex,MOI.LessThan{Int}}(),
1482+
) == Inf
1483+
return
1484+
end
1485+
14681486
end # module
14691487

14701488
TestCachingOptimizer.runtests()

0 commit comments

Comments
 (0)