Skip to content

Commit 0cfa93f

Browse files
authored
Add Objective.FunctionConversionBridge (#2303)
1 parent 09c1bff commit 0cfa93f

File tree

9 files changed

+265
-318
lines changed

9 files changed

+265
-318
lines changed

docs/src/submodules/Bridges/list_of_bridges.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,9 @@ These bridges are subtypes of [`Bridges.Objective.AbstractBridge`](@ref).
8888
```@docs
8989
Bridges.Objective.FunctionizeBridge
9090
Bridges.Objective.QuadratizeBridge
91-
Bridges.Objective.SlackBridge
9291
Bridges.Objective.VectorFunctionizeBridge
92+
Bridges.Objective.FunctionConversionBridge
93+
Bridges.Objective.SlackBridge
9394
Bridges.Objective.VectorSlackBridge
9495
```
9596

src/Bridges/Objective/Objective.jl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,8 @@ include("bridge.jl")
1212
include("map.jl")
1313
include("single_bridge_optimizer.jl")
1414

15-
include("bridges/functionize.jl")
16-
include("bridges/quadratize.jl")
15+
include("bridges/conversion.jl")
1716
include("bridges/slack.jl")
18-
include("bridges/vector_functionize.jl")
1917
include("bridges/vector_slack.jl")
2018

2119
"""
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
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+
FunctionConversionBridge{T,F,G} <: AbstractBridge
9+
10+
`FunctionConversionBridge` implements the following reformulations:
11+
12+
* ``\\min \\{g(x)\\}`` into ``\\min\\{f(x)\\}``
13+
* ``\\max \\{g(x)\\}`` into ``\\max\\{f(x)\\}``
14+
15+
for these pairs of functions:
16+
17+
* [`MOI.ScalarAffineFunction`](@ref)` to [`MOI.ScalarQuadraticFunction`](@ref)
18+
* [`MOI.ScalarQuadraticFunction`](@ref) to [`MOI.ScalarNonlinearFunction`](@ref)
19+
* [`MOI.VectorAffineFunction`](@ref) to [`MOI.VectorQuadraticFunction`](@ref)
20+
21+
## Source node
22+
23+
`FunctionConversionBridge` supports:
24+
25+
* [`MOI.ObjectiveFunction{G}`](@ref)
26+
27+
## Target nodes
28+
29+
`FunctionConversionBridge` creates:
30+
31+
* One objective node: [`MOI.ObjectiveFunction{F}`](@ref)
32+
"""
33+
struct FunctionConversionBridge{T,F,G} <: AbstractBridge end
34+
35+
function bridge_objective(
36+
::Type{FunctionConversionBridge{T,F,G}},
37+
model::MOI.ModelLike,
38+
func::G,
39+
) where {T,F,G<:MOI.AbstractFunction}
40+
MOI.set(model, MOI.ObjectiveFunction{F}(), convert(F, func))
41+
return FunctionConversionBridge{T,F,G}()
42+
end
43+
44+
function supports_objective_function(
45+
::Type{<:FunctionConversionBridge{T,F}},
46+
::Type{G},
47+
) where {T,F,G<:MOI.AbstractFunction}
48+
return isfinite(MOI.Bridges.Constraint.conversion_cost(F, G))
49+
end
50+
51+
function MOI.Bridges.added_constrained_variable_types(
52+
::Type{<:FunctionConversionBridge},
53+
)
54+
return Tuple{Type}[]
55+
end
56+
57+
function MOI.Bridges.added_constraint_types(::Type{<:FunctionConversionBridge})
58+
return Tuple{Type,Type}[]
59+
end
60+
61+
function MOI.Bridges.set_objective_function_type(
62+
::Type{<:FunctionConversionBridge{T,F}},
63+
) where {T,F}
64+
return F
65+
end
66+
67+
function concrete_bridge_type(
68+
::Type{<:FunctionConversionBridge{T,F}},
69+
::Type{G},
70+
) where {T,F,G<:MOI.AbstractFunction}
71+
return FunctionConversionBridge{T,F,G}
72+
end
73+
74+
# Attributes, Bridge acting as a model
75+
MOI.get(::FunctionConversionBridge, ::MOI.NumberOfVariables)::Int64 = 0
76+
77+
function MOI.get(::FunctionConversionBridge, ::MOI.ListOfVariableIndices)
78+
return MOI.VariableIndex[]
79+
end
80+
81+
# No variables or constraints are created in this bridge so there is nothing to
82+
# delete.
83+
MOI.delete(::MOI.ModelLike, ::FunctionConversionBridge) = nothing
84+
85+
function MOI.set(
86+
::MOI.ModelLike,
87+
::MOI.ObjectiveSense,
88+
::FunctionConversionBridge,
89+
::MOI.OptimizationSense,
90+
)
91+
# `FunctionConversionBridge` is sense agnostic, therefore, we don't need to
92+
# change anything.
93+
return
94+
end
95+
96+
function MOI.get(
97+
model::MOI.ModelLike,
98+
attr::MOI.Bridges.ObjectiveFunctionValue{G},
99+
::FunctionConversionBridge{T,F,G},
100+
) where {T,F,G}
101+
attr_f = MOI.Bridges.ObjectiveFunctionValue{F}(attr.result_index)
102+
return MOI.get(model, attr_f)
103+
end
104+
105+
function MOI.get(
106+
model::MOI.ModelLike,
107+
::MOI.ObjectiveFunction{G},
108+
::FunctionConversionBridge{T,F,G},
109+
) where {T,F,G<:MOI.AbstractFunction}
110+
func = MOI.get(model, MOI.ObjectiveFunction{F}())
111+
return MOI.Utilities.convert_approx(G, func)
112+
end
113+
114+
"""
115+
FunctionizeBridge{T,G} <: FunctionConversionBridge{T,MOI.ScalarAffineFunction{T},G}
116+
117+
`FunctionizeBridge` implements the following reformulations:
118+
119+
* ``\\min \\{x\\}`` into ``\\min\\{1x + 0\\}``
120+
* ``\\max \\{x\\}`` into ``\\max\\{1x + 0\\}``
121+
122+
where `T` is the coefficient type of `1` and `0`.
123+
124+
## Source node
125+
126+
`FunctionizeBridge` supports:
127+
128+
* [`MOI.ObjectiveFunction{G}`](@ref)
129+
130+
## Target nodes
131+
132+
`FunctionizeBridge` creates:
133+
134+
* One objective node: [`MOI.ObjectiveFunction{MOI.ScalarAffineFunction{T}}`](@ref)
135+
"""
136+
const FunctionizeBridge{T,G} =
137+
FunctionConversionBridge{T,MOI.ScalarAffineFunction{T},G}
138+
139+
const Functionize{T,OT<:MOI.ModelLike} =
140+
SingleBridgeOptimizer{FunctionizeBridge{T},OT}
141+
142+
"""
143+
QuadratizeBridge{T,G} <: FunctionConversionBridge{T,MOI.ScalarQuadraticFunction{T},G}
144+
145+
`QuadratizeBridge` implements the following reformulations:
146+
147+
* ``\\min \\{a^\\top x + b\\}`` into ``\\min\\{x^\\top \\mathbf{0} x + a^\\top x + b\\}``
148+
* ``\\max \\{a^\\top x + b\\}`` into ``\\max\\{x^\\top \\mathbf{0} x + a^\\top x + b\\}``
149+
150+
where `T` is the coefficient type of `0`.
151+
152+
## Source node
153+
154+
`QuadratizeBridge` supports:
155+
156+
* [`MOI.ObjectiveFunction{G}`](@ref)
157+
158+
## Target nodes
159+
160+
`QuadratizeBridge` creates:
161+
162+
* One objective node: [`MOI.ObjectiveFunction{MOI.ScalarQuadraticFunction{T}}`](@ref)
163+
"""
164+
const QuadratizeBridge{T,G} =
165+
FunctionConversionBridge{T,MOI.ScalarQuadraticFunction{T},G}
166+
167+
const Quadratize{T,OT<:MOI.ModelLike} =
168+
SingleBridgeOptimizer{QuadratizeBridge{T},OT}
169+
170+
"""
171+
VectorFunctionizeBridge{T,G} <: FunctionConversionBridge{T,MOI.VectorAffineFunction{T},G}
172+
173+
`VectorFunctionizeBridge` implements the following reformulations:
174+
175+
* ``\\min \\{x\\}`` into ``\\min\\{1x + 0\\}``
176+
* ``\\max \\{x\\}`` into ``\\max\\{1x + 0\\}``
177+
178+
where `T` is the coefficient type of `1` and `0`.
179+
180+
## Source node
181+
182+
`VectorFunctionizeBridge` supports:
183+
184+
* [`MOI.ObjectiveFunction{G}`](@ref)
185+
186+
## Target nodes
187+
188+
`VectorFunctionizeBridge` creates:
189+
190+
* One objective node: [`MOI.ObjectiveFunction{MOI.VectorAffineFunction{T}}`](@ref)
191+
"""
192+
const VectorFunctionizeBridge{T,G} =
193+
FunctionConversionBridge{T,MOI.VectorAffineFunction{T},G}
194+
195+
const VectorFunctionize{T,OT<:MOI.ModelLike} =
196+
SingleBridgeOptimizer{VectorFunctionizeBridge{T},OT}

src/Bridges/Objective/bridges/functionize.jl

Lines changed: 0 additions & 107 deletions
This file was deleted.

0 commit comments

Comments
 (0)