Skip to content

Commit 2124676

Browse files
committed
Add SOCtoQuad bridge
1 parent 7259328 commit 2124676

File tree

9 files changed

+392
-95
lines changed

9 files changed

+392
-95
lines changed

src/Bridges/Bridges.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ include("lazybridgeoptimizer.jl")
2525

2626
# This is used by JuMP and removes the need to update JuMP everytime a bridge is added
2727
MOIU.@model AllBridgedConstraints () (Interval,) (SecondOrderCone, RotatedSecondOrderCone, GeometricMeanCone, LogDetConeTriangle, RootDetConeTriangle) () () (ScalarAffineFunction,) (VectorOfVariables,) (VectorAffineFunction,)
28+
2829
"""
2930
fullbridgeoptimizer(model::MOI.ModelLike, ::Type{T}) where T
3031
@@ -33,20 +34,23 @@ Returns a `LazyBridgeOptimizer` bridging `model` for every bridge defined in thi
3334
function fullbridgeoptimizer(model::MOI.ModelLike, ::Type{T}) where T
3435
bridgedmodel = MOIB.LazyBridgeOptimizer(model, AllBridgedConstraints{T}())
3536
addbridge!(bridgedmodel, MOIB.SplitIntervalBridge{T})
37+
addbridge!(bridgedmodel, MOIB.RSOCBridge{T})
38+
addbridge!(bridgedmodel, MOIB.SOCtoQuadBridge{T})
3639
addbridge!(bridgedmodel, MOIB.GeoMeanBridge{T})
3740
addbridge!(bridgedmodel, MOIB.SquarePSDBridge{T})
3841
addbridge!(bridgedmodel, MOIB.LogDetBridge{T})
3942
addbridge!(bridgedmodel, MOIB.RootDetBridge{T})
40-
addbridge!(bridgedmodel, MOIB.RSOCBridge{T})
41-
addbridge!(bridgedmodel, MOIB.RSOCtoPSDCBridge{T})
4243
addbridge!(bridgedmodel, MOIB.SOCtoPSDCBridge{T})
44+
addbridge!(bridgedmodel, MOIB.RSOCtoPSDCBridge{T})
4345
bridgedmodel
4446
end
4547

4648
include("intervalbridge.jl")
4749
@bridge SplitInterval SplitIntervalBridge () (Interval,) () () (SingleVariable,) (ScalarAffineFunction, ScalarQuadraticFunction) () ()
4850
include("rsocbridge.jl")
4951
@bridge RSOC RSOCBridge () () (RotatedSecondOrderCone,) () () () (VectorOfVariables,) (VectorAffineFunction,)
52+
include("soctoquadbridge.jl")
53+
@bridge SOCtoQuad SOCtoQuadBridge () () (SecondOrderCone,) () () () (VectorOfVariables,) (VectorAffineFunction,)
5054
include("geomeanbridge.jl")
5155
@bridge GeoMean GeoMeanBridge () () (GeometricMeanCone,) () () () (VectorOfVariables,) (VectorAffineFunction,)
5256
include("squarepsdbridge.jl")

src/Bridges/bridge.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,11 @@ function concrete_bridge_type(bridge_type::DataType,
7676
::Type{<:MOI.AbstractSet})
7777
return bridge_type
7878
end
79+
80+
"""
81+
need_constraint_primal_fallback(BT::Type{<:AbstractBridge})
82+
83+
Return a `Bool` indicating whether bridges of concrete type `BT` need the bridge
84+
optimizer to use `get_fallback`.
85+
"""
86+
need_constraint_primal_fallback(::Type{<:AbstractBridge}) = false

src/Bridges/bridgeoptimizer.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,30 @@ function MOI.get(b::AbstractBridgeOptimizer, attr::ResultConstraintAttribute,
250250
MOI.get(b.model, attr, ci)
251251
end
252252
end
253+
function MOI.canget(b::AbstractBridgeOptimizer, attr::MOI.ConstraintPrimal,
254+
ci::Type{CI{F, S}}) where {F, S}
255+
if isbridged(b, F, S)
256+
if need_constraint_primal_fallback(concrete_bridge_type(b, F, S))
257+
return true
258+
else
259+
return MOI.canget(b, attr, concrete_bridge_type(b, F, S))
260+
end
261+
else
262+
return MOI.canget(b.model, attr, ci)
263+
end
264+
end
265+
function MOI.get(b::AbstractBridgeOptimizer, attr::MOI.ConstraintPrimal,
266+
ci::CI{F, S}) where {F, S}
267+
if isbridged(b, typeof(ci))
268+
if need_constraint_primal_fallback(concrete_bridge_type(b, F, S))
269+
MOIU.get_fallback(b, attr, ci)
270+
else
271+
MOI.get(b, attr, bridge(b, ci))
272+
end
273+
else
274+
MOI.get(b.model, attr, ci)
275+
end
276+
end
253277
## Model constraint attributes
254278
const ModelConstraintAttribute = Union{MOI.ConstraintName,
255279
MOI.ConstraintFunction,

src/Bridges/soctoquadbridge.jl

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"""
2+
SOCtoQuadBridge{T}
3+
4+
Constraints of the form `VectorOfVariables`-in-`SecondOrderCone` (resp.
5+
`VectorAffineFunction`-in-`SecondOrderCone`) can be transformed into a
6+
`ScalarQuadraticFunction`-in-`GreaterThan` and a
7+
`SingleVariable`-in-`GreaterThan` (resp.
8+
`ScalarAffineFunction`-in-`SecondOrderCone`). Indeed, the definition of the
9+
second-order cone
10+
```math
11+
t \\ge || x ||_2 \\}
12+
```
13+
is equivalent to
14+
```math
15+
\\sum x_i^2 \\le t^2
16+
```
17+
with ``t \\ge 0``.
18+
"""
19+
struct SOCtoQuadBridge{T, F, G} <: AbstractBridge
20+
quad::CI{F, MOI.GreaterThan{T}}
21+
t_nonneg::CI{G, MOI.GreaterThan{T}}
22+
end
23+
function SOCtoQuadBridge{T, F, G}(model::MOI.ModelLike,
24+
f::MOI.AbstractVectorFunction,
25+
s::MOI.SecondOrderCone) where {T, F, G}
26+
d = s.dimension
27+
f_scalars = MOIU.eachscalar(f)
28+
t = f_scalars[1]
29+
t_nonneg = MOIU.add_scalar_constraint(model, t, MOI.GreaterThan(zero(T)))
30+
quad_f = MOIU.operate(*, T, t, t)
31+
for i in 2:d
32+
x = f_scalars[i]
33+
quad_f = MOIU.operate!(-, T, quad_f, MOIU.operate(*, T, x, x))
34+
end
35+
quad = MOIU.add_scalar_constraint(model, quad_f, MOI.GreaterThan(zero(T)))
36+
return SOCtoQuadBridge{T, F, G}(quad, t_nonneg)
37+
end
38+
39+
function MOI.supportsconstraint(::Type{SOCtoQuadBridge{T}},
40+
::Type{<:MOI.AbstractVectorFunction},
41+
::Type{MOI.SecondOrderCone}) where T
42+
return true
43+
end
44+
function addedconstrainttypes(::Type{SOCtoQuadBridge{T, F, G}}) where {T, F, G}
45+
list = [(F, MOI.GreaterThan{T})]
46+
if F != G
47+
push!(list, (G, MOI.GreaterThan{T}))
48+
end
49+
return list
50+
end
51+
function concrete_bridge_type(::Type{<:SOCtoQuadBridge{T}},
52+
H::Type{<:MOI.AbstractVectorFunction},
53+
::Type{MOI.SecondOrderCone}) where T
54+
G = MOIU.scalar_type(H)
55+
Q = MOIU.promote_operation(*, T, G, G)
56+
F = MOIU.promote_operation(-, T, Q, Q)
57+
return SOCtoQuadBridge{T, F, G}
58+
end
59+
60+
# Attributes, Bridge acting as an model
61+
function MOI.get(b::SOCtoQuadBridge{T, F, G},
62+
::MOI.NumberOfConstraints{H, MOI.GreaterThan{T}}) where {T, F, G, H}
63+
return (F == H) + (G == H)
64+
end
65+
function MOI.get(b::SOCtoQuadBridge{T, F, G},
66+
::MOI.ListOfConstraintIndices{H, MOI.GreaterThan{T}}) where {T, F, G, H}
67+
list = CI{H, MOI.GreaterThan{T}}[]
68+
if F == H
69+
push!(list, b.quad)
70+
end
71+
if G == H
72+
push!(list, b.t_nonneg)
73+
end
74+
return list
75+
end
76+
77+
# References
78+
function MOI.delete!(model::MOI.ModelLike, bridge::SOCtoQuadBridge)
79+
MOI.delete!(model, bridge.t_nonneg)
80+
MOI.delete!(model, bridge.quad)
81+
end
82+
83+
need_constraint_primal_fallback(::Type{<:SOCtoQuadBridge}) = true

src/Utilities/constraints.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
function add_scalar_constraint(model::MOI.ModelLike, func::MOI.SingleVariable,
2+
set::MOI.AbstractScalarSet)
3+
return MOI.addconstraint!(model, func, set)
4+
end
15
function add_scalar_constraint(model::MOI.ModelLike,
26
func::Union{MOI.ScalarAffineFunction{T},
37
MOI.ScalarQuadraticFunction{T}},

0 commit comments

Comments
 (0)