Skip to content

Commit 460cad7

Browse files
blegatodow
andauthored
[Bridges] Add MOI.Bridge.FirstBridge attribute (#2211)
* Add FirstBridge * Add tests * Update * Add to docs * Update src/Utilities/functions.jl * Update src/Bridges/Constraint/bridges/functionize.jl --------- Co-authored-by: odow <[email protected]> Co-authored-by: Oscar Dowson <[email protected]>
1 parent 0f8d35c commit 460cad7

File tree

6 files changed

+74
-2
lines changed

6 files changed

+74
-2
lines changed

docs/src/submodules/Bridges/reference.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ Bridges.unbridged_variable_function
7575
Bridges.bridged_function
7676
Bridges.supports_constraint_bridges
7777
Bridges.recursive_model
78+
Bridges.FirstBridge
7879
```
7980

8081
## LazyBridgeOptimizer API

src/Bridges/Constraint/bridges/functionize.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ function MOI.get(
4242
return MOI.Utilities.canonical(f)
4343
end
4444

45+
# Needed to avoid an ambiguity with the getter for MOI.AbstractConstraintAttribute
46+
function MOI.get(
47+
::MOI.ModelLike,
48+
::MOI.Bridges.FirstBridge,
49+
bridge::AbstractFunctionConversionBridge,
50+
)
51+
return bridge
52+
end
53+
4554
function MOI.supports(
4655
model::MOI.ModelLike,
4756
attr::MOI.AbstractConstraintAttribute,

src/Bridges/bridge.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,26 @@ julia> MOI.Bridges.bridging_cost(
323323
```
324324
"""
325325
bridging_cost(::Type{<:AbstractBridge}) = 1.0
326+
327+
"""
328+
struct FirstBridge <: MOI.AbstractConstraintAttribute end
329+
330+
Returns the first bridge used to bridge the constraint.
331+
332+
!!! warning
333+
The indices of the bridge correspond to internal indices and may not
334+
correspond to indices of the model this attribute is got from.
335+
"""
336+
struct FirstBridge <: MOI.AbstractConstraintAttribute end
337+
338+
MOI.is_set_by_optimize(::FirstBridge) = true
339+
340+
MOI.get(::MOI.ModelLike, ::FirstBridge, b::MOI.Bridges.AbstractBridge) = b
341+
342+
function MOI.Utilities.map_indices(
343+
::Function,
344+
::FirstBridge,
345+
b::MOI.Bridges.AbstractBridge,
346+
)
347+
return b
348+
end

src/Utilities/functions.jl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,18 @@ constraint functions, attribute values and submittable values. If you define a
221221
new attribute whose values `x::X` contain variable or constraint indices, you
222222
must also implement this function.
223223
"""
224-
map_indices(f, ::MOI.AnyAttribute, x) = map_indices(f, x)
224+
map_indices(f::Function, ::MOI.AnyAttribute, x) = map_indices(f, x)
225+
226+
function map_indices(
227+
variable_map::AbstractDict{T,T},
228+
attr::MOI.AnyAttribute,
229+
x::X,
230+
)::X where {T<:MOI.Index,X}
231+
return map_indices(Base.Fix1(getindex, variable_map), attr, x)
232+
end
225233

226234
# RawOptimizerAttribute values are passed through un-changed.
227-
map_indices(::Any, ::MOI.RawOptimizerAttribute, x) = x
235+
map_indices(::Function, ::MOI.RawOptimizerAttribute, x) = x
228236

229237
"""
230238
map_indices(

test/Bridges/Constraint/functionize.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,16 @@ function test_canonical_constraint_function()
351351
return
352352
end
353353

354+
function test_first_bridge()
355+
inner = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())
356+
model = MOI.Bridges.Constraint.ScalarFunctionize{Float64}(inner)
357+
x = MOI.add_variable(model)
358+
ci = MOI.add_constraint(model, x, MOI.GreaterThan(0.0))
359+
b = MOI.get(model, MOI.Bridges.FirstBridge(), ci)
360+
@test b isa MOI.Bridges.Constraint.ScalarFunctionizeBridge
361+
return
362+
end
363+
354364
end # module
355365

356366
TestConstraintFunctionize.runtests()

test/Bridges/bridge_optimizer.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,27 @@ function test_list_of_constraints_with_attribute_set()
11081108
return
11091109
end
11101110

1111+
function test_first_bridge()
1112+
inner = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())
1113+
bridge = MOI.Bridges.Constraint.ZeroOne{Float64}(inner)
1114+
model = MOI.Utilities.CachingOptimizer(
1115+
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
1116+
bridge,
1117+
)
1118+
x = MOI.add_variable(model)
1119+
ci = MOI.add_constraint(model, x, MOI.ZeroOne())
1120+
MOI.Utilities.attach_optimizer(model)
1121+
b = MOI.get(model, MOI.Bridges.FirstBridge(), ci)
1122+
@test b isa MOI.Bridges.Constraint.ZeroOneBridge
1123+
y = MOI.add_variable(model)
1124+
ci = MOI.add_constraint(model, y, MOI.Integer())
1125+
@test_throws(
1126+
MOI.GetAttributeNotAllowed{MOI.Bridges.FirstBridge},
1127+
MOI.get(model, MOI.Bridges.FirstBridge(), ci),
1128+
)
1129+
return
1130+
end
1131+
11111132
end # module
11121133

11131134
TestBridgeOptimizer.runtests()

0 commit comments

Comments
 (0)