Skip to content

Commit 95e525d

Browse files
committed
ToFunctionTypeBridge
1 parent 5ca6d63 commit 95e525d

File tree

5 files changed

+140
-194
lines changed

5 files changed

+140
-194
lines changed

docs/src/submodules/Utilities/reference.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ Utilities.get_fallback
154154
The following utilities are available for functions:
155155

156156
```@docs
157+
supports_convert
157158
Utilities.eval_variables
158159
Utilities.map_indices
159160
Utilities.substitute_variables

src/Bridges/Constraint/bridges/functionize.jl

Lines changed: 80 additions & 191 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,6 @@ function MOI.delete(model::MOI.ModelLike, c::AbstractFunctionConversionBridge)
103103
return
104104
end
105105

106-
function MOI.get(
107-
model::MOI.ModelLike,
108-
attr::MOI.CanonicalConstraintFunction,
109-
b::AbstractFunctionConversionBridge,
110-
)
111-
f = MOI.get(model, MOI.ConstraintFunction(), b)
112-
return MOI.Utilities.canonical(f)
113-
end
114-
115106
function MOI.set(
116107
model::MOI.ModelLike,
117108
::MOI.ConstraintFunction,
@@ -166,250 +157,148 @@ function invariant_under_function_conversion(
166157
end
167158

168159
"""
169-
ScalarFunctionizeBridge{T,S} <: Bridges.Constraint.AbstractBridge
160+
FunctionConversionBridge{T,F,G,S} <: AbstractFunctionConversionBridge{G,S}
170161
171-
`ScalarFunctionizeBridge` implements the following reformulations:
162+
`FunctionConversionBridge` implements the following reformulations:
172163
173-
* ``x \\in S`` into ``1x + 0 \\in S``
164+
* ``g(x) \\in S`` into ``f(x) \\in S``
165+
166+
for these pairs of functions:
167+
168+
* [`MOI.ScalarAffineFunction`](@ref)` to [`MOI.ScalarQuadraticFunction`](@ref)
169+
* [`MOI.ScalarQuadraticFunction`](@ref) to [`MOI.ScalarNonlinearFunction`](@ref)
170+
* [`MOI.VectorAffineFunction`](@ref) to [`MOI.VectorQuadraticFunction`](@ref)
174171
175172
## Source node
176173
177-
`ScalarFunctionizeBridge` supports:
174+
`FunctionConversionBridge` supports:
178175
179-
* [`MOI.VariableIndex`](@ref) in `S`
176+
* `G` in `S`
180177
181178
## Target nodes
182179
183-
`ScalarFunctionizeBridge` creates:
180+
`FunctionConversionBridge` creates:
184181
185-
* [`MOI.ScalarAffineFunction{T}`](@ref) in `S`
182+
* `F` in `S`
186183
"""
187-
struct ScalarFunctionizeBridge{T,S} <:
188-
AbstractFunctionConversionBridge{MOI.ScalarAffineFunction{T},S}
189-
constraint::MOI.ConstraintIndex{MOI.ScalarAffineFunction{T},S}
184+
mutable struct FunctionConversionBridge{T,F,G,S} <:
185+
AbstractFunctionConversionBridge{F,S}
186+
constraint::MOI.ConstraintIndex{F,S}
190187
end
191-
192-
const ScalarFunctionize{T,OT<:MOI.ModelLike} =
193-
SingleBridgeOptimizer{ScalarFunctionizeBridge{T},OT}
188+
# The `struct` needs to be mutable if `F <: AbstractVectorFunction`
189+
# in case one row is deleted. See `MOI.delete` above.
194190

195191
function bridge_constraint(
196-
::Type{ScalarFunctionizeBridge{T,S}},
197-
model,
198-
f::MOI.VariableIndex,
192+
::Type{FunctionConversionBridge{T,F,G,S}},
193+
model::MOI.ModelLike,
194+
f::G,
199195
s::S,
200-
) where {T,S}
201-
ci = MOI.add_constraint(model, convert(MOI.ScalarAffineFunction{T}, f), s)
202-
return ScalarFunctionizeBridge{T,S}(ci)
196+
) where {T,F,G,S}
197+
ci = MOI.add_constraint(model, convert(F, f), s)
198+
return FunctionConversionBridge{T,F,G,S}(ci)
203199
end
204200

205201
function MOI.supports_constraint(
206-
::Type{ScalarFunctionizeBridge{T}},
207-
::Type{<:MOI.VariableIndex},
208-
::Type{<:MOI.AbstractScalarSet},
209-
) where {T}
210-
return true
202+
::Type{<:FunctionConversionBridge{T,F}},
203+
::Type{G},
204+
::Type{<:MOI.AbstractSet},
205+
) where {T,F,G<:MOI.AbstractFunction}
206+
return MOI.supports_convert(F, G)
211207
end
212208

213209
function concrete_bridge_type(
214-
::Type{<:ScalarFunctionizeBridge{T}},
215-
::Type{MOI.VariableIndex},
216-
S::Type{<:MOI.AbstractScalarSet},
217-
) where {T}
218-
return ScalarFunctionizeBridge{T,S}
210+
::Type{<:FunctionConversionBridge{T,F}},
211+
G::Type{<:MOI.AbstractFunction},
212+
S::Type{<:MOI.AbstractSet},
213+
) where {T,F}
214+
return FunctionConversionBridge{T,F,G,S}
219215
end
220216

221217
function MOI.get(
222218
model::MOI.ModelLike,
223219
::MOI.ConstraintFunction,
224-
b::ScalarFunctionizeBridge,
225-
)
220+
b::FunctionConversionBridge{T,F,G},
221+
) where {T,F,G}
226222
f = MOI.get(model, MOI.ConstraintFunction(), b.constraint)
227-
return convert(MOI.VariableIndex, f)
223+
return convert(G, f)
228224
end
229225

230226
"""
231-
VectorFunctionizeBridge{T,S} <: Bridges.Constraint.AbstractBridge
232227
233-
`VectorFunctionizeBridge` implements the following reformulations:
228+
ScalarFunctionizeBridge{T,S} = FunctionConversionBridge{T,MOI.ScalarAffineFunction{T},MOI.VariableIndex,S}
234229
235-
* ``x \\in S`` into ``Ix + 0 \\in S``
230+
`ScalarFunctionizeBridge` implements the following reformulations:
231+
232+
* ``x \\in S`` into ``1x + 0 \\in S``
236233
237234
## Source node
238235
239-
`VectorFunctionizeBridge` supports:
236+
`ScalarFunctionizeBridge` supports:
240237
241-
* [`MOI.VectorOfVariables`](@ref) in `S`
238+
* [`MOI.VariableIndex`](@ref) in `S`
242239
243240
## Target nodes
244241
245-
`VectorFunctionizeBridge` creates:
242+
`ScalarFunctionizeBridge` creates:
246243
247-
* [`MOI.VectorAffineFunction{T}`](@ref) in `S`
244+
* [`MOI.ScalarAffineFunction{T}`](@ref) in `S`
248245
"""
249-
mutable struct VectorFunctionizeBridge{T,S} <:
250-
AbstractFunctionConversionBridge{MOI.VectorAffineFunction{T},S}
251-
constraint::MOI.ConstraintIndex{MOI.VectorAffineFunction{T},S}
252-
end
253-
254-
const VectorFunctionize{T,OT<:MOI.ModelLike} =
255-
SingleBridgeOptimizer{VectorFunctionizeBridge{T},OT}
256-
257-
function bridge_constraint(
258-
::Type{VectorFunctionizeBridge{T,S}},
259-
model,
260-
f::MOI.VectorOfVariables,
261-
s::S,
262-
) where {T,S}
263-
ci = MOI.add_constraint(model, convert(MOI.VectorAffineFunction{T}, f), s)
264-
return VectorFunctionizeBridge{T,S}(ci)
265-
end
266-
267-
function MOI.supports_constraint(
268-
::Type{VectorFunctionizeBridge{T}},
269-
::Type{MOI.VectorOfVariables},
270-
::Type{<:MOI.AbstractVectorSet},
271-
) where {T}
272-
return true
273-
end
274-
275-
function concrete_bridge_type(
276-
::Type{<:VectorFunctionizeBridge{T}},
277-
::Type{MOI.VectorOfVariables},
278-
S::Type{<:MOI.AbstractVectorSet},
279-
) where {T}
280-
return VectorFunctionizeBridge{T,S}
281-
end
246+
const ScalarFunctionizeBridge{T,S} =
247+
FunctionConversionBridge{T,MOI.ScalarAffineFunction{T},MOI.VariableIndex,S}
248+
const ScalarFunctionize{T,OT<:MOI.ModelLike} =
249+
SingleBridgeOptimizer{ScalarFunctionizeBridge{T},OT}
282250

283-
function MOI.get(
284-
model::MOI.ModelLike,
285-
::MOI.ConstraintFunction,
286-
b::VectorFunctionizeBridge,
287-
)
288-
f = MOI.get(model, MOI.ConstraintFunction(), b.constraint)
289-
return MOI.Utilities.convert_approx(MOI.VectorOfVariables, f)
290-
end
251+
# VectorOfVariables -> VectorAffineFunction # Handled by VectorFunctionizeBridge
291252

292253
"""
293-
FunctionConversionBridge{T,F,G,S} <: AbstractFunctionConversionBridge{G,S}
294-
295-
`FunctionConversionBridge` implements the following reformulations:
254+
VectorFunctionizeBridge{T,S} = FunctionConversionBridge{T,MOI.VectorAffineFunction{T},S}
296255
297-
* ``f(x) \\in S`` into ``g(x) \\in S``
298-
299-
for these pairs of functions:
256+
`VectorFunctionizeBridge` implements the following reformulations:
300257
301-
* [`MOI.ScalarAffineFunction`](@ref)` to [`MOI.ScalarQuadraticFunction`](@ref)
302-
* [`MOI.ScalarQuadraticFunction`](@ref) to [`MOI.ScalarNonlinearFunction`](@ref)
303-
* [`MOI.VectorAffineFunction`](@ref) to [`MOI.VectorQuadraticFunction`](@ref)
258+
* ``x \\in S`` into ``Ix + 0 \\in S``
304259
305260
## Source node
306261
307-
`FunctionConversionBridge` supports:
262+
`VectorFunctionizeBridge` supports:
308263
309-
* `F` in `S`
264+
* [`MOI.VectorOfVariables`](@ref) in `S`
310265
311266
## Target nodes
312267
313-
`FunctionConversionBridge` creates:
268+
`VectorFunctionizeBridge` creates:
314269
315-
* `G` in `S`
270+
* [`MOI.VectorAffineFunction{T}`](@ref) in `S`
316271
"""
317-
struct FunctionConversionBridge{T,F,G,S} <:
318-
AbstractFunctionConversionBridge{G,S}
319-
constraint::MOI.ConstraintIndex{G,S}
320-
end
321-
322-
const FunctionConversion{T,OT<:MOI.ModelLike} =
323-
SingleBridgeOptimizer{FunctionConversionBridge{T},OT}
324-
325-
function bridge_constraint(
326-
::Type{FunctionConversionBridge{T,F,G,S}},
327-
model::MOI.ModelLike,
328-
f::F,
329-
s::S,
330-
) where {T,F,G,S}
331-
ci = MOI.add_constraint(model, convert(G, f), s)
332-
return FunctionConversionBridge{T,F,G,S}(ci)
333-
end
272+
const VectorFunctionizeBridge{T,S} = FunctionConversionBridge{
273+
T,
274+
MOI.VectorAffineFunction{T},
275+
MOI.VectorOfVariables,
276+
S,
277+
}
334278

335-
function MOI.get(
336-
model::MOI.ModelLike,
337-
::MOI.ConstraintFunction,
338-
b::FunctionConversionBridge{T,F},
339-
) where {T,F}
340-
g = MOI.get(model, MOI.ConstraintFunction(), b.constraint)
341-
return convert(F, g)
342-
end
279+
const VectorFunctionize{T,OT<:MOI.ModelLike} =
280+
SingleBridgeOptimizer{VectorFunctionizeBridge{T},OT}
343281

344-
# VariableIndex -> ScalarAffineFunction # Handled by ScalarFunctionizeBridge
282+
# AbstractScalarFunction -> ScalarQuadraticFunction
345283

346-
# ScalarAffineFunction -> ScalarQuadraticFunction
284+
const ToScalarQuadraticBridge{T,G,S} =
285+
FunctionConversionBridge{T,MOI.ScalarQuadraticFunction{T},G,S}
347286

348-
function MOI.supports_constraint(
349-
::Type{<:FunctionConversionBridge{T}},
350-
::Type{MOI.ScalarAffineFunction{T}},
351-
::Type{<:MOI.AbstractScalarSet},
352-
) where {T}
353-
return true
354-
end
287+
const ToScalarQuadratic{T,OT<:MOI.ModelLike} =
288+
SingleBridgeOptimizer{ToScalarQuadraticBridge{T},OT}
355289

356-
function concrete_bridge_type(
357-
::Type{<:FunctionConversionBridge{T}},
358-
::Type{MOI.ScalarAffineFunction{T}},
359-
S::Type{<:MOI.AbstractScalarSet},
360-
) where {T}
361-
return FunctionConversionBridge{
362-
T,
363-
MOI.ScalarAffineFunction{T},
364-
MOI.ScalarQuadraticFunction{T},
365-
S,
366-
}
367-
end
290+
# AbstractVectorFunction -> VectorQuadraticFunction
368291

369-
# ScalarQuadraticFunction -> ScalarNonlinearFunction
292+
const ToVectorQuadraticBridge{T,G,S} =
293+
FunctionConversionBridge{T,MOI.VectorQuadraticFunction{T},G,S}
370294

371-
function MOI.supports_constraint(
372-
::Type{<:FunctionConversionBridge{T}},
373-
::Type{MOI.ScalarQuadraticFunction{T}},
374-
::Type{<:MOI.AbstractScalarSet},
375-
) where {T}
376-
return true
377-
end
295+
const ToVectorQuadratic{T,OT<:MOI.ModelLike} =
296+
SingleBridgeOptimizer{ToVectorQuadraticBridge{T},OT}
378297

379-
function concrete_bridge_type(
380-
::Type{<:FunctionConversionBridge{T}},
381-
::Type{MOI.ScalarQuadraticFunction{T}},
382-
S::Type{<:MOI.AbstractScalarSet},
383-
) where {T}
384-
return FunctionConversionBridge{
385-
T,
386-
MOI.ScalarQuadraticFunction{T},
387-
MOI.ScalarNonlinearFunction,
388-
S,
389-
}
390-
end
298+
# AbstractScalarFunction -> ScalarNonlinearFunction
391299

392-
# VectorOfVariables -> VectorAffineFunction # Handled by VectorFunctionizeBridge
300+
const ToScalarNonlinearBridge{T,G,S} =
301+
FunctionConversionBridge{T,MOI.ScalarNonlinearFunction,G,S}
393302

394-
# VectorAffineFunction -> VectorQuadraticFunction
395-
396-
function MOI.supports_constraint(
397-
::Type{<:FunctionConversionBridge{T}},
398-
::Type{MOI.VectorAffineFunction{T}},
399-
::Type{<:MOI.AbstractVectorSet},
400-
) where {T}
401-
return true
402-
end
403-
404-
function concrete_bridge_type(
405-
::Type{<:FunctionConversionBridge{T}},
406-
::Type{MOI.VectorAffineFunction{T}},
407-
S::Type{<:MOI.AbstractVectorSet},
408-
) where {T}
409-
return FunctionConversionBridge{
410-
T,
411-
MOI.VectorAffineFunction{T},
412-
MOI.VectorQuadraticFunction{T},
413-
S,
414-
}
415-
end
303+
const ToScalarNonlinear{T,OT<:MOI.ModelLike} =
304+
SingleBridgeOptimizer{ToScalarNonlinearBridge{T},OT}

0 commit comments

Comments
 (0)