@@ -70,69 +70,61 @@ The `NormOneCone` is representable with LP constraints, since
70
70
``t \\ ge \\ sum_i \\ lvert x_i \\ rvert`` if and only if there exists a vector y such that
71
71
``t \\ ge \\ sum_i y_i`` and ``y_i \\ ge x_i``, ``y_i \\ ge -x_i`` for all ``i``.
72
72
"""
73
- struct NormOneBridge{T, F, G, H } <: AbstractBridge
73
+ struct NormOneBridge{T, F, G} <: AbstractBridge
74
74
y:: Vector{MOI.VariableIndex}
75
- ge_index:: CI{F, MOI.GreaterThan{T}}
76
- nn_index:: CI{G, MOI.Nonnegatives}
75
+ nn_index:: CI{F, MOI.Nonnegatives}
77
76
end
78
- function bridge_constraint (:: Type{NormOneBridge{T, F, G, H }} , model:: MOI.ModelLike , f:: H , s:: MOI.NormOneCone ) where {T, F, G, H }
77
+ function bridge_constraint (:: Type{NormOneBridge{T, F, G}} , model:: MOI.ModelLike , f:: G , s:: MOI.NormOneCone ) where {T, F, G}
79
78
f_scalars = MOIU. eachscalar (f)
80
79
d = MOI. dimension (s)
81
80
y = MOI. add_variables (model, d - 1 )
82
- ge_index = MOIU. normalize_and_add_constraint (model, MOIU . operate (- , T, f_scalars[1 ], MOIU. operate (sum, T, y)), MOI . GreaterThan ( zero (T)), allow_modify_function = true )
81
+ ge = MOIU. operate (- , T, f_scalars[1 ], MOIU. operate (sum, T, y))
83
82
lb = f_scalars[2 : d]
84
83
ub = MOIU. operate (- , T, lb)
85
84
lb = MOIU. operate! (+ , T, lb, MOI. VectorOfVariables (y))
86
85
ub = MOIU. operate! (+ , T, ub, MOI. VectorOfVariables (y))
87
- f_new = MOIU. operate (vcat, T, ub, lb)
88
- nn_index = MOI. add_constraint (model, f_new, MOI. Nonnegatives (2 d - 2 ))
89
- return NormOneBridge {T, F, G, H } (y, ge_index , nn_index)
86
+ f_new = MOIU. operate (vcat, T, ge, ub, lb)
87
+ nn_index = MOI. add_constraint (model, f_new, MOI. Nonnegatives (2 d - 1 ))
88
+ return NormOneBridge {T, F, G} (y, nn_index)
90
89
end
91
90
92
91
MOI. supports_constraint (:: Type{NormOneBridge{T}} , :: Type{<:MOI.AbstractVectorFunction} , :: Type{MOI.NormOneCone} ) where T = true
93
92
MOIB. added_constrained_variable_types (:: Type{<:NormOneBridge} ) = Tuple{DataType}[]
94
- MOIB. added_constraint_types (:: Type{NormOneBridge{T, F, G, H}} ) where {T, F, G, H} = [(F, MOI. GreaterThan{T}), (G, MOI. Nonnegatives)]
95
- function concrete_bridge_type (:: Type{<:NormOneBridge{T}} , H:: Type{<:MOI.AbstractVectorFunction} , :: Type{MOI.NormOneCone} ) where T
96
- S = MOIU. scalar_type (H)
97
- F = MOIU. promote_operation (+ , T, S, S)
98
- G = MOIU. promote_operation (+ , T, H, H)
99
- return NormOneBridge{T, F, G, H}
93
+ MOIB. added_constraint_types (:: Type{<:NormOneBridge{T, F}} ) where {T, F} = [(F, MOI. Nonnegatives)]
94
+ function concrete_bridge_type (:: Type{<:NormOneBridge{T}} , G:: Type{<:MOI.AbstractVectorFunction} , :: Type{MOI.NormOneCone} ) where T
95
+ S = MOIU. scalar_type (G)
96
+ F = MOIU. promote_operation (vcat, T, MOIU. promote_operation (+ , T, S, S), MOIU. promote_operation (- , T, S, S))
97
+ return NormOneBridge{T, F, G}
100
98
end
101
99
102
100
# Attributes, Bridge acting as a model
103
101
MOI. get (b:: NormOneBridge , :: MOI.NumberOfVariables ) = length (b. y)
104
102
MOI. get (b:: NormOneBridge , :: MOI.ListOfVariableIndices ) = b. y
105
- MOI. get (b:: NormOneBridge{T, F, G, H} , :: MOI.NumberOfConstraints{F, MOI.GreaterThan{T}} ) where {T, F, G, H} = 1
106
- MOI. get (b:: NormOneBridge{T, F, G, H} , :: MOI.NumberOfConstraints{G, MOI.Nonnegatives} ) where {T, F, G, H} = 1
107
- MOI. get (b:: NormOneBridge{T, F, G, H} , :: MOI.ListOfConstraintIndices{F, MOI.GreaterThan{T}} ) where {T, F, G, H} = [b. ge_index]
108
- MOI. get (b:: NormOneBridge{T, F, G, H} , :: MOI.ListOfConstraintIndices{G, MOI.Nonnegatives} ) where {T, F, G, H} = [b. nn_index]
103
+ MOI. get (b:: NormOneBridge{T, F} , :: MOI.NumberOfConstraints{F, MOI.Nonnegatives} ) where {T, F} = 1
104
+ MOI. get (b:: NormOneBridge{T, F} , :: MOI.ListOfConstraintIndices{F, MOI.Nonnegatives} ) where {T, F} = [b. nn_index]
109
105
110
106
# References
111
107
function MOI. delete (model:: MOI.ModelLike , c:: NormOneBridge )
112
108
MOI. delete (model, c. nn_index)
113
- MOI. delete (model, c. ge_index)
114
109
MOI. delete (model, c. y)
115
110
end
116
111
117
112
# Attributes, Bridge acting as a constraint
118
- function MOI. get (model:: MOI.ModelLike , :: MOI.ConstraintFunction , c:: NormOneBridge{T, F, G, H} ) where {T, F, G, H}
119
- ge_func = MOI. get (model, MOI. ConstraintFunction (), c. ge_index)
113
+ function MOI. get (model:: MOI.ModelLike , :: MOI.ConstraintFunction , c:: NormOneBridge{T, F, G} ) where {T, F, G}
120
114
nn_func = MOIU. eachscalar (MOI. get (model, MOI. ConstraintFunction (), c. nn_index))
121
- t = MOIU. operate! (+ , T, ge_func, MOIU . operate! ( / , T, sum (nn_func), T (2 ) ))
122
- d = div (length (nn_func), 2 )
123
- x = MOIU. operate! (/ , T, MOIU. operate! (- , T, nn_func[(d + 1 ): end ], nn_func[1 : d ]), T (2 ))
124
- return MOIU. convert_approx (H , MOIU. remove_variable (MOIU. operate (vcat, T, t, x), c. y))
115
+ t = MOIU. operate! (/ , T, nn_func[ 1 ] + sum (nn_func), T (2 ))
116
+ d = div (length (nn_func) - 1 , 2 )
117
+ x = MOIU. operate! (/ , T, MOIU. operate! (- , T, nn_func[(d + 2 ): end ], nn_func[2 : (d + 1 ) ]), T (2 ))
118
+ return MOIU. convert_approx (G , MOIU. remove_variable (MOIU. operate (vcat, T, t, x), c. y))
125
119
end
126
120
function MOI. get (model:: MOI.ModelLike , :: MOI.ConstraintSet , c:: NormOneBridge )
127
- dim = 1 + div (MOI. dimension (MOI. get (model, MOI. ConstraintSet (), c. nn_index)), 2 )
121
+ dim = div (MOI. dimension (MOI. get (model, MOI. ConstraintSet (), c. nn_index)) + 1 , 2 )
128
122
return MOI. NormOneCone (dim)
129
123
end
130
-
131
124
function MOI. supports (
132
125
:: MOI.ModelLike ,
133
126
:: Union{MOI.ConstraintPrimalStart, MOI.ConstraintDualStart} ,
134
127
:: Type{<:NormOneBridge} )
135
-
136
128
return true
137
129
end
138
130
function MOI. set (model:: MOI.ModelLike , attr:: MOI.ConstraintPrimalStart ,
@@ -142,18 +134,17 @@ function MOI.set(model::MOI.ModelLike, attr::MOI.ConstraintPrimalStart,
142
134
for i in eachindex (bridge. y)
143
135
MOI. set (model, MOI. VariablePrimalStart (), bridge. y[i], y_value[i])
144
136
end
145
- MOI . set (model, attr, bridge . nn_index, [ y_value - x_value; y_value + x_value] )
146
- MOI. set (model, attr, bridge. ge_index, value[ 1 ] - reduce ( + , y_value, init = zero (T)) )
137
+ nn_value = vcat (value[ 1 ] - reduce ( + , y_value, init = zero (T)), y_value - x_value, y_value + x_value)
138
+ MOI. set (model, attr, bridge. nn_index, nn_value )
147
139
return
148
140
end
149
141
function MOI. get (model:: MOI.ModelLike ,
150
142
attr:: Union{MOI.ConstraintPrimal, MOI.ConstraintPrimalStart} ,
151
143
bridge:: NormOneBridge )
152
- ge_primal = MOI. get (model, attr, bridge. ge_index)
153
144
nn_primal = MOI. get (model, attr, bridge. nn_index)
154
- t = ge_primal + sum (nn_primal) / 2
145
+ t = (nn_primal[ 1 ] + sum (nn_primal) ) / 2
155
146
d = length (bridge. y)
156
- x = (nn_primal[(d + 1 ): end ] - nn_primal[1 : d ]) / 2
147
+ x = (nn_primal[(d + 2 ): end ] - nn_primal[2 : (d + 1 ) ]) / 2
157
148
return vcat (t, x)
158
149
end
159
150
# Given a_i is dual on y_i - x_i >= 0 and b_i is dual on y_i + x_i >= 0 and c is dual on t - sum(y) >= 0,
@@ -162,27 +153,26 @@ end
162
153
function MOI. get (model:: MOI.ModelLike ,
163
154
attr:: Union{MOI.ConstraintDual, MOI.ConstraintDualStart} ,
164
155
bridge:: NormOneBridge )
165
- t = MOI. get (model, attr, bridge. ge_index)
166
156
nn_dual = MOI. get (model, attr, bridge. nn_index)
167
157
d = length (bridge. y)
168
- x = nn_dual[(d + 1 ): end ] - nn_dual[1 : d ]
169
- return vcat (t , x)
158
+ x = nn_dual[(d + 2 ): end ] - nn_dual[2 : (d + 1 ) ]
159
+ return vcat (nn_dual[ 1 ] , x)
170
160
end
171
- # value[1 + i] = nn_dual[d + i] - nn_dual[i]
161
+ # value[1 + i] = nn_dual[1 + d + i] - nn_dual[1 + i]
172
162
# and `nn_dual` is nonnegative. By complementarity slackness, only one of each
173
163
# `nn_dual` can be nonzero (except if `x = 0`) so we can set
174
164
# depending on the sense of `value[1 + i]`.
175
165
function MOI. set (model:: MOI.ModelLike , :: MOI.ConstraintDualStart ,
176
166
bridge:: NormOneBridge , value)
177
- t = MOI. set (model, MOI. ConstraintDualStart (), bridge. ge_index, value[1 ])
178
167
d = length (bridge. y)
179
- nn_dual = zeros (eltype (value), 2 d)
168
+ nn_dual = zeros (eltype (value), 2 d + 1 )
169
+ nn_dual[1 ] = value[1 ]
180
170
for i in eachindex (bridge. y)
181
171
v = value[1 + i]
182
172
if v < 0
183
- nn_dual[i] = - v
173
+ nn_dual[1 + i] = - v
184
174
else
185
- nn_dual[d + i] = v
175
+ nn_dual[1 + d + i] = v
186
176
end
187
177
end
188
178
MOI. set (model, MOI. ConstraintDualStart (), bridge. nn_index, nn_dual)
0 commit comments