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
2 changes: 2 additions & 0 deletions docs/src/submodules/Utilities/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ The following functions can be used to canonicalize a function:
Utilities.is_canonical
Utilities.canonical
Utilities.copy_if_modifiable
Utilities.UnsafeConstraintFunction
Utilities.UnsafeObjectiveFunction
Utilities.canonicalize!
```

Expand Down
30 changes: 30 additions & 0 deletions src/Bridges/Constraint/bridges/AbstractFunctionConversionBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,36 @@ function MOI.get(
model::MOI.ModelLike,
attr::MOI.AbstractConstraintAttribute,
bridge::AbstractFunctionConversionBridge,
)
return _get_invariant(model, attr, bridge)
end

# Needed to avoid an ambiguity with the getter for
# MOI.AbstractConstraintAttribute and the fallback in `bridge.jl`. Subtypes have
# to implement `MOI.ConstraintFunction` as it is not invariant under function
# conversion.
function MOI.get(
model::MOI.ModelLike,
attr::MOI.ConstraintFunction,
bridge::AbstractFunctionConversionBridge,
)
return _get_invariant(model, attr, bridge)
end

# Needed to avoid an ambiguity with the getter for
# MOI.AbstractConstraintAttribute and the fallback in `bridge.jl`.
function MOI.get(
::MOI.ModelLike,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::AbstractFunctionConversionBridge,
)
return MOI.Bridges._throw_constraint_function_not_allowed(bridge)
end

function _get_invariant(
model::MOI.ModelLike,
attr::MOI.AbstractConstraintAttribute,
bridge::AbstractFunctionConversionBridge,
)
if !invariant_under_function_conversion(attr)
throw(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::AllDifferentToCountDistinctBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(
Expand Down
4 changes: 2 additions & 2 deletions src/Bridges/Constraint/bridges/BinPackingToMILPBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::BinPackingToMILPBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(
Expand Down
4 changes: 2 additions & 2 deletions src/Bridges/Constraint/bridges/CircuitToMILPBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::CircuitToMILPBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::CountAtLeastToCountBelongsBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(
Expand Down
4 changes: 2 additions & 2 deletions src/Bridges/Constraint/bridges/CountBelongsToMILPBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::CountBelongsToMILPBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(
Expand Down
4 changes: 2 additions & 2 deletions src/Bridges/Constraint/bridges/CountDistinctToMILPBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::CountDistinctToMILPBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::CountGreaterThanToMILPBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::ExponentialConeToScalarNonlinearFunctionBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(
Expand Down
4 changes: 2 additions & 2 deletions src/Bridges/Constraint/bridges/IndicatorToMILPBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::IndicatorToMILPBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::ReifiedAllDifferentToCountDistinctBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::ReifiedCountDistinctToMILPBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(
Expand Down
4 changes: 2 additions & 2 deletions src/Bridges/Constraint/bridges/SOS1ToMILPBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::SOS1ToMILPBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(::MOI.ModelLike, ::MOI.ConstraintSet, bridge::SOS1ToMILPBridge)
Expand Down
4 changes: 2 additions & 2 deletions src/Bridges/Constraint/bridges/SOS2ToMILPBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::SOS2ToMILPBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(::MOI.ModelLike, ::MOI.ConstraintSet, bridge::SOS2ToMILPBridge)
Expand Down
4 changes: 2 additions & 2 deletions src/Bridges/Constraint/bridges/SplitIntervalBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ end

function MOI.get(
model::MOI.ModelLike,
attr::MOI.ConstraintFunction,
attr::MOI.Utilities.UnsafeConstraintFunction,
bridge::SplitIntervalBridge,
)
if bridge.lower !== nothing
Expand All @@ -430,7 +430,7 @@ function MOI.get(
if bridge.upper !== nothing
return MOI.get(model, attr, bridge.upper)
end
return MOI.Utilities.copy_if_modifiable(bridge.func)
return bridge.func
end

function MOI.get(
Expand Down
4 changes: 2 additions & 2 deletions src/Bridges/Constraint/bridges/TableToMILPBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ end

function MOI.get(
::MOI.ModelLike,
::MOI.ConstraintFunction,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::TableToMILPBridge,
)
return MOI.Utilities.copy_if_modifiable(bridge.f)
return bridge.f
end

function MOI.get(
Expand Down
23 changes: 18 additions & 5 deletions src/Bridges/Variable/set_map.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,24 @@ end

function MOI.get(
model::MOI.ModelLike,
attr::Union{
MOI.ConstraintFunction,
MOI.ConstraintPrimal,
MOI.ConstraintPrimalStart,
},
attr::Union{MOI.ConstraintPrimal,MOI.ConstraintPrimalStart},
bridge::SetMapBridge,
)
return _get_mapped(model, attr, bridge)
end

# Separate method to avoid an ambiguity with the fallback in `bridge.jl`.
function MOI.get(
model::MOI.ModelLike,
attr::MOI.ConstraintFunction,
bridge::SetMapBridge,
)
return _get_mapped(model, attr, bridge)
end

function _get_mapped(
model::MOI.ModelLike,
attr::MOI.AbstractConstraintAttribute,
bridge::SetMapBridge,
)
value = MOI.get(model, attr, bridge.constraint)
Expand Down
47 changes: 47 additions & 0 deletions src/Bridges/bridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,53 @@ function MOI.get(
return throw(MOI.GetAttributeNotAllowed(attr, message))
end

"""
MOI.get(
model::MOI.ModelLike,
::MOI.ConstraintFunction,
bridge::AbstractBridge,
)

Return a copy of the function of the constraint bridged by `bridge` if it can
be modified, see [`MOI.Utilities.copy_if_modifiable`](@ref).

A bridge that stores the function of the constraint it bridges only needs to
implement [`MOI.Utilities.UnsafeConstraintFunction`](@ref) and return the
stored function. A bridge that builds a new function should implement
`MOI.ConstraintFunction` instead.

There is no fallback of `MOI.Utilities.UnsafeConstraintFunction` to
`MOI.ConstraintFunction` for bridges as it would create an infinite recursion
for bridges implementing neither of them. The bridge optimizer therefore always
gets `MOI.ConstraintFunction` from the bridges.
"""
function MOI.get(
model::MOI.ModelLike,
::MOI.ConstraintFunction,
bridge::AbstractBridge,
)
return MOI.Utilities.copy_if_modifiable(
MOI.get(model, MOI.Utilities.UnsafeConstraintFunction(), bridge),
)
end

# A bridge that implements neither `MOI.ConstraintFunction` nor
# `MOI.Utilities.UnsafeConstraintFunction` should throw the same error as before
# `MOI.Utilities.UnsafeConstraintFunction` was introduced.
function MOI.get(
::MOI.ModelLike,
::MOI.Utilities.UnsafeConstraintFunction,
bridge::AbstractBridge,
)
return _throw_constraint_function_not_allowed(bridge)
end

function _throw_constraint_function_not_allowed(bridge::AbstractBridge)
attr = MOI.ConstraintFunction()
message = _attribute_error_message(attr, typeof(bridge), "accessing")
return throw(MOI.GetAttributeNotAllowed(attr, message))
end

function MOI.get(
model::MOI.ModelLike,
::MOI.CanonicalConstraintFunction,
Expand Down
16 changes: 13 additions & 3 deletions src/Bridges/bridge_optimizer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1264,6 +1264,15 @@ function MOI.get(b::AbstractBridgeOptimizer, attr::MOI.ObjectiveFunction)
return unbridged_function(b, _bridged_function(b, attr))
end

# The objective function of `b.model` may be bridged so we cannot forward
# `UnsafeObjectiveFunction` to `b.model`.
function MOI.get(
b::AbstractBridgeOptimizer,
::MOI.Utilities.UnsafeObjectiveFunction{F},
) where {F}
return MOI.get(b, MOI.ObjectiveFunction{F}())
end

function MOI.set(
b::AbstractBridgeOptimizer,
attr::MOI.ObjectiveSense,
Expand Down Expand Up @@ -1515,7 +1524,7 @@ end

function MOI.get(
b::AbstractBridgeOptimizer,
attr::MOI.ConstraintFunction,
attr::Union{MOI.ConstraintFunction,MOI.Utilities.UnsafeConstraintFunction},
ci::MOI.ConstraintIndex,
)
if is_bridged(b, ci)
Expand All @@ -1526,8 +1535,9 @@ function MOI.get(
return Variable.function_for(Variable.bridges(b)::Variable.Map, ci)
else
# Otherwise, we need to query ConstraintFunction in the context of
# the bridge...
func = call_in_context(MOI.get, b, ci, attr)
# the bridge. We don't forward `UnsafeConstraintFunction` as bridges
# building a new function only implement `ConstraintFunction`...
func = call_in_context(MOI.get, b, ci, MOI.ConstraintFunction())
# and then unbridge this function (because it may contain variables
# that are themselves bridged).
return unbridged_constraint_function(b, func)
Expand Down
Loading
Loading