/
single_bridge_optimizer.jl
140 lines (117 loc) · 4.51 KB
/
single_bridge_optimizer.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# Copyright (c) 2017: Miles Lubin and contributors
# Copyright (c) 2017: Google Inc.
#
# Use of this source code is governed by an MIT-style license that can be found
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
"""
SingleBridgeOptimizer{BT<:AbstractBridge}(model::MOI.ModelLike)
Return `AbstractBridgeOptimizer` that always bridges any objective function
supported by the bridge `BT`.
This is in contrast with the [`MOI.Bridges.LazyBridgeOptimizer`](@ref),
which only bridges the objective function if it is supported by the bridge `BT`
and unsupported by `model`.
## Example
```jldoctest con_singlebridgeoptimizer; setup=:(import MathOptInterface as MOI)
julia> struct MyNewBridge{T} <: MOI.Bridges.Constraint.AbstractBridge end
julia> bridge = MOI.Bridges.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}}(
MOI.Utilities.Model{Float64}(),
)
MOIB.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
with 0 constraint bridges
with inner model MOIU.Model{Float64}
```
## Implementation notes
All bridges should simplify the creation of `SingleBridgeOptimizer`s by defining
a constant that wraps the bridge in a `SingleBridgeOptimizer`.
```jldoctest con_singlebridgeoptimizer
julia> const MyNewBridgeModel{T,OT<:MOI.ModelLike} =
MOI.Bridges.Constraint.SingleBridgeOptimizer{MyNewBridge{T},OT};
```
This enables users to create bridged models as follows:
```jldoctest con_singlebridgeoptimizer
julia> MyNewBridgeModel{Float64}(MOI.Utilities.Model{Float64}())
MOIB.Constraint.SingleBridgeOptimizer{MyNewBridge{Float64}, MOIU.Model{Float64}}
with 0 constraint bridges
with inner model MOIU.Model{Float64}
```
"""
mutable struct SingleBridgeOptimizer{BT<:AbstractBridge,OT<:MOI.ModelLike} <:
MOI.Bridges.AbstractBridgeOptimizer
model::OT
map::Map # index of bridged constraint -> constraint bridge
con_to_name::Dict{MOI.ConstraintIndex,String}
name_to_con::Union{Dict{String,MOI.ConstraintIndex},Nothing}
end
function SingleBridgeOptimizer{BT}(model::OT) where {BT,OT<:MOI.ModelLike}
return SingleBridgeOptimizer{BT,OT}(
model,
Map(),
Dict{MOI.ConstraintIndex,String}(),
nothing,
)
end
bridges(::MOI.Bridges.AbstractBridgeOptimizer) = EmptyMap()
bridges(bridge::SingleBridgeOptimizer) = bridge.map
MOI.Bridges.supports_constraint_bridges(::SingleBridgeOptimizer) = true
# If `BT` bridges `MOI.Reals` (such as `Constraint.FunctionizeBridge` bridge,
# without this method, it creates a `StackOverflow` with `is_bridged`,
# `supports_bridging_constrained_variable` and `supports_add_constrained_variables`.
MOI.Bridges.is_bridged(::SingleBridgeOptimizer, ::Type{MOI.Reals}) = false
function MOI.Bridges.is_bridged(
b::SingleBridgeOptimizer,
S::Type{<:MOI.AbstractSet},
)
return MOI.Bridges.supports_bridging_constrained_variable(b, S)
end
MOI.Bridges.is_bridged(::SingleBridgeOptimizer, ::MOI.VariableIndex) = false
function MOI.Bridges.is_bridged(
b::SingleBridgeOptimizer,
ci::MOI.ConstraintIndex{MOI.VariableIndex,S},
) where {S}
return MOI.Bridges.is_bridged(b, MOI.VariableIndex, S) &&
haskey(Constraint.bridges(b), ci)
end
function MOI.Bridges.is_bridged(
b::SingleBridgeOptimizer,
ci::MOI.ConstraintIndex{MOI.VectorOfVariables,S},
) where {S}
return MOI.Bridges.is_bridged(b, MOI.VectorOfVariables, S) &&
haskey(Constraint.bridges(b), ci)
end
function MOI.Bridges.supports_bridging_constrained_variable(
b::SingleBridgeOptimizer,
S::Type{<:MOI.AbstractSet},
)
F = MOI.Utilities.variable_function_type(S)
return MOI.Bridges.supports_bridging_constraint(b, F, S) &&
MOI.supports_add_constrained_variables(b, MOI.Reals)
end
function MOI.Bridges.supports_bridging_constraint(
::SingleBridgeOptimizer{BT},
F::Type{<:MOI.AbstractFunction},
S::Type{<:MOI.AbstractSet},
) where {BT}
return MOI.supports_constraint(BT, F, S)
end
function MOI.Bridges.is_bridged(
b::SingleBridgeOptimizer,
F::Type{<:MOI.AbstractFunction},
S::Type{<:MOI.AbstractSet},
)
return MOI.Bridges.supports_bridging_constraint(b, F, S)
end
function MOI.Bridges.is_bridged(
::SingleBridgeOptimizer,
::Type{<:MOI.AbstractFunction},
)
return false
end
function MOI.Bridges.bridge_type(
::SingleBridgeOptimizer{BT},
::Type{<:MOI.AbstractFunction},
::Type{<:MOI.AbstractSet},
) where {BT}
return BT
end
MOI.Bridges.bridging_cost(::SingleBridgeOptimizer, args...) = 1.0
MOI.Bridges.recursive_model(b::SingleBridgeOptimizer) = b.model