6767function MOI. Bridges. added_constrained_variable_types (
6868 :: Type{<:ScaledDiagonallyDominantBridge} ,
6969)
70- return [(SOS. PositiveSemidefinite2x2ConeTriangle,)]
70+ return Tuple{Type} [(SOS. PositiveSemidefinite2x2ConeTriangle,)]
7171end
7272function MOI. Bridges. added_constraint_types (
7373 :: Type{<:ScaledDiagonallyDominantBridge} ,
@@ -86,7 +86,7 @@ function MOI.get(
8686 bridge:: ScaledDiagonallyDominantBridge ,
8787 :: MOI.ListOfVariableIndices ,
8888)
89- return Iterators. flatten (bridge. variables)
89+ return collect ( Iterators. flatten (bridge. variables) )
9090end
9191function MOI. get (
9292 bridge:: ScaledDiagonallyDominantBridge ,
@@ -127,17 +127,88 @@ function MOI.get(
127127 return SOS. ScaledDiagonallyDominantConeTriangle (bridge. side_dimension)
128128end
129129
130- # TODO ConstraintPrimal, ConstraintDual
130+ # The map `A` is not injective because it maps the entry of several 2x2 matrices
131+ # into the same index so it is not invertible hence it's unclear how to implemented
132+ # `set` for `VariablePrimalStart`.
133+ # The adjoint `A'` is however injective and it is easy to invert.
131134
132- trimap (i, j) = div (j * (j - 1 ), 2 ) + i
135+ function MOI. supports (
136+ model:: MOI.ModelLike ,
137+ attr:: MOI.ConstraintDualStart ,
138+ :: Type{<:ScaledDiagonallyDominantBridge} ,
139+ )
140+ return MOI. supports (
141+ model,
142+ attr,
143+ MOI. ConstraintIndex{
144+ MOI. VectorOfVariables,
145+ SOS. PositiveSemidefinite2x2ConeTriangle,
146+ },
147+ )
148+ end
149+
150+ function MOI. set (
151+ model:: MOI.ModelLike ,
152+ attr:: MOI.ConstraintDualStart ,
153+ bridge:: ScaledDiagonallyDominantBridge ,
154+ value,
155+ )
156+ n = bridge. side_dimension
157+ k = 0
158+ for j in 1 : n
159+ for i in 1 : (j- 1 )
160+ k += 1
161+ # PSD constraints on 2x2 matrices are SOC representable
162+ if isnothing (value)
163+ dual = nothing
164+ else
165+ dual = [
166+ value[MOI. Utilities. trimap (i, i)],
167+ value[MOI. Utilities. trimap (i, j)],
168+ value[MOI. Utilities. trimap (j, j)],
169+ ]
170+ end
171+ MOI. set (model, attr, bridge. constraints[k], dual)
172+ end
173+ end
174+ return
175+ end
176+
177+ function MOI. get (
178+ model:: MOI.ModelLike ,
179+ attr:: Union{MOI.ConstraintDual,MOI.ConstraintDualStart} ,
180+ bridge:: ScaledDiagonallyDominantBridge{T} ,
181+ ) where {T}
182+ n = bridge. side_dimension
183+ value = zeros (T, MOI. Utilities. trimap (n, n))
184+ k = 0
185+ for j in 1 : n
186+ for i in 1 : (j- 1 )
187+ k += 1
188+ dual = MOI. get (model, attr, bridge. constraints[k])
189+ if isnothing (dual)
190+ return nothing
191+ end
192+ # There are `bridge.side_dimension - 1` possible candidate that should all have
193+ # the same `dual` so we take an arbitrary choice
194+ if j == i + 1
195+ value[MOI. Utilities. trimap (i, i)] = dual[1 ]
196+ elseif i == 1 && j == n
197+ value[MOI. Utilities. trimap (j, j)] = dual[3 ]
198+ end
199+ value[MOI. Utilities. trimap (i, j)] = dual[2 ]
200+ end
201+ end
202+ return value
203+ end
133204
134205function MOI. get (
135206 model:: MOI.ModelLike ,
136207 attr:: MOI.VariablePrimal ,
137208 bridge:: ScaledDiagonallyDominantBridge{T} ,
138- i :: MOI.Bridges.IndexInVector ,
209+ index :: MOI.Bridges.IndexInVector ,
139210) where {T}
140- i, j = matrix_indices (i . value)
211+ i, j = MOI . Utilities . inverse_trimap (index . value)
141212 if i == j
142213 value = zero (T)
143214 for k in 1 : (i- 1 )
@@ -159,7 +230,7 @@ function MOI.Bridges.bridged_function(
159230 bridge:: ScaledDiagonallyDominantBridge{T} ,
160231 i:: MOI.Bridges.IndexInVector ,
161232) where {T}
162- i, j = matrix_indices (i. value)
233+ i, j = MOI . Utilities . inverse_trimap (i. value)
163234 if i == j
164235 func = zero (MOI. ScalarAffineFunction{T})
165236 for k in 1 : (i- 1 )
@@ -188,19 +259,28 @@ function MOI.Bridges.Variable.unbridged_map(
188259 k = 0
189260 z = zero (SAF)
190261 saf (i) = convert (SAF, vis[i])
191- # vis[trimap(j, j)] is replaced by a sum of several variables.
262+ # vis[MOI.Utilities. trimap(j, j)] is replaced by a sum of several variables.
192263 # The strategy is to replace all of them by zero except one.
193264 for j in 1 : bridge. side_dimension
194265 for i in 1 : (j- 1 )
195266 k += 1
196267 if i == 1 && j == 2
197- push! (umap, bridge. variables[k][1 ] => saf (trimap (1 , 1 )))
268+ push! (
269+ umap,
270+ bridge. variables[k][1 ] => saf (MOI. Utilities. trimap (1 , 1 )),
271+ )
198272 else
199273 push! (umap, bridge. variables[k][1 ] => z)
200274 end
201- push! (umap, bridge. variables[k][2 ] => saf (trimap (i, j)))
275+ push! (
276+ umap,
277+ bridge. variables[k][2 ] => saf (MOI. Utilities. trimap (i, j)),
278+ )
202279 if i == 1
203- push! (umap, bridge. variables[k][3 ] => saf (trimap (j, j)))
280+ push! (
281+ umap,
282+ bridge. variables[k][3 ] => saf (MOI. Utilities. trimap (j, j)),
283+ )
204284 else
205285 push! (umap, bridge. variables[k][3 ] => z)
206286 end
0 commit comments