Skip to content

Commit 72c1ab6

Browse files
authored
[Utilities] unify how we compute variable dual fallback (#2640)
1 parent 147a5b9 commit 72c1ab6

File tree

2 files changed

+42
-63
lines changed

2 files changed

+42
-63
lines changed

src/Utilities/results.jl

Lines changed: 28 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ end
246246
function _variable_coefficient(
247247
func::MOI.ScalarAffineFunction{T},
248248
vi::MOI.VariableIndex,
249+
value_fn::Any,
249250
) where {T}
250251
coef = zero(T)
251252
for term in func.terms
@@ -259,12 +260,12 @@ end
259260
function _variable_coefficient(
260261
func::MOI.VectorAffineFunction{T},
261262
vi::MOI.VariableIndex,
263+
value_fn::Any,
262264
) where {T}
263265
coef = zeros(T, MOI.output_dimension(func))
264-
for vector_term in func.terms
265-
term = vector_term.scalar_term
266-
if term.variable == vi
267-
coef[vector_term.output_index] += term.coefficient
266+
for term in func.terms
267+
if term.scalar_term.variable == vi
268+
coef[term.output_index] += term.scalar_term.coefficient
268269
end
269270
end
270271
return coef
@@ -273,7 +274,7 @@ end
273274
function _variable_coefficient(
274275
func::MOI.ScalarQuadraticFunction{T},
275276
vi::MOI.VariableIndex,
276-
value::F,
277+
value_fn::F,
277278
) where {T,F<:Function}
278279
coef = zero(T)
279280
# `vi`'th row of `Qx + a` where `func` is `x'Qx/2 + a'x + b`.
@@ -284,9 +285,9 @@ function _variable_coefficient(
284285
end
285286
for term in func.quadratic_terms
286287
if term.variable_1 == vi
287-
coef += term.coefficient * value(term.variable_2)
288+
coef += term.coefficient * value_fn(term.variable_2)
288289
elseif term.variable_2 == vi
289-
coef += term.coefficient * value(term.variable_1)
290+
coef += term.coefficient * value_fn(term.variable_1)
290291
end
291292
end
292293
return coef
@@ -295,23 +296,21 @@ end
295296
function _variable_coefficient(
296297
func::MOI.VectorQuadraticFunction{T},
297298
vi::MOI.VariableIndex,
298-
value::F,
299+
value_fn::F,
299300
) where {T,F<:Function}
300301
coef = zeros(T, MOI.output_dimension(func))
301302
# `vi`'th row of `Qx + a` where `func` is `x'Qx/2 + a'x + b`.
302-
for vector_term in func.affine_terms
303-
term = vector_term.scalar_term
304-
if term.variable == vi
305-
coef[vector_term.output_index] += term.coefficient
303+
for aff_term in func.affine_terms
304+
if aff_term.scalar_term.variable == vi
305+
coef[aff_term.output_index] += aff_term.scalar_term.coefficient
306306
end
307307
end
308-
for vector_term in func.quadratic_terms
309-
term = vector_term.scalar_term
310-
oi = vector_term.output_index
308+
for q_term in func.quadratic_terms
309+
index, term = q_term.output_index, q_term.scalar_term
311310
if term.variable_1 == vi
312-
coef[oi] += term.coefficient * value(term.variable_2)
313-
elseif term.variable_2 == vi
314-
coef[oi] += term.coefficient * value(term.variable_1)
311+
coef[index] += term.coefficient * value_fn(term.variable_2)
312+
elseif q_term.scalar_term.variable_2 == vi
313+
coef[index] += term.coefficient * value_fn(term.variable_1)
315314
end
316315
end
317316
return coef
@@ -322,48 +321,14 @@ function _variable_dual(
322321
model::MOI.ModelLike,
323322
attr::MOI.ConstraintDual,
324323
vi::MOI.VariableIndex,
325-
ci::MOI.ConstraintIndex{<:MOI.ScalarAffineFunction},
326-
) where {T}
327-
func = MOI.get(model, MOI.ConstraintFunction(), ci)
328-
coef = _variable_coefficient(func, vi)
329-
dual = MOI.get(model, attr, ci)
330-
return coef * dual
331-
end
332-
333-
function _variable_dual(
334-
::Type{T},
335-
model::MOI.ModelLike,
336-
attr::MOI.ConstraintDual,
337-
vi::MOI.VariableIndex,
338-
ci::MOI.ConstraintIndex{<:MOI.ScalarQuadraticFunction},
339-
) where {T}
340-
func = MOI.get(model, MOI.ConstraintFunction(), ci)
341-
primal = MOI.VariablePrimal(attr.result_index)
342-
coef = _variable_coefficient(func, vi, vi -> MOI.get(model, primal, vi))
343-
dual = MOI.get(model, attr, ci)
344-
return coef * dual
345-
end
346-
347-
function _variable_dual(
348-
::Type{T},
349-
model::MOI.ModelLike,
350-
attr::MOI.ConstraintDual,
351-
vi::MOI.VariableIndex,
352-
ci::MOI.ConstraintIndex{<:MOI.VectorAffineFunction},
353-
) where {T}
354-
func = MOI.get(model, MOI.ConstraintFunction(), ci)
355-
set = MOI.get(model, MOI.ConstraintSet(), ci)
356-
coef = _variable_coefficient(func, vi)
357-
dual = MOI.get(model, attr, ci)
358-
return set_dot(coef, dual, set)
359-
end
360-
361-
function _variable_dual(
362-
::Type{T},
363-
model::MOI.ModelLike,
364-
attr::MOI.ConstraintDual,
365-
vi::MOI.VariableIndex,
366-
ci::MOI.ConstraintIndex{<:MOI.VectorQuadraticFunction},
324+
ci::MOI.ConstraintIndex{
325+
<:Union{
326+
MOI.ScalarAffineFunction,
327+
MOI.ScalarQuadraticFunction,
328+
MOI.VectorAffineFunction,
329+
MOI.VectorQuadraticFunction,
330+
},
331+
},
367332
) where {T}
368333
func = MOI.get(model, MOI.ConstraintFunction(), ci)
369334
set = MOI.get(model, MOI.ConstraintSet(), ci)
@@ -437,7 +402,7 @@ function _variable_dual(
437402
end
438403
elseif F <: MOI.ScalarAffineFunction
439404
f = MOI.get(model, obj_attr)
440-
dual += sign * _variable_coefficient(f, vi)
405+
dual += sign * _variable_coefficient(f, vi, nothing)
441406
elseif F <: MOI.ScalarQuadraticFunction
442407
f = MOI.get(model, obj_attr)
443408
primal_attr = MOI.VariablePrimal(attr.result_index)
@@ -455,8 +420,8 @@ function _variable_dual(
455420
)
456421
end
457422
end
458-
for FS in MOI.get(model, MOI.ListOfConstraintTypesPresent())
459-
dual -= _variable_dual(T, model, attr, ci, vi, FS[1], FS[2])
423+
for (F, S) in MOI.get(model, MOI.ListOfConstraintTypesPresent())
424+
dual -= _variable_dual(T, model, attr, ci, vi, F, S)
460425
end
461426
return dual
462427
end

test/Utilities/model.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,20 @@ function test_set_unsupported_objective()
570570
return
571571
end
572572

573+
function test_variable_coefficient_VectorQuadraticFunction()
574+
x = MOI.VariableIndex.(1:2)
575+
fs = [
576+
1.0 * x[1] * x[1] + 2.0 * x[1] * x[2] + 3.0 * x[2] + 0.5,
577+
1.0 * x[2] * x[2],
578+
]
579+
f = MOI.Utilities.vectorize(fs)
580+
for xi in x
581+
@test MOI.Utilities._variable_coefficient(f, xi, y -> sin(y.value))
582+
MOI.Utilities._variable_coefficient.(fs, xi, y -> sin(y.value))
583+
end
584+
return
585+
end
586+
573587
end # module
574588

575589
TestModel.runtests()

0 commit comments

Comments
 (0)