Skip to content

Commit 160bcdf

Browse files
committed
[Bridges] add ExponentialConeToScalarNonlinearFunctionBridge
1 parent 5098bd7 commit 160bcdf

File tree

4 files changed

+227
-0
lines changed

4 files changed

+227
-0
lines changed

src/Bridges/Constraint/Constraint.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ function add_all_bridges(bridged_model, ::Type{T}) where {T}
108108
MOI.Bridges.add_bridge(bridged_model, SOS1ToMILPBridge{T})
109109
MOI.Bridges.add_bridge(bridged_model, SOS2ToMILPBridge{T})
110110
MOI.Bridges.add_bridge(bridged_model, IndicatorToMILPBridge{T})
111+
112+
MOI.Bridges.add_bridge(
113+
bridged_model,
114+
ExponentialConeToScalarNonlinearFunctionBridge{T},
115+
)
111116
return
112117
end
113118

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
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+
ExponentialConeToScalarNonlinearFunctionBridge{T,F} <:
9+
Bridges.Constraint.AbstractBridge
10+
11+
`ExponentialConeToScalarNonlinearFunctionBridge` implements the following
12+
reformulation:
13+
14+
* ``(x, y, z) \\in \\textsf{ExponentialCone}()`` to
15+
``y \\cdot exp(x / y)) - z \\le 0``, ``y \\ge 0``.
16+
17+
## Source node
18+
19+
`ExponentialConeToScalarNonlinearFunctionBridge` supports:
20+
21+
* `F` in [`MOI.ExponentialCone`](@ref)
22+
23+
## Target nodes
24+
25+
`ExponentialConeToScalarNonlinearFunctionBridge` creates:
26+
27+
* [`MOI.ScalarNonlinearFunction`](@ref) in [`MOI.LessThan{T}`](@ref)
28+
* [`MOI.ScalarAffineFunction`](@ref) in [`MOI.GreaterThan{T}`](@ref)
29+
"""
30+
mutable struct ExponentialConeToScalarNonlinearFunctionBridge{
31+
T,
32+
F<:Union{MOI.VectorOfVariables,MOI.VectorAffineFunction{T}},
33+
} <: AbstractBridge
34+
f::F
35+
ci::MOI.ConstraintIndex{MOI.ScalarNonlinearFunction,MOI.LessThan{T}}
36+
ci_y::MOI.ConstraintIndex{MOI.ScalarAffineFunction{T},MOI.GreaterThan{T}}
37+
end
38+
39+
const ExponentialToScalarNonlinearFunction{T,OT<:MOI.ModelLike} =
40+
SingleBridgeOptimizer{ExponentialConeToScalarNonlinearFunctionBridge{T},OT}
41+
42+
function bridge_constraint(
43+
::Type{ExponentialConeToScalarNonlinearFunctionBridge{T,F}},
44+
model::MOI.ModelLike,
45+
f::F,
46+
s::MOI.ExponentialCone,
47+
) where {T,F<:Union{MOI.VectorOfVariables,MOI.VectorAffineFunction{T}}}
48+
x, y, z = MOI.Utilities.scalarize(f)
49+
g_x_div_y = MOI.ScalarNonlinearFunction(:/, Any[x, y])
50+
g_exp_x_div_y = MOI.ScalarNonlinearFunction(:exp, Any[g_x_div_y])
51+
g = MOI.ScalarNonlinearFunction(
52+
:-,
53+
Any[MOI.ScalarNonlinearFunction(:*, Any[y, g_exp_x_div_y]), z],
54+
)
55+
ci = MOI.add_constraint(model, g, MOI.LessThan(zero(T)))
56+
ci_y = MOI.add_constraint(model, one(T) * y, MOI.GreaterThan(zero(T)))
57+
return ExponentialConeToScalarNonlinearFunctionBridge{T,F}(f, ci, ci_y)
58+
end
59+
60+
function MOI.supports_constraint(
61+
::Type{<:ExponentialConeToScalarNonlinearFunctionBridge{T}},
62+
::Type{<:Union{MOI.VectorOfVariables,MOI.VectorAffineFunction{T}}},
63+
::Type{MOI.ExponentialCone},
64+
) where {T}
65+
return true
66+
end
67+
68+
function MOI.Bridges.added_constrained_variable_types(
69+
::Type{ExponentialConeToScalarNonlinearFunctionBridge{T,F}},
70+
) where {T,F}
71+
return Tuple{Type}[]
72+
end
73+
74+
function MOI.Bridges.added_constraint_types(
75+
::Type{ExponentialConeToScalarNonlinearFunctionBridge{T,F}},
76+
) where {T,F}
77+
return Tuple{Type,Type}[
78+
(MOI.ScalarNonlinearFunction, MOI.LessThan{T}),
79+
(MOI.ScalarAffineFunction{T}, MOI.GreaterThan{T}),
80+
]
81+
end
82+
83+
function concrete_bridge_type(
84+
::Type{<:ExponentialConeToScalarNonlinearFunctionBridge{T}},
85+
::Type{F},
86+
::Type{MOI.ExponentialCone},
87+
) where {T,F<:Union{MOI.VectorOfVariables,MOI.VectorAffineFunction{T}}}
88+
return ExponentialConeToScalarNonlinearFunctionBridge{T,F}
89+
end
90+
91+
function MOI.get(
92+
::MOI.ModelLike,
93+
::MOI.ConstraintFunction,
94+
bridge::ExponentialConeToScalarNonlinearFunctionBridge,
95+
)
96+
return copy(bridge.f)
97+
end
98+
99+
function MOI.get(
100+
::MOI.ModelLike,
101+
::MOI.ConstraintSet,
102+
::ExponentialConeToScalarNonlinearFunctionBridge,
103+
)
104+
return MOI.ExponentialCone()
105+
end
106+
107+
function MOI.delete(
108+
model::MOI.ModelLike,
109+
bridge::ExponentialConeToScalarNonlinearFunctionBridge,
110+
)
111+
MOI.delete(model, bridge.ci)
112+
MOI.delete(model, bridge.ci_y)
113+
return
114+
end
115+
116+
function MOI.get(
117+
::ExponentialConeToScalarNonlinearFunctionBridge,
118+
::MOI.NumberOfVariables,
119+
)::Int64
120+
return 0
121+
end
122+
123+
function MOI.get(
124+
::ExponentialConeToScalarNonlinearFunctionBridge,
125+
::MOI.ListOfVariableIndices,
126+
)::Vector{MOI.VariableIndex}
127+
return MOI.VariableIndex[]
128+
end
129+
130+
function MOI.get(
131+
bridge::ExponentialConeToScalarNonlinearFunctionBridge{T},
132+
::MOI.NumberOfConstraints{MOI.ScalarNonlinearFunction,MOI.LessThan{T}},
133+
)::Int64 where {T}
134+
return 1
135+
end
136+
137+
function MOI.get(
138+
bridge::ExponentialConeToScalarNonlinearFunctionBridge{T},
139+
::MOI.ListOfConstraintIndices{MOI.ScalarNonlinearFunction,MOI.LessThan{T}},
140+
) where {T}
141+
return [bridge.ci]
142+
end
143+
144+
function MOI.get(
145+
bridge::ExponentialConeToScalarNonlinearFunctionBridge{T},
146+
::MOI.NumberOfConstraints{
147+
MOI.ScalarAffineFunction{T},
148+
MOI.GreaterThan{T},
149+
},
150+
)::Int64 where {T}
151+
return 1
152+
end
153+
154+
function MOI.get(
155+
bridge::ExponentialConeToScalarNonlinearFunctionBridge{T},
156+
::MOI.ListOfConstraintIndices{
157+
MOI.ScalarAffineFunction{T},
158+
MOI.GreaterThan{T},
159+
},
160+
) where {T}
161+
return [bridge.ci_y]
162+
end

src/Utilities/parser.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ function _parsed_to_moi(model, s::Expr)
244244
return _parsed_scalar_to_moi(model, s.args[2])
245245
elseif Meta.isexpr(s, :call, 2) && s.args[1] == :VectorNonlinearFunction
246246
return _parsed_vector_to_moi(model, s.args[2])
247+
elseif Meta.isexpr(s, :call, 2) && s.args[1] == :esc
248+
return _parsed_to_moi(model, _parse_function(s.args[2], Float64))
247249
end
248250
args = Any[_parsed_to_moi(model, arg) for arg in s.args[2:end]]
249251
return MOI.ScalarNonlinearFunction(s.args[1], args)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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+
module TestConstraintExponentialConeToScalarNonlinearFunctionBridge
8+
9+
using Test
10+
11+
import MathOptInterface as MOI
12+
13+
function runtests()
14+
for name in names(@__MODULE__; all = true)
15+
if startswith("$(name)", "test_")
16+
@testset "$(name)" begin
17+
getfield(@__MODULE__, name)()
18+
end
19+
end
20+
end
21+
return
22+
end
23+
24+
function test_runtests_VectorOfVariables()
25+
MOI.Bridges.runtests(
26+
MOI.Bridges.Constraint.ExponentialConeToScalarNonlinearFunctionBridge,
27+
"""
28+
variables: x, y, z
29+
[x, y, z] in ExponentialCone()
30+
""",
31+
"""
32+
variables: x, y, z
33+
ScalarNonlinearFunction(y * exp(x / y) - z) <= 0.0
34+
1.0 * y >= 0.0
35+
""",
36+
)
37+
return
38+
end
39+
40+
function test_runtests_VectorAffineFunction()
41+
MOI.Bridges.runtests(
42+
MOI.Bridges.Constraint.ExponentialConeToScalarNonlinearFunctionBridge,
43+
"""
44+
variables: x, y, z
45+
[1.0 * x, 2.0 * y, 3.0 * z + 1.0] in ExponentialCone()
46+
""",
47+
"""
48+
variables: x, y, z
49+
ScalarNonlinearFunction(esc(2.0 * y) * exp(esc(1.0 * x) / esc(2.0 * y)) - esc(3.0 * z + 1.0)) <= 0.0
50+
2.0 * y >= 0.0
51+
""",
52+
)
53+
return
54+
end
55+
56+
end # module
57+
58+
TestConstraintExponentialConeToScalarNonlinearFunctionBridge.runtests()

0 commit comments

Comments
 (0)