@@ -15,10 +15,7 @@ const SVF = MOI.SingleVariable
15
15
const VVF = MOI. VectorOfVariables
16
16
const VF = Union{SVF, VVF}
17
17
const SAF{T} = MOI. ScalarAffineFunction{T}
18
- const VAF{T} = MOI. VectorAffineFunction{T}
19
- const AF{T} = Union{SAF{T}, VAF{T}}
20
18
const ASF{T} = Union{SVF, SAF{T}}
21
- const AVF{T} = Union{VVF, VAF{T}}
22
19
23
20
const ZS = Union{MOI. EqualTo, MOI. Zeros}
24
21
const NS = Union{MOI. GreaterThan, MOI. Nonnegatives}
@@ -43,7 +40,6 @@ mutable struct SOItoMOIBridge{T, SIT <: AbstractSDOptimizer} <: MOI.AbstractOpti
43
40
varmap:: Vector{Vector{Tuple{Int, Int, Int, T, T}}} # Variable Index vi -> blk, i, j, coef, shift # x = sum coef * block(X, blk)[i, j] + shift
44
41
zeroblock:: Dict{CI, Int}
45
42
constrmap:: Dict{CI, UnitRange{Int}} # Constraint Index ci -> cs
46
- slackmap:: Vector{Tuple{Int, Int, Int, T}} # c -> blk, i, j, coef
47
43
double:: Vector{CI} # created when there are two cones for same variable
48
44
function SOItoMOIBridge {T} (sdoptimizer:: SIT ) where {T, SIT}
49
45
new {T, SIT} (sdoptimizer, Dict {Int64, T} (), Dict {Int, T} (),
@@ -53,7 +49,6 @@ mutable struct SOItoMOIBridge{T, SIT <: AbstractSDOptimizer} <: MOI.AbstractOpti
53
49
Vector{Tuple{Int, Int, Int, T}}[],
54
50
Dict {CI, Int} (),
55
51
Dict {CI, UnitRange{Int}} (),
56
- Tuple{Int, Int, Int, T}[],
57
52
CI[])
58
53
end
59
54
end
@@ -86,8 +81,7 @@ function MOI.is_empty(optimizer::SOItoMOIBridge)
86
81
isempty (optimizer. free) &&
87
82
isempty (optimizer. varmap) &&
88
83
isempty (optimizer. zeroblock) &&
89
- isempty (optimizer. constrmap) &&
90
- isempty (optimizer. slackmap)
84
+ isempty (optimizer. constrmap)
91
85
end
92
86
function MOI. empty! (optimizer:: SOItoMOIBridge{T} ) where T
93
87
for s in optimizer. double
@@ -107,37 +101,57 @@ function MOI.empty!(optimizer::SOItoMOIBridge{T}) where T
107
101
optimizer. varmap = Vector{Tuple{Int, Int, Int, T}}[]
108
102
optimizer. zeroblock = Dict {CI, Int} ()
109
103
optimizer. constrmap = Dict {CI, UnitRange{Int}} ()
110
- optimizer. slackmap = Tuple{Int, Int, Int, T}[]
111
104
end
112
105
113
106
function setconstant! (optimizer:: SOItoMOIBridge , ci:: CI , s) end
114
107
function setconstant! (optimizer:: SOItoMOIBridge , ci:: CI , s:: MOI.AbstractScalarSet )
115
108
optimizer. setconstant[ci. value] = MOIU. getconstant (s)
116
109
end
117
- function addsetconstant (optimizer:: SOItoMOIBridge , ci:: CI{<:Any, <:MOI.AbstractScalarSet} , x)
118
- x + optimizer. setconstant[ci. value]
110
+ function set_constant (optimizer:: SOItoMOIBridge ,
111
+ ci:: CI {<: MOI.AbstractScalarFunction ,
112
+ <: MOI.AbstractScalarSet })
113
+ return optimizer. setconstant[ci. value]
119
114
end
120
- function addsetconstant (optimizer:: SOItoMOIBridge , ci:: CI , x)
121
- x
115
+ function set_constant (optimizer:: SOItoMOIBridge{T} , ci:: CI ) where T
116
+ return zeros (T, length (optimizer . constrmap[ci]))
122
117
end
123
118
function addblkconstant (optimizer:: SOItoMOIBridge , ci:: CI{<:Any, <:Union{NS, PS}} , x)
124
119
blk = - ci. value
125
- x .+ optimizer. blkconstant[blk]
126
- end
127
- function addblkconstant (optimizer:: SOItoMOIBridge , ci:: CI , x)
128
- x
120
+ return x .+ optimizer. blkconstant[blk]
129
121
end
122
+ addblkconstant (optimizer:: SOItoMOIBridge , ci:: CI , x) = x
130
123
131
- function MOI. supports (optimizer:: SOItoMOIBridge{T} ,
132
- :: Union {MOI. ObjectiveSense,
133
- MOI. ObjectiveFunction{<: Union {MOI. SingleVariable,
134
- MOI. ScalarAffineFunction{T}}}}) where T
124
+ function MOI. supports (
125
+ optimizer:: SOItoMOIBridge{T} ,
126
+ :: Union {MOI. ObjectiveSense,
127
+ MOI. ObjectiveFunction{<: Union {MOI. SingleVariable,
128
+ MOI. ScalarAffineFunction{T}}}}) where T
135
129
return true
136
130
end
137
131
138
- function MOI. supports_constraint (:: SOItoMOIBridge{T} ,
139
- :: Type{<:Union{VF, AF{T}}} ,
140
- :: Type{<:SupportedSets} ) where T
132
+ # Zeros and Nonpositives supports could be removed thanks to variable bridges
133
+ # * `VectorOfVariables`-in-`Zeros` would return a `VectorAffineFunction` with
134
+ # zero constant and no variable created.
135
+ # * `VectorOfVariables`-in-`Nonpositives` would create variables in
136
+ # `Nonnegatives` and return a `VectorAffineFunction` containing `-` the
137
+ # variables.
138
+ function MOI. supports_constraint (
139
+ :: SOItoMOIBridge , :: Type{MOI.VectorOfVariables} ,
140
+ :: Type {<: Union {MOI. Zeros, MOI. Nonnegatives, MOI. Nonpositives,
141
+ MOI. PositiveSemidefiniteConeTriangle}})
142
+ return true
143
+ end
144
+ # This support could be remove thanks to variable bridges.
145
+ # The VectorizeVariableBridge would redirect to the above case and then the
146
+ # resulting function would be shifted by the constant.
147
+ function MOI. supports_constraint (
148
+ :: SOItoMOIBridge{T} , :: Type{MOI.SingleVariable} ,
149
+ :: Type{<:Union{MOI.EqualTo{T}, MOI.GreaterThan{T}, MOI.LessThan{T}}} ) where T
150
+ return true
151
+ end
152
+ function MOI. supports_constraint (
153
+ :: SOItoMOIBridge{T} , :: Type{MOI.ScalarAffineFunction{T}} ,
154
+ :: Type{MOI.EqualTo{T}} ) where T
141
155
return true
142
156
end
143
157
@@ -163,10 +177,10 @@ MOI.get(m::SOItoMOIBridge, s::SolverStatus) = MOI.get(m.sdoptimizer, s)
163
177
MOI. get (m:: SOItoMOIBridge , :: MOI.ResultCount ) = 1
164
178
165
179
function _getblock (M, blk:: Integer , s:: Type{<:Union{NS, ZS}} )
166
- diag (block (M, blk))
180
+ return diag (block (M, blk))
167
181
end
168
182
function _getblock (M, blk:: Integer , s:: Type{<:PS} )
169
- - diag (block (M, blk))
183
+ return - diag (block (M, blk))
170
184
end
171
185
# Vectorized length for matrix dimension d
172
186
sympackedlen (d:: Integer ) = (d* (d+ 1 )) >> 1
@@ -183,20 +197,22 @@ function _getblock(M::AbstractMatrix{T}, blk::Integer, s::Type{<:DS}) where T
183
197
end
184
198
end
185
199
@assert k == n
186
- v
200
+ return v
187
201
end
188
202
function getblock (M, blk:: Integer , s:: Type{<:MOI.AbstractScalarSet} )
189
203
vd = _getblock (M, blk, s)
190
204
@assert length (vd) == 1
191
- vd[1 ]
205
+ return vd[1 ]
192
206
end
193
207
function getblock (M, blk:: Integer , s:: Type{<:MOI.AbstractVectorSet} )
194
- _getblock (M, blk, s)
208
+ return _getblock (M, blk, s)
195
209
end
196
210
197
211
getvarprimal (m:: SOItoMOIBridge , blk:: Integer , S) = getblock (getX (m. sdoptimizer), blk, S)
198
212
function getvardual (m:: SOItoMOIBridge , blk:: Integer , S)
199
- getblock (getZ (m. sdoptimizer), blk, S)
213
+ z = getZ (m. sdoptimizer)
214
+ b = getblock (z, blk, S)
215
+ return getblock (getZ (m. sdoptimizer), blk, S)
200
216
end
201
217
202
218
function MOI. get (m:: SOItoMOIBridge{T} , :: MOI.VariablePrimal , vi:: VI ) where T
@@ -208,97 +224,54 @@ function MOI.get(m::SOItoMOIBridge{T}, ::MOI.VariablePrimal, vi::VI) where T
208
224
x += block (X, blk)[i, j] * sign (coef)
209
225
end
210
226
end
211
- x
227
+ return x
212
228
end
213
229
function MOI. get (m:: SOItoMOIBridge , vp:: MOI.VariablePrimal , vi:: Vector{VI} )
214
- MOI. get .(m, vp, vi)
230
+ return MOI. get .(m, vp, vi)
215
231
end
216
232
217
233
function _getattribute (m:: SOItoMOIBridge , ci:: CI{<:ASF} , f)
218
234
cs = m. constrmap[ci]
219
235
@assert length (cs) == 1
220
- f (m, first (cs))
236
+ return f (m, first (cs))
221
237
end
222
- function _getattribute (m:: SOItoMOIBridge , ci:: CI{<:AVF} , f)
223
- f .(m, m. constrmap[ci])
224
- end
225
-
226
- function getslack (m:: SOItoMOIBridge{T} , c:: Integer ) where T
227
- X = getX (m. sdoptimizer)
228
- blk, i, j, coef = m. slackmap[c]
229
- if iszero (blk)
230
- zero (T)
231
- else
232
- if i != j
233
- coef *= 2 # We should take block(X, blk)[i, j] + block(X, blk)[j, i] but they are equal
234
- end
235
- coef * block (X, blk)[i, j]
236
- end
238
+ function _getattribute (m:: SOItoMOIBridge , ci:: CI{<:VVF} , f)
239
+ return f .(m, m. constrmap[ci])
237
240
end
238
241
239
- function MOI. get (m:: SOItoMOIBridge , a:: MOI.ConstraintPrimal , ci:: CI{F, S} ) where {F, S}
242
+ function MOI. get (m:: SOItoMOIBridge , a:: MOI.ConstraintPrimal ,
243
+ ci:: CI{F, S} ) where {F, S}
240
244
if ci. value >= 0
241
- addsetconstant (m, ci, _getattribute (m, ci, getslack) )
245
+ return set_constant (m, ci)
242
246
else
243
247
# Variable Function-in-S with S different from Zeros and EqualTo and not a double variable constraint
244
248
blk = - ci. value
245
- addblkconstant (m, ci, getvarprimal (m, blk, S))
249
+ return addblkconstant (m, ci, getvarprimal (m, blk, S))
246
250
end
247
251
end
248
252
249
- function getvardual (m:: SOItoMOIBridge{T} , vi:: VI ) where T
250
- Z = getZ (m. sdoptimizer)
251
- z = zero (T)
252
- for (blk, i, j, coef) in varmap (m, vi)
253
- if blk != 0
254
- z += block (Z, blk)[i, j] * sign (coef)
255
- end
256
- end
257
- z
258
- end
259
- getvardual (m:: SOItoMOIBridge , f:: SVF ) = getvardual (m, f. variable)
260
- getvardual (m:: SOItoMOIBridge , f:: VVF ) = map (vi -> getvardual (m, vi), f. variables)
261
- # function MOI.get(m::SOItoMOIBridge, ::MOI.ConstraintDual, ci::CI{<:VF, S})
262
- # _getattribute(m, ci, getdual) + getvardual(m, MOI.get(m, MOI.ConstraintFunction(), ci))
263
- # end
264
253
function MOI. get (m:: SOItoMOIBridge , :: MOI.ConstraintDual , ci:: CI{<:VF, S} ) where S<: SupportedSets
265
254
if ci. value < 0
266
- getvardual (m, - ci. value, S)
255
+ return getvardual (m, - ci. value, S)
267
256
else
268
257
dual = _getattribute (m, ci, getdual)
269
258
if haskey (m. zeroblock, ci) # ZS
270
- dual + getvardual (m, m. zeroblock[ci], S)
259
+ return dual + getvardual (m, m. zeroblock[ci], S)
271
260
else # var constraint on unfree constraint
272
- dual
261
+ return dual
273
262
end
274
263
end
275
264
end
276
265
277
266
function getdual (m:: SOItoMOIBridge{T} , c:: Integer ) where T
278
267
if c == 0
279
- zero (T)
268
+ return zero (T)
280
269
else
281
- - gety (m. sdoptimizer)[c]
270
+ return - gety (m. sdoptimizer)[c]
282
271
end
283
272
end
284
273
function MOI. get (m:: SOItoMOIBridge , :: MOI.ConstraintDual , ci:: CI )
285
- _getattribute (m, ci, getdual)
286
- end
287
- function scalevec! (v, c)
288
- d = div (isqrt (1 + 8 length (v))- 1 , 2 )
289
- @assert div (d* (d+ 1 ), 2 ) == length (v)
290
- i = 1
291
- for j in 1 : d
292
- for k in i: (i+ j- 2 )
293
- v[k] *= c
294
- end
295
- i += j
296
- end
297
- v
298
- end
299
- function MOI. get (m:: SOItoMOIBridge{T} , :: MOI.ConstraintDual ,
300
- ci:: CI{<:AF{T}, DS} ) where T
301
- scalevec! (_getattribute (m, ci, getdual), one (T)/ 2 )
274
+ return _getattribute (m, ci, getdual)
302
275
end
303
276
304
277
include (" sdpa.jl" )
0 commit comments