55# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
66
77"""
8- ComplementsToScalarNonlinearFunctionBridge{T,F} <:
8+ ComplementsToScalarNonlinearFunctionBridge{T,F,G } <:
99 Bridges.Constraint.AbstractBridge
1010
1111`ComplementsToScalarNonlinearFunctionBridge` implements the following
1212reformulation:
1313
1414 * ``(F, x) \\ in \\ textsf{Complements}()`` to
15+ ``y - F = 0`` and
1516 ```julia
1617 if isfinite(l)
17- (x - l) * F <= 0.0
18+ (x - l) * y <= 0.0
1819 else
19- 1.0 * F <= 0. 0
20+ y <= 0
2021 end
2122 if isfinite(u)
22- (x - u) * F <= 0.0
23+ (x - u) * y <= 0.0
2324 else
24- -1.0 * F <= 0. 0
25+ y >= 0
2526 end
2627 ```
2728
@@ -35,7 +36,9 @@ reformulation:
3536
3637`ComplementsToScalarNonlinearFunctionBridge` creates:
3738
38- * [`MOI.ScalarNonlinearFunction`](@ref) in [`MOI.LessThan{T}`](@ref)
39+ * `G` in [`MOI.EqualTo{T}`](@ref)
40+ * [`MOI.ScalarQuadraticFunction`](@ref) in [`MOI.LessThan{T}`](@ref)
41+ * [`MOI.VariableIndex`](@ref) in [`MOI.Interval{T}`](@ref)
3942"""
4043mutable struct ComplementsToScalarNonlinearFunctionBridge{
4144 T,
@@ -45,24 +48,38 @@ mutable struct ComplementsToScalarNonlinearFunctionBridge{
4548 MOI. VectorQuadraticFunction{T},
4649 MOI. VectorNonlinearFunction,
4750 },
51+ G,
4852} <: AbstractBridge
4953 f:: F
50- ci:: Vector{MOI.ConstraintIndex{MOI.ScalarNonlinearFunction,MOI.LessThan{T}}}
54+ y:: Vector{MOI.VariableIndex}
55+ ci_eq:: Vector{MOI.ConstraintIndex{G,MOI.EqualTo{T}}}
56+ ci_lt:: Vector {
57+ MOI. ConstraintIndex{MOI. ScalarQuadraticFunction{T},MOI. LessThan{T}}
58+ }
5159 bounds:: Vector{NTuple{2,T}}
52- function ComplementsToScalarNonlinearFunctionBridge {T} (
53- f,
60+
61+ function ComplementsToScalarNonlinearFunctionBridge {T,F,G} (
62+ f:: F ,
5463 :: MOI.Complements ,
55- ) where {T}
56- ci = MOI. ConstraintIndex{MOI. ScalarNonlinearFunction,MOI. LessThan{T}}[]
57- return new {T,typeof(f)} (f, ci, NTuple{2 ,T}[])
64+ ) where {T,F,G}
65+ return new {T,F,G} (
66+ f,
67+ MOI. VariableIndex[],
68+ MOI. ConstraintIndex{G,MOI. EqualTo{T}}[],
69+ MOI. ConstraintIndex{
70+ MOI. ScalarQuadraticFunction{T},
71+ MOI. LessThan{T},
72+ }[],
73+ NTuple{2 ,T}[],
74+ )
5875 end
5976end
6077
6178const ComplementsToScalarNonlinearFunction{T,OT<: MOI.ModelLike } =
6279 SingleBridgeOptimizer{ComplementsToScalarNonlinearFunctionBridge{T},OT}
6380
6481function bridge_constraint (
65- :: Type{ComplementsToScalarNonlinearFunctionBridge{T,F}} ,
82+ :: Type{ComplementsToScalarNonlinearFunctionBridge{T,F,G }} ,
6683 model:: MOI.ModelLike ,
6784 f:: F ,
6885 s:: MOI.Complements ,
@@ -74,10 +91,11 @@ function bridge_constraint(
7491 MOI. VectorQuadraticFunction{T},
7592 MOI. VectorNonlinearFunction,
7693 },
94+ G,
7795}
7896 # !!! info
7997 # Postpone creation until final_touch.
80- return ComplementsToScalarNonlinearFunctionBridge {T} (f, s)
98+ return ComplementsToScalarNonlinearFunctionBridge {T,F,G } (f, s)
8199end
82100
83101function MOI. supports_constraint (
@@ -97,15 +115,18 @@ function MOI.supports_constraint(
97115end
98116
99117function MOI. Bridges. added_constrained_variable_types (
100- :: Type{<: ComplementsToScalarNonlinearFunctionBridge} ,
101- )
102- return Tuple{Type}[]
118+ :: Type{ComplementsToScalarNonlinearFunctionBridge{T,F,G} } ,
119+ ) where {T,F,G}
120+ return Tuple{Type}[(MOI . Interval{T},) ]
103121end
104122
105123function MOI. Bridges. added_constraint_types (
106- :: Type{<:ComplementsToScalarNonlinearFunctionBridge{T}} ,
107- ) where {T}
108- return Tuple{Type,Type}[(MOI. ScalarNonlinearFunction, MOI. LessThan{T})]
124+ :: Type{ComplementsToScalarNonlinearFunctionBridge{T,F,G}} ,
125+ ) where {T,F,G}
126+ return Tuple{Type,Type}[
127+ (G, MOI. EqualTo{T}),
128+ (MOI. ScalarQuadraticFunction{T}, MOI. LessThan{T}),
129+ ]
109130end
110131
111132function concrete_bridge_type (
@@ -121,7 +142,13 @@ function concrete_bridge_type(
121142 MOI. VectorNonlinearFunction,
122143 },
123144}
124- return ComplementsToScalarNonlinearFunctionBridge{T,F}
145+ G = MOI. Utilities. promote_operation (
146+ - ,
147+ T,
148+ MOI. Utilities. scalar_type (F),
149+ MOI. VariableIndex,
150+ )
151+ return ComplementsToScalarNonlinearFunctionBridge{T,F,G}
125152end
126153
127154function MOI. get (
@@ -145,37 +172,72 @@ function MOI.delete(
145172 model:: MOI.ModelLike ,
146173 bridge:: ComplementsToScalarNonlinearFunctionBridge ,
147174)
148- MOI. delete .(model, bridge. ci)
175+ MOI. delete .(model, bridge. y)
176+ MOI. delete .(model, bridge. ci_eq)
177+ MOI. delete .(model, bridge. ci_lt)
149178 empty! (bridge. bounds)
150179 return
151180end
152181
153182function MOI. get (
154- :: ComplementsToScalarNonlinearFunctionBridge ,
183+ bridge :: ComplementsToScalarNonlinearFunctionBridge ,
155184 :: MOI.NumberOfVariables ,
156185):: Int64
157- return 0
186+ return length (bridge . y)
158187end
159188
160189function MOI. get (
161- :: ComplementsToScalarNonlinearFunctionBridge ,
190+ bridge :: ComplementsToScalarNonlinearFunctionBridge ,
162191 :: MOI.ListOfVariableIndices ,
163192):: Vector{MOI.VariableIndex}
164- return MOI. VariableIndex[]
193+ return copy (bridge. y)
194+ end
195+
196+ function MOI. get (
197+ bridge:: ComplementsToScalarNonlinearFunctionBridge{T,F,G} ,
198+ :: MOI.NumberOfConstraints{G,MOI.EqualTo{T}} ,
199+ ):: Int64 where {T,F,G}
200+ return length (bridge. ci_eq)
201+ end
202+
203+ function MOI. get (
204+ bridge:: ComplementsToScalarNonlinearFunctionBridge{T,F,G} ,
205+ :: MOI.ListOfConstraintIndices{G,MOI.EqualTo{T}} ,
206+ ) where {T,F,G}
207+ return copy (bridge. ci_eq)
165208end
166209
167210function MOI. get (
168211 bridge:: ComplementsToScalarNonlinearFunctionBridge{T} ,
169- :: MOI.NumberOfConstraints{MOI.ScalarNonlinearFunction ,MOI.LessThan{T}} ,
212+ :: MOI.NumberOfConstraints{MOI.ScalarQuadraticFunction{T} ,MOI.LessThan{T}} ,
170213):: Int64 where {T}
171- return length (bridge. ci )
214+ return length (bridge. ci_lt )
172215end
173216
174217function MOI. get (
175218 bridge:: ComplementsToScalarNonlinearFunctionBridge{T} ,
176- :: MOI.ListOfConstraintIndices{MOI.ScalarNonlinearFunction,MOI.LessThan{T}} ,
219+ :: MOI.ListOfConstraintIndices {
220+ MOI. ScalarQuadraticFunction{T},
221+ MOI. LessThan{T},
222+ },
177223) where {T}
178- return copy (bridge. ci)
224+ return copy (bridge. ci_lt)
225+ end
226+
227+ function MOI. get (
228+ bridge:: ComplementsToScalarNonlinearFunctionBridge{T} ,
229+ :: MOI.NumberOfConstraints{MOI.VariableIndex,MOI.Interval{T}} ,
230+ ):: Int64 where {T}
231+ return length (bridge. y)
232+ end
233+
234+ function MOI. get (
235+ bridge:: ComplementsToScalarNonlinearFunctionBridge{T} ,
236+ :: MOI.ListOfConstraintIndices{MOI.VariableIndex,MOI.Interval{T}} ,
237+ ) where {T}
238+ return map (bridge. y) do y
239+ return MOI. ConstraintIndex {MOI.VariableIndex,MOI.Interval{T}} (y. value)
240+ end
179241end
180242
181243function MOI. Bridges. needs_final_touch (
@@ -216,27 +278,23 @@ function MOI.Bridges.final_touch(
216278 end
217279 for i in 1 : N
218280 (l, u), F = bridge. bounds[i], f[i]
281+ y_u = isfinite (l) ? typemax (T) : zero (T)
282+ y_l = isfinite (u) ? typemin (T) : zero (T)
283+ y, _ = MOI. add_constrained_variable (model, MOI. Interval {T} (y_l, y_u))
284+ push! (bridge. y, y)
285+ # F(x) - y = 0
286+ g = MOI. Utilities. operate (- , T, F, y)
287+ push! (bridge. ci_eq, MOI. add_constraint (model, g, MOI. EqualTo (zero (T))))
219288 x = convert (MOI. VariableIndex, f[N+ i])
220- g_l = if isfinite (l) && iszero (l)
221- MOI. ScalarNonlinearFunction (:* , Any[x, F])
222- elseif isfinite (l)
223- x_l = MOI. ScalarNonlinearFunction (:- , Any[x, l])
224- MOI. ScalarNonlinearFunction (:* , Any[x_l, F])
225- elseif F isa MOI. ScalarNonlinearFunction
226- F
227- else
228- MOI. ScalarNonlinearFunction (:+ , Any[F])
229- end
230- push! (bridge. ci, MOI. add_constraint (model, g_l, MOI. LessThan (zero (T))))
231- g_u = if isfinite (u) && iszero (u)
232- MOI. ScalarNonlinearFunction (:* , Any[x, F])
233- elseif isfinite (u)
234- x_u = MOI. ScalarNonlinearFunction (:- , Any[x, u])
235- MOI. ScalarNonlinearFunction (:* , Any[x_u, F])
236- else
237- MOI. ScalarNonlinearFunction (:* , Any[- one (T), F])
289+ # (x - b) * y <= 0
290+ for b in (l, u)
291+ if isfinite (b)
292+ x_less_b = MOI. Utilities. operate (- , T, x, b)
293+ h = MOI. Utilities. operate (* , T, x_less_b, y)
294+ ci = MOI. add_constraint (model, h, MOI. LessThan (zero (T)))
295+ push! (bridge. ci_lt, ci)
296+ end
238297 end
239- push! (bridge. ci, MOI. add_constraint (model, g_u, MOI. LessThan (zero (T))))
240298 end
241299 return
242300end
0 commit comments