Skip to content

Commit 35ece1a

Browse files
authored
[QCQP] Add inner bridge layer (#121)
* [QCQP] Add inner bridge layer * Fix format
1 parent 5098d31 commit 35ece1a

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

src/QCQP/MOI_wrapper.jl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,16 @@ mutable struct Optimizer{T,O<:MOI.ModelLike} <: MOI.AbstractOptimizer
1010
index_map::Dict{MOI.ConstraintIndex,MOI.ConstraintIndex}
1111
end
1212

13-
function Optimizer{T}(model::MOI.ModelLike) where {T}
14-
return Optimizer{T,typeof(model)}(
15-
model,
13+
function Optimizer{T}(optimizer::MOI.ModelLike) where {T}
14+
if !MOI.supports_incremental_interface(optimizer)
15+
cache = MOI.default_cache(optimizer, T)
16+
optimizer = MOI.Utilities.CachingOptimizer(cache, optimizer)
17+
end
18+
# This bridge layer is needed for instance if `optimizer` needs to bridge
19+
# quadratic objective into quadratic constraints with a slack bridge (e.g., like SCIP)
20+
inner = MOI.Bridges.full_bridge_optimizer(optimizer, T)
21+
return Optimizer{T,typeof(inner)}(
22+
inner,
1623
nothing,
1724
DataStructures.OrderedDict{Type,MOI.Utilities.VectorOfConstraints}(),
1825
Dict{MOI.ConstraintIndex,MOI.ConstraintIndex}(),

test/qcqp.jl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,25 @@ MOI.Utilities.@model(
4949
(),
5050
)
5151

52+
MOI.Utilities.@model(
53+
AffineObjectiveModel,
54+
(),
55+
(MOI.LessThan, MOI.GreaterThan, MOI.EqualTo, MOI.Interval),
56+
(),
57+
(),
58+
(),
59+
(MOI.ScalarAffineFunction, MOI.ScalarQuadraticFunction),
60+
(),
61+
(),
62+
)
63+
64+
function MOI.supports(
65+
::AffineObjectiveModel{T},
66+
::MOI.ObjectiveFunction{F},
67+
) where {T,F<:MOI.AbstractFunction}
68+
return F == MOI.ScalarAffineFunction{T}
69+
end
70+
5271
function MOI.supports(
5372
::Model,
5473
::MOI.ObjectiveFunction{MOI.ScalarNonlinearFunction},
@@ -336,6 +355,21 @@ function test_start(x, y, T)
336355
@test sort(MOI.get(inner, MOI.VariablePrimalStart(), vis)) == T[2, 3, 4, 9]
337356
end
338357

358+
function test_inner_bridge(x, y, T)
359+
# The quadratic objective should be bridged after the QCQP layer
360+
inner = AffineObjectiveModel{T}()
361+
model = PolyJuMP.QCQP.Optimizer{T}(inner)
362+
a = MOI.add_variable(model)
363+
b = MOI.add_variable(model)
364+
p = PolyJuMP.ScalarPolynomialFunction(one(T) * x^3 - x * y^2, [a, b])
365+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
366+
MOI.set(model, MOI.ObjectiveFunction{typeof(p)}(), p)
367+
MOI.Utilities.final_touch(model, nothing)
368+
F = MOI.ScalarAffineFunction{T}
369+
@test MOI.ObjectiveFunction{F}() in
370+
MOI.get(inner, MOI.ListOfModelAttributesSet())
371+
end
372+
339373
function runtests(x, y)
340374
for name in names(@__MODULE__; all = true)
341375
if startswith("$name", "test_")

0 commit comments

Comments
 (0)