diff --git a/docs/make.jl b/docs/make.jl index b6a9ae4209..8e68e2677b 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -39,6 +39,7 @@ makedocs( ], "Bridges" => [ "Overview" => "submodules/Bridges/overview.md", + "Implementation" => "submodules/Bridges/implementation.md", "API Reference" => "submodules/Bridges/reference.md", ], "FileFormats" => [ diff --git a/docs/src/submodules/Bridges/implementation.md b/docs/src/submodules/Bridges/implementation.md new file mode 100644 index 0000000000..b5f95f3010 --- /dev/null +++ b/docs/src/submodules/Bridges/implementation.md @@ -0,0 +1,47 @@ +```@meta +CurrentModule = MathOptInterface +DocTestSetup = quote + using MathOptInterface + const MOI = MathOptInterface +end +DocTestFilters = [r"MathOptInterface|MOI"] +``` + +# Bridge interface + +A bridge should implement the following functions to be usable by a bridge optimizer: +```@docs +Bridges.added_constrained_variable_types +Bridges.added_constraint_types +``` +Additionally, variable bridges should implement: +```@docs +Bridges.Variable.supports_constrained_variable +Bridges.Variable.concrete_bridge_type +Bridges.Variable.bridge_constrained_variable +``` +constraint bridges should implement: +```@docs +supports_constraint(::Type{<:Bridges.Constraint.AbstractBridge}, ::Type{<:AbstractFunction}, ::Type{<:AbstractSet}) +Bridges.Constraint.concrete_bridge_type +Bridges.Constraint.bridge_constraint +``` +and objective bridges should implement: +```@docs +Bridges.set_objective_function_type +Bridges.Objective.concrete_bridge_type +Bridges.Objective.bridge_objective +``` + +When querying the [`NumberOfVariables`](@ref), [`NumberOfConstraints`](@ref) +and [`ListOfConstraintIndices`](@ref), the variables and constraints created +by the bridges in the underlying model are hidden by the bridge optimizer. +For this purpose, the bridge should provide access to the variables and +constraints it has creates by implemented the following methods of +[`get`](@ref): +```@docs +get(::Bridges.Constraint.AbstractBridge, ::NumberOfVariables) +get(::Bridges.Constraint.AbstractBridge, ::ListOfVariableIndices) +get(::Bridges.AbstractBridge, ::NumberOfConstraints) +get(::Bridges.AbstractBridge, ::ListOfConstraintIndices) +``` diff --git a/docs/src/submodules/Bridges/overview.md b/docs/src/submodules/Bridges/overview.md index 5e3e9d130f..bf30ea56da 100644 --- a/docs/src/submodules/Bridges/overview.md +++ b/docs/src/submodules/Bridges/overview.md @@ -7,7 +7,16 @@ end DocTestFilters = [r"MathOptInterface|MOI"] ``` -# The `Bridges` submodule +# The Bridges submodule + +The `Bridges` module simplifies the process of converting models between +equivalent formulations. + +!!! tip + [Read our paper](https://arxiv.org/abs/2002.03447) for more details on how + bridges are implemented. + +## Why bridges? A constraint can often be written in a number of equivalent formulations. For example, the constraint ``l \le a^\top x \le u`` @@ -19,63 +28,164 @@ re-formulation is to add a dummy variable `y` with the constraints ``l \le y \le ([`ScalarAffineFunction`](@ref)-in-[`EqualTo`](@ref)). To avoid each solver having to code these transformations manually, -MathOptInterface provides *bridges*. A bridge is a small transformation from one -constraint type to another (potentially collection of) constraint type. Because -these bridges are included in MathOptInterface, they can be re-used by any -optimizer. Some bridges also implement constraint modifications and constraint -primal and dual translations. - -For example, the `SplitIntervalBridge` defines the reformulation of a -`ScalarAffineFunction`-in-`Interval` constraint into a -`ScalarAffineFunction`-in-`GreaterThan` and a -`ScalarAffineFunction`-in-`LessThan` constraint. `SplitInterval` is the -bridge optimizer that applies the `SplitIntervalBridge` rewriting rule. Given -an optimizer `optimizer` implementing `ScalarAffineFunction`-in-`GreaterThan` -and `ScalarAffineFunction`-in-`LessThan`, the optimizer -```jldoctest; setup=:(model = MOI.Utilities.Model{Float64}()) -optimizer = MOI.Bridges.Constraint.SplitInterval{Float64}(model) -MOI.supports_constraint( - optimizer, MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64} -) - -# output - -true +MathOptInterface provides *bridges*. + +A bridge is a small transformation from one constraint type to another +(potentially collection of) constraint type. + +Because these bridges are included in MathOptInterface, they can be re-used by +any optimizer. Some bridges also implement constraint modifications and +constraint primal and dual translations. + +## The three types of bridges + +There are three types of bridges in MathOptInterface: +1. Constraint bridges +2. Variable bridges +3. Objective bridges + +### Constraint bridges + +Constraint bridges convert constraints formulated by the user into an equivalent +form supported by the solver. + +The equivalent formulation may add constraints (and possibly also variables) in +the underlying model. + +Read the [list of implemented constraint bridges](@ref constraint_bridges_ref) +for more details on the types of transformations that are available. + +### [Variable bridges](@id variable_bridges) + +Variable bridges convert variables added by the user, either free with +[`add_variable`](@ref)/[`add_variables`](@ref), or constrained with +[`add_constrained_variable`](@ref)/[`add_constrained_variables`](@ref), +into an equivalent form supported by the solver. + +Te equivalent formulation may add constraints (and possibly also variables) in +the underlying model. + +Read the [list of implemented variable bridges](@ref variable_bridges_ref) for +more details on the types of transformations that are available. + +### Objective bridges + +Objective bridges convert the [`ObjectiveFunction`](@ref) set by the user into +an equivalent form supported by the solver. + +Te equivalent formulation may add constraints (and possibly also variables) in +the underlying model. + +Read the [list of implemented objective bridges](@ref objective_bridges_ref) for +more details on the types of transformations that are available. + +## Bridges.`full_bridge_optimizer` + +!!! tip + Unless you have an advanced use-case, this is probably the only function you + need to care about. + +To enable the full power of MathOptInterface's bridges, wrap an `optimizer` +in a [`Bridges.full_bridge_optimizer`](@ref). + +```jldoctest +julia> inner_optimizer = MOI.Utilities.Model{Float64}() +MOIU.Model{Float64} + +julia> optimizer = MOI.Bridges.full_bridge_optimizer(inner_optimizer, Float64) +MOIB.LazyBridgeOptimizer{MOIU.Model{Float64}} +with 0 variable bridges +with 0 constraint bridges +with 0 objective bridges +with inner model MOIU.Model{Float64} ``` -will additionally support [`ScalarAffineFunction`](@ref)-in-[`Interval`](@ref). -Note that these [`Bridges.Constraint.SingleBridgeOptimizer`](@ref)s are mainly -used for testing bridges. - -It is recommended to rather use [`Bridges.full_bridge_optimizer`](@ref) which -automatically selects the appropriate constraint bridges for unsupported -constraints. -```julia -optimizer = MOI.Bridges.full_bridge_optimizer(model, Float64) + +That's all you have to do! Use `optimizer` as normal, and bridging will happen +lazily behind the scenes. By lazily, we mean that bridging will only happen if +the constraint is not supported by the `inner_optimizer`. + +!!! info + Most bridges are added by default in [`Bridges.full_bridge_optimizer`](@ref). + However, for technical reasons, some bridges are not added by default. Three + examples include [`Bridges.Constraint.SOCtoPSDBridge`](@ref), + [`Bridges.Constraint.SOCtoNonConvexQuadBridge`](@ref) and + [`Bridges.Constraint.RSOCtoNonConvexQuadBridge`](@ref). See the docs of + those bridges for more information. + +## Add a single bridge + +If you don't want to use [`Bridges.full_bridge_optimizer`](@ref), you can wrap +an optimizer in a single bridge. + +However, this will force the constraint to be bridged, even if the +`inner_optimizer` supports it. + +```jldoctest +julia> inner_optimizer = MOI.Utilities.Model{Float64}() +MOIU.Model{Float64} + +julia> optimizer = MOI.Bridges.Constraint.SplitInterval{Float64}(inner_optimizer) +MOIB.Constraint.SingleBridgeOptimizer{MOIB.Constraint.SplitIntervalBridge{Float64,F,S,LS,US} where US<:MOI.AbstractSet where LS<:MOI.AbstractSet where S<:MOI.AbstractSet where F<:MOI.AbstractFunction,MOIU.Model{Float64}} +with 0 constraint bridges +with inner model MOIU.Model{Float64} + +julia> x = MOI.add_variable(optimizer) +MOI.VariableIndex(1) + +julia> MOI.add_constraint(optimizer, MOI.SingleVariable(x), MOI.Interval(0.0, 1.0)) +MathOptInterface.ConstraintIndex{MathOptInterface.SingleVariable,MathOptInterface.Interval{Float64}}(1) + +julia> MOI.get(optimizer, MOI.ListOfConstraints()) +1-element Array{Tuple{DataType,DataType},1}: + (MathOptInterface.SingleVariable, MathOptInterface.Interval{Float64}) + +julia> MOI.get(inner_optimizer, MOI.ListOfConstraints()) +2-element Array{Tuple{DataType,DataType},1}: + (MathOptInterface.SingleVariable, MathOptInterface.GreaterThan{Float64}) + (MathOptInterface.SingleVariable, MathOptInterface.LessThan{Float64}) ``` -### Variable reformulations +## Bridges.LazyBridgeOptimizer + +If you don't want to use [`Bridges.full_bridge_optimizer`](@ref), but you need +more than a single bridge (or you want the bridging to happen lazily), you can +manually construct a [`Bridges.LazyBridgeOptimizer`](@ref). + +First, wrap an inner optimizer: +```jldoctest lazy_bridge_optimizer +julia> inner_optimizer = MOI.Utilities.Model{Float64}() +MOIU.Model{Float64} -A variable is often created constrained in a set unsupported by the solver while -it could be parametrized by variables constrained in supported sets. -For example, the [`Bridges.Variable.VectorizeBridge`](@ref) defines the -reformulation of a constrained variable in [`GreaterThan`](@ref) into a -constrained vector of one variable in [`Nonnegatives`](@ref). -The `Bridges.Variable.Vectorize` is the bridge optimizer that applies the -[`Bridges.Variable.VectorizeBridge`](@ref) rewriting rule. Given an optimizer -`optimizer` implementing constrained variables in [`Nonnegatives`](@ref), -the optimizer -```jldoctest; setup=:(model = MOI.Utilities.Model{Float64}()) -optimizer = MOI.Bridges.Variable.Vectorize{Float64}(model) -MOI.supports_add_constrained_variable(optimizer, MOI.GreaterThan{Float64}) +julia> optimizer = MOI.Bridges.LazyBridgeOptimizer(inner_optimizer) +MOIB.LazyBridgeOptimizer{MOIU.Model{Float64}} +with 0 variable bridges +with 0 constraint bridges +with 0 objective bridges +with inner model MOIU.Model{Float64} +``` -# output +Then use [`Bridges.add_bridge`](@ref) to add individual bridges: +```jldoctest lazy_bridge_optimizer +julia> MOI.Bridges.add_bridge(optimizer, MOI.Bridges.Constraint.SplitIntervalBridge{Float64}) +Dict{Any,DataType} with 0 entries -true +julia> MOI.Bridges.add_bridge(optimizer, MOI.Bridges.Objective.FunctionizeBridge{Float64}) +Dict{Any,DataType} with 0 entries ``` -will additionally support constrained variables in [`GreaterThan`](@ref). -Note that these [`Bridges.Variable.SingleBridgeOptimizer`](@ref) are mainly -used for testing bridges. -It is recommended to rather use [`Bridges.full_bridge_optimizer`](@ref), which -automatically selects the appropriate bridges for unsupported constrained -variables. +Now the constraints will be bridged only if needed: +```jldoctest lazy_bridge_optimizer +julia> x = MOI.add_variable(optimizer) +MOI.VariableIndex(1) + +julia> MOI.add_constraint(optimizer, MOI.SingleVariable(x), MOI.Interval(0.0, 1.0)) +MathOptInterface.ConstraintIndex{MathOptInterface.SingleVariable,MathOptInterface.Interval{Float64}}(1) + +julia> MOI.get(optimizer, MOI.ListOfConstraints()) +1-element Array{Tuple{DataType,DataType},1}: + (MathOptInterface.SingleVariable, MathOptInterface.Interval{Float64}) + +julia> MOI.get(inner_optimizer, MOI.ListOfConstraints()) +1-element Array{Tuple{DataType,DataType},1}: + (MathOptInterface.SingleVariable, MathOptInterface.Interval{Float64}) +``` diff --git a/docs/src/submodules/Bridges/reference.md b/docs/src/submodules/Bridges/reference.md index 714a29717a..14975ca02b 100644 --- a/docs/src/submodules/Bridges/reference.md +++ b/docs/src/submodules/Bridges/reference.md @@ -15,64 +15,7 @@ end DocTestFilters = [r"MathOptInterface|MOI"] ``` -## Bridges - -Bridges can be used for automatic reformulation of constrained variables (i.e. -variables added with [`add_constrained_variable`](@ref)/[`add_constrained_variables`](@ref)) -or constraints into equivalent formulations using constrained variables and -constraints of different types. There are two important concepts to distinguish: -* [`Bridges.AbstractBridge`](@ref)s are recipes implementing a specific - reformulation. Bridges are not directly subtypes of - [`Bridges.AbstractBridge`](@ref), they are either - [`Bridges.Variable.AbstractBridge`](@ref) or - [`Bridges.Constraint.AbstractBridge`](@ref). -* [`Bridges.AbstractBridgeOptimizer`](@ref) is a layer that can be applied to - another [`ModelLike`](@ref) to apply the reformulation. The - [`Bridges.LazyBridgeOptimizer`](@ref) automatically chooses the appropriate - bridges to use when a constrained variable or constraint is not supported - by using the list of bridges that were added to it by - [`Bridges.add_bridge`](@ref). [`Bridges.full_bridge_optimizer`](@ref) wraps a - model in a [`Bridges.LazyBridgeOptimizer`](@ref) where all the bridges defined - in MOI are added. JuMP automatically calls - [`Bridges.full_bridge_optimizer`](@ref) when attaching an optimizer. - [`Bridges.debug_supports_constraint`](@ref) and [`Bridges.debug_supports`](@ref) - allow introspection into the bridge selection rationale of - [`Bridges.LazyBridgeOptimizer`](@ref). - -Most bridges are added by default in [`Bridges.full_bridge_optimizer`](@ref). -However, for technical reasons, some bridges are not added by default, for instance: -[`Bridges.Constraint.SOCtoPSDBridge`](@ref), [`Bridges.Constraint.SOCtoNonConvexQuadBridge`](@ref) -and [`Bridges.Constraint.RSOCtoNonConvexQuadBridge`](@ref). See the docs of those bridges -for more information. - -It is possible to add those bridges and also user defined bridges, -following one of the two methods. We present the examples for: -[`Bridges.Constraint.SOCtoNonConvexQuadBridge`](@ref). - -The first option is to add the specific bridges to a -`bridged_model` optimizer, with coefficient type `T`. The `bridged_model` -optimizer itself must have been constructed with a -[`Bridges.LazyBridgeOptimizer`](@ref). Once such a optimizer is available, we -can proceed using using [`Bridges.add_bridge`](@ref): - -```julia -MOIB.add_bridge(bridged_model, SOCtoNonConvexQuadBridge{T}) -``` - -Alternatively, it is possible to create a [`Bridges.Constraint.SingleBridgeOptimizer`](@ref) -and wrap an existing `model` with it: - -```julia -const SOCtoNonConvexQuad{T, OT<:ModelLike} = Bridges.Constraint.SingleBridgeOptimizer{Bridges.Constraint.SOCtoNonConvexQuadBridge{T}, OT} -bridged_model = SOCtoNonConvexQuad{Float64}(model) -``` - -Those procedures could be applied to user define bridges. For the -bridges defined in MathOptInterface, the [`Bridges.Constraint.SingleBridgeOptimizer`](@ref)'s are already created, therefore, for the case of [`Bridges.Constraint.SOCtoNonConvexQuadBridge`](@ref), one could simply use the existing optimizer: - -```julia -bridged_model = Bridges.Constraint.SOCtoNonConvexQuad{Float64}(model) -``` +# Bridges ```@docs Bridges.AbstractBridge @@ -84,195 +27,20 @@ Bridges.has_bridge Bridges.full_bridge_optimizer Bridges.debug_supports_constraint Bridges.debug_supports -``` - -### [Variable bridges](@id variable_bridges) - -When variables are added, either free with -[`add_variable`](@ref)/[`add_variables`](@ref), -or constrained with -[`add_constrained_variable`](@ref)/[`add_constrained_variables`](@ref), -variable bridges allow to return *bridged variables* that do not correspond to -variables of the underlying model. These variables are parametrized by -variables of the underlying model and this parametrization can be obtained with -[`Bridges.bridged_variable_function`](@ref). Similarly, the variables of the -underlying model that were created by the bridge can be expressed in terms of -the bridged variables and this expression can be obtained with -[`Bridges.unbridged_variable_function`](@ref). -For instance, consider a model bridged by the -[`Bridges.Variable.VectorizeBridge`](@ref): -```jldoctest bridged_variable_function -model = MOI.Utilities.Model{Float64}() -bridged_model = MOI.Bridges.Variable.Vectorize{Float64}(model) -bridged_variable, bridged_constraint = MOI.add_constrained_variable(bridged_model, MOI.GreaterThan(1.0)) - -# output - -(VariableIndex(-1), MOI.ConstraintIndex{MOI.SingleVariable,MOI.GreaterThan{Float64}}(-1)) -``` -The constrained variable in `MOI.GreaterThan(1.0)` returned is a bridged -variable as its index in negative. In `model`, a constrained variable in -`MOI.Nonnegatives` is created: -```jldoctest bridged_variable_function -inner_variables = MOI.get(model, MOI.ListOfVariableIndices()) - -# output - -1-element Array{VariableIndex,1}: - VariableIndex(1) -``` -In the functions used for adding constraints or setting the objective to -`bridged_model`, `bridged_variable` is substituted for `inner_variables[1]` plus -1: -```jldoctest bridged_variable_function -MOI.Bridges.bridged_variable_function(bridged_model, bridged_variable) - -# output - -MOI.ScalarAffineFunction{Float64}(MOI.ScalarAffineTerm{Float64}[ScalarAffineTerm{Float64}(1.0, VariableIndex(1))], 1.0) -``` -When getting [`ConstraintFunction`](@ref) or [`ObjectiveFunction`](@ref), -`inner_variables[1]` is substituted for `bridged_variable` minus 1: -```jldoctest bridged_variable_function -MOI.Bridges.unbridged_variable_function(bridged_model, inner_variables[1]) - -# output - -MOI.ScalarAffineFunction{Float64}(MOI.ScalarAffineTerm{Float64}[ScalarAffineTerm{Float64}(1.0, VariableIndex(-1))], -1.0) -``` - -!!! note - A notable exception is with [`Bridges.Variable.ZerosBridge`](@ref) where no - variable is created in the underlying model as the variables are simply - transformed to zeros. When this bridge is used, it is not possible to - recover functions with bridged variables from functions of the inner - model. Consider for instance that we create two zero variables: - ```jldoctest cannot_unbridge_zero - model = MOI.Utilities.Model{Float64}() - bridged_model = MOI.Bridges.Variable.Zeros{Float64}(model) - bridged_variables, bridged_constraint = MOI.add_constrained_variables(bridged_model, MOI.Zeros(2)) - - # output - - (MOI.VariableIndex[VariableIndex(-1), VariableIndex(-2)], MOI.ConstraintIndex{MOI.VectorOfVariables,MOI.Zeros}(-1)) - ``` - Consider the following functions in the variables of `bridged_model`: - ```jldoctest cannot_unbridge_zero - func = MOI.Utilities.operate(+, Float64, MOI.SingleVariable.(bridged_variables)...) - - # output - - MOI.ScalarAffineFunction{Float64}(MOI.ScalarAffineTerm{Float64}[ScalarAffineTerm{Float64}(1.0, VariableIndex(-1)), ScalarAffineTerm{Float64}(1.0, VariableIndex(-2))], 0.0) - ``` - We can obtain the equivalent function in the variables of `model` as follows: - ```jldoctest cannot_unbridge_zero - inner_func = MOI.Bridges.bridged_function(bridged_model, func) - - # output - - MOI.ScalarAffineFunction{Float64}(MOI.ScalarAffineTerm{Float64}[], 0.0) - ``` - However, it's not possible to invert this operation. Indeed, since the - bridged variables are substituted for zeros, we cannot deduce whether - they were present in the initial function. - ```jldoctest cannot_unbridge_zero; filter = r"Stacktrace:.*"s - MOI.Bridges.unbridged_function(bridged_model, inner_func) - - # output - - ERROR: Cannot unbridge function because some variables are bridged by variable bridges that do not support reverse mapping, e.g., `ZerosBridge`. - Stacktrace: - [1] error(::String, ::String, ::String) at ./error.jl:42 - [2] throw_if_cannot_unbridge at /home/blegat/.julia/dev/MathOptInterface/src/Bridges/Variable/map.jl:343 [inlined] - [3] unbridged_function(::MOI.Bridges.Variable.SingleBridgeOptimizer{MOI.Bridges.Variable.ZerosBridge{Float64},MOI.Utilities.Model{Float64}}, ::MOI.ScalarAffineFunction{Float64}) at /home/blegat/.julia/dev/MOI/src/Bridges/bridge_optimizer.jl:920 - [4] top-level scope at none:0 - ``` - -```@docs -Bridges.Variable.AbstractBridge Bridges.bridged_variable_function Bridges.unbridged_variable_function ``` -Below is the list of variable bridges implemented in this package. -```@docs -Bridges.Variable.ZerosBridge -Bridges.Variable.FreeBridge -Bridges.Variable.NonposToNonnegBridge -Bridges.Variable.VectorizeBridge -Bridges.Variable.SOCtoRSOCBridge -Bridges.Variable.RSOCtoSOCBridge -Bridges.Variable.RSOCtoPSDBridge -``` - -For each bridge defined in this package, a corresponding -[`Bridges.Variable.SingleBridgeOptimizer`](@ref) is available with the same -name without the "Bridge" suffix, e.g., `SplitInterval` is a -`SingleBridgeOptimizer` for the `SplitIntervalBridge`. Moreover, they are all -added in the [`Bridges.LazyBridgeOptimizer`](@ref) returned by -[`Bridges.full_bridge_optimizer`](@ref) as it calls -[`Bridges.Variable.add_all_bridges`](@ref). -```@docs -Bridges.Variable.SingleBridgeOptimizer -Bridges.Variable.add_all_bridges -``` - -### Constraint bridges - -When constraints are added with [`add_constraint`](@ref), constraint bridges -allow to return *bridged constraints* that do not correspond to -constraints of the underlying model. These constraints were enforced by an -equivalent formulation that added constraints (and possibly also variables) in -the underlying model. -For instance, consider a model bridged by the -[`Bridges.Constraint.SplitIntervalBridge`](@ref): -```jldoctest split_interval -model = MOI.Utilities.Model{Float64}() -bridged_model = MOI.Bridges.Constraint.SplitInterval{Float64}(model) -x, y = MOI.add_variables(bridged_model, 2) -func = MOI.Utilities.operate(+, Float64, MOI.SingleVariable(x), MOI.SingleVariable(y)) -c = MOI.add_constraint(bridged_model, func, MOI.Interval(1.0, 2.0)) - -# output - -MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64},MOI.Interval{Float64}}(1) -``` -We can see the constraint was bridged to two constraints, one for each bound, -in the inner model. -```jldoctest split_interval -MOI.get(model, MOI.ListOfConstraints()) - -# output - -2-element Array{Tuple{DataType,DataType},1}: - (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) - (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) -``` -However, `bridged_model` transparently hides these constraints and creates the -illusion that an interval constraint was created. -```jldoctest split_interval -MOI.get(bridged_model, MOI.ListOfConstraints()) - -# output - -1-element Array{Tuple{DataType,DataType},1}: - (MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) -``` -It is nevertheless possible to differentiate this constraint from a constraint -added to the inner model by asking whether it is bridged: -```jldoctest split_interval -MOI.Bridges.is_bridged(bridged_model, c) - -# output - -true -``` +## Constraint bridges ```@docs Bridges.Constraint.AbstractBridge +Bridges.Constraint.SingleBridgeOptimizer +Bridges.Constraint.add_all_bridges ``` -Below is the list of constraint bridges implemented in this package. +### [Bridges implemented](@id constraint_bridges_ref) + ```@docs Bridges.Constraint.GreaterToIntervalBridge Bridges.Constraint.LessToIntervalBridge @@ -309,82 +77,38 @@ Bridges.Constraint.IndicatorSOS1Bridge Bridges.Constraint.SemiToBinaryBridge Bridges.Constraint.ZeroOneBridge ``` -For each bridge defined in this package, a corresponding -[`Bridges.Constraint.SingleBridgeOptimizer`](@ref) is available with the same -name without the "Bridge" suffix, e.g., `SplitInterval` is a -`SingleBridgeOptimizer` for the `SplitIntervalBridge`. Moreover, they are all -added in the [`Bridges.LazyBridgeOptimizer`](@ref) returned by -[`Bridges.full_bridge_optimizer`](@ref) as it calls -[`Bridges.Constraint.add_all_bridges`](@ref). -```@docs -Bridges.Constraint.SingleBridgeOptimizer -Bridges.Constraint.add_all_bridges -``` - -### Objective bridges -When an objective is set with [`set`](@ref), objective bridges -allow to set a *bridged objective* to the underlying model that do not -correspond to the objective set by the user. This equivalent formulation may add -constraints (and possibly also variables) in the underlying model in addition -to setting an objective function. +## [Variable bridges](@id ref_variable_bridges) ```@docs -Bridges.Objective.AbstractBridge +Bridges.Variable.AbstractBridge +Bridges.Variable.SingleBridgeOptimizer +Bridges.Variable.add_all_bridges ``` -Below is the list of objective bridges implemented in this package. +### [Bridges implemented](@id variable_bridges_ref) + ```@docs -Bridges.Objective.SlackBridge -Bridges.Objective.FunctionizeBridge +Bridges.Variable.ZerosBridge +Bridges.Variable.FreeBridge +Bridges.Variable.NonposToNonnegBridge +Bridges.Variable.VectorizeBridge +Bridges.Variable.SOCtoRSOCBridge +Bridges.Variable.RSOCtoSOCBridge +Bridges.Variable.RSOCtoPSDBridge ``` -For each bridge defined in this package, a corresponding -[`Bridges.Objective.SingleBridgeOptimizer`](@ref) is available with the same -name without the "Bridge" suffix, e.g., `Slack` is a `SingleBridgeOptimizer` -for the `SlackBridge`. Moreover, they are all added in the -[`Bridges.LazyBridgeOptimizer`](@ref) returned by -[`Bridges.full_bridge_optimizer`](@ref) as it calls -[`Bridges.Objective.add_all_bridges`](@ref). + +## Objective bridges + ```@docs +Bridges.Objective.AbstractBridge Bridges.Objective.SingleBridgeOptimizer Bridges.Objective.add_all_bridges ``` -### Bridge interface - -A bridge should implement the following functions to be usable by a bridge optimizer: -```@docs -Bridges.added_constrained_variable_types -Bridges.added_constraint_types -``` -Additionally, variable bridges should implement: -```@docs -Bridges.Variable.supports_constrained_variable -Bridges.Variable.concrete_bridge_type -Bridges.Variable.bridge_constrained_variable -``` -constraint bridges should implement: -```@docs -supports_constraint(::Type{<:Bridges.Constraint.AbstractBridge}, ::Type{<:AbstractFunction}, ::Type{<:AbstractSet}) -Bridges.Constraint.concrete_bridge_type -Bridges.Constraint.bridge_constraint -``` -and objective bridges should implement: -```@docs -Bridges.set_objective_function_type -Bridges.Objective.concrete_bridge_type -Bridges.Objective.bridge_objective -``` +### [Bridges implemented](@id objective_bridges_ref) -When querying the [`NumberOfVariables`](@ref), [`NumberOfConstraints`](@ref) -and [`ListOfConstraintIndices`](@ref), the variables and constraints created -by the bridges in the underlying model are hidden by the bridge optimizer. -For this purpose, the bridge should provide access to the variables and -constraints it has creates by implemented the following methods of -[`get`](@ref): ```@docs -get(::Bridges.Constraint.AbstractBridge, ::NumberOfVariables) -get(::Bridges.Constraint.AbstractBridge, ::ListOfVariableIndices) -get(::Bridges.AbstractBridge, ::NumberOfConstraints) -get(::Bridges.AbstractBridge, ::ListOfConstraintIndices) +Bridges.Objective.SlackBridge +Bridges.Objective.FunctionizeBridge ```