|
| 1 | +# `SetConversionBridge{T,S2,S1}` lets a solver backend that only |
| 2 | +# implements `MOI.add_constrained_variables(model, ::S2)` transparently |
| 3 | +# also support `@variable(model, x[1:n] in S1(...))`, for any pair of |
| 4 | +# vector sets connected by a linear map (`S2` is the set actually added to |
| 5 | +# the underlying model, `S1` is the set exposed to the user). A new `S1 => S2` pair |
| 6 | +# only has to supply `map_set` / `inverse_map_set` (how the sets relate — generic here, via |
| 7 | +# `Base.convert`) and `map_function` / `inverse_map_function` (how the |
| 8 | +# *variables* relate — necessarily specific to the pair, since `S1` and |
| 9 | +# `S2` need not even share a dimension). |
| 10 | +# |
| 11 | + |
| 12 | +""" |
| 13 | + SetConversionBridge{T,S2,S1} <: MOI.Bridges.Variable.SetMapBridge{T,S2,S1} |
| 14 | +
|
| 15 | +Bridges `MOI.VectorOfVariables`-in-`S1` (what the user asks for) to |
| 16 | +`MOI.VectorOfVariables`-in-`S2` (what gets added to the underlying model). |
| 17 | +""" |
| 18 | +struct SetConversionBridge{T,S2,S1} <: MOI.Bridges.Variable.SetMapBridge{T,S2,S1} |
| 19 | + variables::Vector{MOI.VariableIndex} |
| 20 | + constraint::MOI.ConstraintIndex{MOI.VectorOfVariables,S2} |
| 21 | +end |
| 22 | + |
| 23 | +function MOI.Bridges.map_set( |
| 24 | + ::Type{<:SetConversionBridge{T,S2,S1}}, |
| 25 | + set::S2, |
| 26 | +) where {T,S2,S1} |
| 27 | + return convert(S1, set) |
| 28 | +end |
| 29 | + |
| 30 | +function MOI.Bridges.inverse_map_set( |
| 31 | + ::Type{<:SetConversionBridge{T,S2,S1}}, |
| 32 | + set::S1, |
| 33 | +) where {T,S2,S1} |
| 34 | + return convert(S2, set) |
| 35 | +end |
| 36 | + |
| 37 | +MOI.Bridges.map_function(::Type{<:SetConversionBridge}, func) = func |
| 38 | + |
| 39 | +MOI.Bridges.inverse_map_function(::Type{<:SetConversionBridge}, func) = func |
| 40 | + |
| 41 | +# The map is the identity so it is its own adjoint; without these, setting |
| 42 | +# `MOI.ConstraintDualStart` (or getting `MOI.ConstraintDual`) on a bridged |
| 43 | +# constraint errors. |
| 44 | +MOI.Bridges.adjoint_map_function(::Type{<:SetConversionBridge}, func) = func |
| 45 | + |
| 46 | +function MOI.Bridges.inverse_adjoint_map_function( |
| 47 | + ::Type{<:SetConversionBridge}, |
| 48 | + func, |
| 49 | +) |
| 50 | + return func |
| 51 | +end |
| 52 | + |
| 53 | +""" |
| 54 | + ListToPartitionBridge{T} = SetConversionBridge{T,Partition,List} |
| 55 | +
|
| 56 | +Bridges `List(n)` to `Partition(n, 1)`, for backends that support |
| 57 | +`Partition` but not `List`. |
| 58 | +""" |
| 59 | +const ListToPartitionBridge{T} = SetConversionBridge{T,Partition,List} |
0 commit comments