|
| 1 | +# Copyright (c) 2017: Miles Lubin and contributors |
| 2 | +# Copyright (c) 2017: Google Inc. |
| 3 | +# |
| 4 | +# Use of this source code is governed by an MIT-style license that can be found |
| 5 | +# in the LICENSE.md file or at https://opensource.org/licenses/MIT. |
| 6 | + |
| 7 | +""" |
| 8 | + NumberConversionBridge{T,F1,S1,F2,S2} <: Bridges.Constraint.AbstractBridge |
| 9 | +
|
| 10 | +`NumberConversionBridge` implements the following reformulation: |
| 11 | +
|
| 12 | + * ``f1(x) \\in S1`` to ``f2(x) \\in S2`` |
| 13 | +
|
| 14 | +where `f` and `S` are the same functional form, but differ in their coefficient |
| 15 | +type. |
| 16 | +
|
| 17 | +## Source node |
| 18 | +
|
| 19 | +`NumberConversionBridge` supports: |
| 20 | +
|
| 21 | + * `F1` in `S1` |
| 22 | +
|
| 23 | +## Target node |
| 24 | +
|
| 25 | +`NumberConversionBridge` creates: |
| 26 | +
|
| 27 | + * `F2` in `S2` |
| 28 | +""" |
| 29 | +struct NumberConversionBridge{T,F1,S1,F2,S2} <: AbstractBridge |
| 30 | + constraint::MOI.ConstraintIndex{F2,S2} |
| 31 | +end |
| 32 | + |
| 33 | +const NumberConversion{T,OT<:MOI.ModelLike} = |
| 34 | + SingleBridgeOptimizer{NumberConversionBridge{T},OT} |
| 35 | + |
| 36 | +function concrete_bridge_type( |
| 37 | + ::Type{<:NumberConversionBridge{T}}, |
| 38 | + ::Type{F1}, |
| 39 | + ::Type{S1}, |
| 40 | +) where {T,F1<:MOI.AbstractFunction,S1<:MOI.AbstractSet} |
| 41 | + F2 = MOI.Utilities.similar_type(F1, T) |
| 42 | + S2 = MOI.Utilities.similar_type(S1, T) |
| 43 | + return NumberConversionBridge{T,F1,S1,F2,S2} |
| 44 | +end |
| 45 | + |
| 46 | +function bridge_constraint( |
| 47 | + ::Type{NumberConversionBridge{T,F1,S1,F2,S2}}, |
| 48 | + model::MOI.ModelLike, |
| 49 | + f::F1, |
| 50 | + set::S1, |
| 51 | +) where {T,F1,S1,F2,S2} |
| 52 | + ci = MOI.add_constraint( |
| 53 | + model, |
| 54 | + MOI.Utilities.convert_approx(F2, f), |
| 55 | + MOI.Utilities.convert_approx(S2, set), |
| 56 | + ) |
| 57 | + return NumberConversionBridge{T,F1,S1,F2,S2}(ci) |
| 58 | +end |
| 59 | + |
| 60 | +function MOI.supports_constraint( |
| 61 | + ::Type{NumberConversionBridge{T}}, |
| 62 | + ::Type{F1}, |
| 63 | + ::Type{S1}, |
| 64 | +) where {T,F1<:MOI.AbstractFunction,S1<:MOI.AbstractSet} |
| 65 | + return F1 != MOI.Utilities.similar_type(F1, T) || |
| 66 | + S1 != MOI.Utilities.similar_type(S1, T) |
| 67 | +end |
| 68 | + |
| 69 | +function MOI.Bridges.added_constrained_variable_types( |
| 70 | + ::Type{<:NumberConversionBridge}, |
| 71 | +) |
| 72 | + return Tuple{Type}[] |
| 73 | +end |
| 74 | + |
| 75 | +function MOI.Bridges.added_constraint_types( |
| 76 | + A::Type{NumberConversionBridge{T,F1,S1,F2,S2}}, |
| 77 | +) where {T,F1,S1,F2,S2} |
| 78 | + return Tuple{Type,Type}[(F2, S2)] |
| 79 | +end |
| 80 | + |
| 81 | +function MOI.get( |
| 82 | + bridge::NumberConversionBridge{T,F1,S1,F2,S2}, |
| 83 | + ::MOI.NumberOfConstraints{F2,S2}, |
| 84 | +)::Int64 where {T,F1,S1,F2,S2} |
| 85 | + return 1 |
| 86 | +end |
| 87 | + |
| 88 | +function MOI.get( |
| 89 | + bridge::NumberConversionBridge{T,F1,S1,F2,S2}, |
| 90 | + ::MOI.ListOfConstraintIndices{F2,S2}, |
| 91 | +) where {T,F1,S1,F2,S2} |
| 92 | + return [bridge.constraint] |
| 93 | +end |
| 94 | + |
| 95 | +function MOI.delete(model::MOI.ModelLike, bridge::NumberConversionBridge) |
| 96 | + MOI.delete(model, bridge.constraint) |
| 97 | + return |
| 98 | +end |
| 99 | + |
| 100 | +MOI.get(b::NumberConversionBridge, ::MOI.NumberOfVariables)::Int64 = 0 |
| 101 | + |
| 102 | +function MOI.get(b::NumberConversionBridge, ::MOI.ListOfVariableIndices) |
| 103 | + return MOI.VariableIndex[] |
| 104 | +end |
| 105 | + |
| 106 | +function MOI.get( |
| 107 | + model::MOI.ModelLike, |
| 108 | + ::MOI.ConstraintFunction, |
| 109 | + bridge::NumberConversionBridge{T,F1,S1,F2,S2}, |
| 110 | +) where {T,F1,S1,F2,S2} |
| 111 | + f = MOI.get(model, MOI.ConstraintFunction(), bridge.constraint) |
| 112 | + return MOI.Utilities.convert_approx(F1, f) |
| 113 | +end |
| 114 | + |
| 115 | +function MOI.get( |
| 116 | + model::MOI.ModelLike, |
| 117 | + ::MOI.ConstraintSet, |
| 118 | + bridge::NumberConversionBridge{T,F1,S1,F2,S2}, |
| 119 | +) where {T,F1,S1,F2,S2} |
| 120 | + s = MOI.get(model, MOI.ConstraintSet(), bridge.constraint) |
| 121 | + return MOI.Utilities.convert_approx(S1, s) |
| 122 | +end |
0 commit comments