-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
894 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
module Objective | ||
|
||
using MathOptInterface | ||
const MOI = MathOptInterface | ||
const MOIU = MOI.Utilities | ||
const MOIB = MOI.Bridges | ||
|
||
# Definition of an objective bridge | ||
include("bridge.jl") | ||
|
||
# Mapping between objective function attributes and bridges | ||
include("map.jl") | ||
|
||
# Bridge optimizer bridging a specific objective bridge | ||
include("single_bridge_optimizer.jl") | ||
|
||
# Objective bridges | ||
include("functionize.jl") | ||
const Functionize{T, OT<:MOI.ModelLike} = SingleBridgeOptimizer{FunctionizeBridge{T}, OT} | ||
include("slack.jl") | ||
const Slack{T, OT<:MOI.ModelLike} = SingleBridgeOptimizer{SlackBridge{T}, OT} | ||
|
||
""" | ||
add_all_bridges(bridged_model, T::Type) | ||
Add all bridges defined in the `Bridges.Objective` submodule to `bridged_model`. | ||
The coefficient type used is `T`. | ||
""" | ||
function add_all_bridges(bridged_model, T::Type) | ||
MOIB.add_bridge(bridged_model, FunctionizeBridge{T}) | ||
MOIB.add_bridge(bridged_model, SlackBridge{T}) | ||
return | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
""" | ||
AbstractBridge | ||
Subtype of [`MathOptInterface.Bridges.AbstractBridge`](@ref) for objective | ||
bridges. | ||
""" | ||
abstract type AbstractBridge <: MOIB.AbstractBridge end | ||
|
||
""" | ||
bridge_objective(BT::Type{<:AbstractBridge}, model::MOI.ModelLike, | ||
func::MOI.AbstractScalarFunction) | ||
Bridge the objective function `func` using bridge `BT` to `model` and returns | ||
a bridge object of type `BT`. The bridge type `BT` should be a concrete type, | ||
that is, all the type parameters of the bridge should be set. Use | ||
[`concrete_bridge_type`](@ref) to obtain a concrete type for a given function | ||
type. | ||
""" | ||
function bridge_objective(::Type{<:AbstractBridge}, ::MOI.ModelLike, | ||
func::MOI.AbstractScalarFunction) | ||
throw(MOI.UnsupportedAttribute(MOI.ObjectiveFunction{typeof(func)}())) | ||
end | ||
|
||
""" | ||
function MOI.set(model::MOI.ModelLike, attr::MOI.ObjectiveSense, | ||
bridge::AbstractBridge, sense::MOI.ObjectiveSense) | ||
Return the value of the attribute `attr` of the model `model` for the | ||
variable bridged by `bridge`. | ||
""" | ||
function MOI.set(::MOI.ModelLike, ::MOI.ObjectiveSense, | ||
bridge::AbstractBridge, ::MOI.OptimizationSense) | ||
throw(ArgumentError( | ||
"Objective bridge of type `$(typeof(bridge))` does not support" * | ||
" modifying the objective sense. As a workaround, set the sense to" * | ||
" `MOI.FEASIBILITY_SENSE` to clear the objective function and" * | ||
" bridges.")) | ||
end | ||
|
||
""" | ||
function MOI.get(model::MOI.ModelLike, attr::MOI.ObjectiveFunction, | ||
bridge::AbstractBridge) | ||
Return the value of the objective function bridged by `bridge` for the model | ||
`model`. | ||
""" | ||
function MOI.get(::MOI.ModelLike, ::MOI.ObjectiveFunction, | ||
bridge::AbstractBridge) | ||
throw(ArgumentError( | ||
"ObjectiveFunction bridge of type `$(typeof(bridge))` does not" * | ||
" support getting the objective function.")) | ||
end | ||
|
||
""" | ||
supports_objective_function( | ||
BT::Type{<:AbstractBridge}, | ||
F::Type{<:MOI.AbstractScalarFunction})::Bool | ||
Return a `Bool` indicating whether the bridges of type `BT` support bridging | ||
objective functions of type `F`. | ||
""" | ||
function supports_objective_function( | ||
::Type{<:AbstractBridge}, ::Type{<:MOI.AbstractScalarFunction}) | ||
return false | ||
end | ||
|
||
""" | ||
added_constrained_variable_types(BT::Type{<:MOI.Bridges.Objective.AbstractBridge}, | ||
F::Type{<:MOI.AbstractScalarFunction}) | ||
Return a list of the types of constrained variables that bridges of type `BT` | ||
add for bridging objective functions of type `F`. This fallbacks to | ||
`added_constrained_variable_types(concrete_bridge_type(BT, F))` | ||
so bridges should not implement this method. | ||
``` | ||
""" | ||
function MOIB.added_constrained_variable_types( | ||
BT::Type{<:AbstractBridge}, F::Type{<:MOI.AbstractScalarFunction}) | ||
return MOIB.added_constrained_variable_types(concrete_bridge_type(BT, F)) | ||
end | ||
|
||
""" | ||
added_constraint_types(BT::Type{<:MOI.Bridges.Objective.AbstractBridge}, | ||
F::Type{<:MOI.AbstractScalarFunction}) | ||
Return a list of the types of constraints that bridges of type `BT` add | ||
add for bridging objective functions of type `F`. This fallbacks to | ||
`added_constraint_types(concrete_bridge_type(BT, S))` | ||
so bridges should not implement this method. | ||
""" | ||
function MOIB.added_constraint_types( | ||
BT::Type{<:AbstractBridge}, F::Type{<:MOI.AbstractScalarFunction}) | ||
return MOIB.added_constraint_types(concrete_bridge_type(BT, F)) | ||
end | ||
|
||
function MOIB.set_objective_function_type( | ||
BT::Type{<:AbstractBridge}, F::Type{<:MOI.AbstractScalarFunction}) | ||
return MOIB.set_objective_function_type(concrete_bridge_type(BT, F)) | ||
end | ||
|
||
|
||
""" | ||
concrete_bridge_type(BT::Type{<:MOI.Bridges.Objective.AbstractBridge}, | ||
F::Type{<:MOI.AbstractScalarFunction})::DataType | ||
Return the concrete type of the bridge supporting objective functions of type | ||
`F`. This function can only be called if `MOI.supports_objective_function(BT, F)` | ||
is `true`. | ||
""" | ||
function concrete_bridge_type(bridge_type::DataType, | ||
::Type{<:MOI.AbstractScalarFunction}) | ||
return bridge_type | ||
end | ||
|
||
function concrete_bridge_type(b::MOIB.AbstractBridgeOptimizer, | ||
F::Type{<:MOI.AbstractScalarFunction}) | ||
return concrete_bridge_type(MOIB.bridge_type(b, F), F) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
""" | ||
FunctionizeBridge{T} | ||
The `FunctionizeBridge` converts a `SingleVariable` objective into a | ||
`ScalarAffineFunction{T}` objective. | ||
""" | ||
struct FunctionizeBridge{T} <: AbstractBridge end | ||
function bridge_objective(::Type{FunctionizeBridge{T}}, model, | ||
func::MOI.SingleVariable) where T | ||
F = MOI.ScalarAffineFunction{T} | ||
MOI.set(model, MOI.ObjectiveFunction{F}(), convert(F, func)) | ||
return FunctionizeBridge{T}() | ||
end | ||
|
||
function supports_objective_function( | ||
::Type{<:FunctionizeBridge}, ::Type{MOI.SingleVariable}) | ||
return true | ||
end | ||
MOIB.added_constrained_variable_types(::Type{<:FunctionizeBridge}) = Tuple{DataType}[] | ||
function MOIB.added_constraint_types(::Type{<:FunctionizeBridge}) | ||
return Tuple{DataType, DataType}[] | ||
end | ||
function MOIB.set_objective_function_type(::Type{FunctionizeBridge{T}}) where T | ||
return MOI.ScalarAffineFunction{T} | ||
end | ||
|
||
function MOI.delete(model::MOI.ModelLike, bridge::FunctionizeBridge) end | ||
|
||
function MOI.set(::MOI.ModelLike, ::MOI.ObjectiveSense, | ||
::FunctionizeBridge, ::MOI.OptimizationSense) | ||
end | ||
function MOI.get(model::MOI.ModelLike, | ||
attr::MOIB.ObjectiveFunctionValue{MOI.SingleVariable}, | ||
bridge::FunctionizeBridge{T}) where T | ||
F = MOI.ScalarAffineFunction{T} | ||
return MOI.get(model, MOIB.ObjectiveFunctionValue{F}()) | ||
end | ||
function MOI.get(model::MOI.ModelLike, attr::MOI.ObjectiveFunction{MOI.SingleVariable}, | ||
bridge::FunctionizeBridge{T}) where T | ||
F = MOI.ScalarAffineFunction{T} | ||
func = MOI.get(model, MOI.ObjectiveFunction{F}()) | ||
return convert(MOI.SingleVariable, func) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
""" | ||
Map <: AbstractDict{MOI.ObjectiveFunction, AbstractBridge} | ||
Mapping between bridged variables and the bridge that bridged the variable. | ||
""" | ||
mutable struct Map <: AbstractDict{MOI.ObjectiveFunction, AbstractBridge} | ||
bridges::Dict{MOI.ObjectiveFunction, AbstractBridge} | ||
function_type::Union{Nothing, Type{<:MOI.AbstractScalarFunction}} | ||
end | ||
function Map() | ||
return Map(Dict{MOI.ObjectiveFunction, AbstractBridge}(), nothing) | ||
end | ||
|
||
# Implementation of `AbstractDict` interface. | ||
|
||
Base.isempty(map::Map) = isempty(map.bridges) | ||
function Base.empty!(map::Map) | ||
empty!(map.bridges) | ||
map.function_type = nothing | ||
end | ||
function Base.haskey(map::Map, attr::MOI.ObjectiveFunction) | ||
return haskey(map.bridges, attr) | ||
end | ||
function Base.getindex(map::Map, attr::MOI.ObjectiveFunction) | ||
return map.bridges[attr] | ||
end | ||
Base.length(map::Map) = length(map.bridges) | ||
Base.values(map::Map) = values(map.bridges) | ||
Base.iterate(map::Map, args...) = iterate(map.bridges, args...) | ||
|
||
# Custom interface for information needed by `AbstractBridgeOptimizer`s that is | ||
# not part of the `AbstractDict` interface. | ||
|
||
""" | ||
function_type(map::Map) | ||
Return the function type of the [`root_bridge`](@ref) or `nothing` if `map` is | ||
empty. | ||
""" | ||
function_type(map::Map) = map.function_type | ||
|
||
""" | ||
root_bridge(map::Map) | ||
Return the last bridge added. | ||
""" | ||
function root_bridge(map::Map) | ||
attr = MOI.ObjectiveFunction{function_type(map)}() | ||
return map[attr] | ||
end | ||
|
||
""" | ||
add_key_for_bridge(map::Map, bridge::AbstractBridge, | ||
func::MOI.AbstractScalarFunction) | ||
Stores the mapping `atttr => bridge` where `attr` is | ||
`MOI.ObjectiveFunction{typeof(func)}()` and set [`function_type`](@ref) to | ||
`typeof(func)`. | ||
""" | ||
function add_key_for_bridge(map::Map, bridge::AbstractBridge, | ||
func::MOI.AbstractScalarFunction) | ||
attr = MOI.ObjectiveFunction{typeof(func)}() | ||
map.function_type = typeof(func) | ||
map.bridges[attr] = bridge | ||
end | ||
|
||
""" | ||
EmptyMap <: AbstractDict{MOI.ObjectiveFunction, AbstractBridge} | ||
Empty version of [`Map`](@ref). It is used by | ||
[`MathOptInterface.Bridges.Constraint.SingleBridgeOptimizer`](@ref) as it does | ||
not bridge any variable. | ||
""" | ||
struct EmptyMap <: AbstractDict{MOI.ObjectiveFunction, AbstractBridge} end | ||
Base.isempty(::EmptyMap) = true | ||
function Base.empty!(::EmptyMap) end | ||
Base.length(::EmptyMap) = 0 | ||
Base.haskey(::EmptyMap, ::MOI.ObjectiveFunction) = false | ||
Base.values(::EmptyMap) = MOIB.EmptyVector{AbstractBridge}() | ||
Base.iterate(::EmptyMap) = nothing | ||
function_type(::EmptyMap) = nothing |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
""" | ||
SingleBridgeOptimizer{BT<:AbstractBridge, OT<:MOI.ModelLike} <: AbstractBridgeOptimizer | ||
The `SingleBridgeOptimizer` bridges any objective functions supported by the | ||
bridge `BT`. This is in contrast with the [`MathOptInterface.Bridges.LazyBridgeOptimizer`](@ref) | ||
which only bridges the objective functions that are unsupported by the internal model, | ||
even if they are supported by one of its bridges. | ||
""" | ||
mutable struct SingleBridgeOptimizer{BT<:AbstractBridge, OT<:MOI.ModelLike} <: MOIB.AbstractBridgeOptimizer | ||
model::OT | ||
map::Map # `MOI.ObjectiveFunction` -> objective bridge | ||
end | ||
function SingleBridgeOptimizer{BT}(model::OT) where {BT, OT <: MOI.ModelLike} | ||
SingleBridgeOptimizer{BT, OT}(model, Map()) | ||
end | ||
|
||
function bridges(bridge::MOI.Bridges.AbstractBridgeOptimizer) | ||
return EmptyMap() | ||
end | ||
bridges(bridge::SingleBridgeOptimizer) = bridge.map | ||
|
||
MOIB.supports_constraint_bridges(::SingleBridgeOptimizer) = false | ||
function MOIB.is_bridged(::SingleBridgeOptimizer, ::Type{<:MOI.AbstractSet}) | ||
return false | ||
end | ||
function MOIB.is_bridged(::SingleBridgeOptimizer, | ||
::Type{<:MOI.AbstractFunction}, | ||
::Type{<:MOI.AbstractSet}) | ||
return false | ||
end | ||
function MOIB.supports_bridging_objective_function( | ||
::SingleBridgeOptimizer{BT}, F::Type{<:MOI.AbstractScalarFunction}) where BT | ||
return supports_objective_function(BT, F) | ||
end | ||
function MOIB.is_bridged( | ||
b::SingleBridgeOptimizer, F::Type{<:MOI.AbstractScalarFunction}) | ||
return MOIB.supports_bridging_objective_function(b, F) | ||
end | ||
function MOIB.bridge_type(::SingleBridgeOptimizer{BT}, | ||
::Type{<:MOI.AbstractScalarFunction}) where BT | ||
return BT | ||
end |
Oops, something went wrong.