Skip to content

Commit 39adba2

Browse files
blegatandrewrosemberg
authored andcommitted
Use SlackBridgePrimalDualStart (jump-dev#253)
* Use SlackBridgePrimalDualStart * Update src/copy_dual.jl * Remove test_broken * Add supports * Add comment * Move to AbstractModel
1 parent 614b026 commit 39adba2

File tree

4 files changed

+26
-76
lines changed

4 files changed

+26
-76
lines changed

Diff for: Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ ChainRulesCore = "1"
2020
IterativeSolvers = "0.9"
2121
JuMP = "1"
2222
LazyArrays = "0.21, 0.22, 1"
23-
MathOptInterface = "1.14.1"
23+
MathOptInterface = "1.18"
2424
MathOptSetDistances = "0.2.7"
2525
julia = "1.6"

Diff for: src/copy_dual.jl

+5-74
Original file line numberDiff line numberDiff line change
@@ -11,45 +11,6 @@ struct ObjectiveFunctionAttribute{A,F} <: MOI.AbstractModelAttribute
1111
attr::A
1212
end
1313

14-
"""
15-
struct ObjectiveDualStart <: MOI.AbstractModelAttribute end
16-
17-
If the objective function had a dual, it would be `-1` for the Lagrangian
18-
function to be the same.
19-
When the `MOI.Bridges.Objective.SlackBridge` is used, it creates a constraint.
20-
The dual of this constraint is therefore `-1` as well.
21-
When setting this attribute, it allows to set the constraint dual of this
22-
constraint.
23-
"""
24-
struct ObjectiveDualStart <: MOI.AbstractModelAttribute end
25-
# Defining it for `MOI.set` leads to ambiguity
26-
function MOI.throw_set_error_fallback(
27-
::MOI.ModelLike,
28-
::ObjectiveDualStart,
29-
value,
30-
)
31-
return nothing
32-
end
33-
34-
"""
35-
struct ObjectiveSlackGapPrimalStart <: MOI.AbstractModelAttribute end
36-
37-
If the objective function had a dual, it would be `-1` for the Lagrangian
38-
function to be the same.
39-
When the `MOI.Bridges.Objective.SlackBridge` is used, it creates a constraint.
40-
The dual of this constraint is therefore `-1` as well.
41-
When setting this attribute, it allows to set the constraint dual of this
42-
constraint.
43-
"""
44-
struct ObjectiveSlackGapPrimalStart <: MOI.AbstractModelAttribute end
45-
function MOI.throw_set_error_fallback(
46-
::MOI.ModelLike,
47-
::ObjectiveSlackGapPrimalStart,
48-
value,
49-
)
50-
return nothing
51-
end
52-
5314
function MOI.get(
5415
b::MOI.Bridges.AbstractBridgeOptimizer,
5516
attr::ObjectiveFunctionAttribute{A,F},
@@ -100,11 +61,7 @@ end
10061

10162
function MOI.set(
10263
b::MOI.Bridges.AbstractBridgeOptimizer,
103-
attr::Union{
104-
ObjectiveDualStart,
105-
ObjectiveSlackGapPrimalStart,
106-
ForwardObjectiveFunction,
107-
},
64+
attr::ForwardObjectiveFunction,
10865
value,
10966
)
11067
if MOI.Bridges.is_objective_bridged(b)
@@ -121,34 +78,6 @@ function MOI.set(
12178
end
12279
end
12380

124-
function MOI.set(
125-
model::MOI.ModelLike,
126-
::ObjectiveFunctionAttribute{ObjectiveDualStart},
127-
b::MOI.Bridges.Objective.SlackBridge,
128-
value,
129-
)
130-
return MOI.set(model, MOI.ConstraintDualStart(), b.constraint, value)
131-
end
132-
133-
function MOI.set(
134-
model::MOI.ModelLike,
135-
::ObjectiveFunctionAttribute{ObjectiveSlackGapPrimalStart},
136-
b::MOI.Bridges.Objective.SlackBridge{T},
137-
value,
138-
) where {T}
139-
# `f(x) - slack = value` so `slack = f(x) - value`
140-
fun = MOI.get(model, MOI.ConstraintFunction(), b.constraint)
141-
set = MOI.get(model, MOI.ConstraintSet(), b.constraint)
142-
MOI.Utilities.operate!(-, T, fun, MOI.constant(set))
143-
# `fun = f - slack` so we remove the term `-slack` to get `f`
144-
f = MOI.Utilities.remove_variable(fun, b.slack)
145-
f_val = MOI.Utilities.eval_variables(f) do v
146-
return MOI.get(model, MOI.VariablePrimalStart(), v)
147-
end
148-
MOI.set(model, MOI.VariablePrimalStart(), b.slack, f_val - value)
149-
return MOI.set(model, MOI.ConstraintPrimalStart(), b.constraint, value)
150-
end
151-
15281
function _copy_dual(dest::MOI.ModelLike, src::MOI.ModelLike, index_map)
15382
vis_src = MOI.get(src, MOI.ListOfVariableIndices())
15483
MOI.set(
@@ -173,8 +102,10 @@ function _copy_dual(dest::MOI.ModelLike, src::MOI.ModelLike, index_map)
173102
MOI.ConstraintDual(),
174103
)
175104
end
176-
MOI.set(dest, ObjectiveDualStart(), -1.0)
177-
return MOI.set(dest, ObjectiveSlackGapPrimalStart(), 0.0)
105+
# Same as in `JuMP.set_start_values`
106+
# Needed for models which bridge `min f(x)` into `min t such that t >= f(x)`.
107+
MOI.set(dest, MOI.Bridges.Objective.SlackBridgePrimalDualStart(), nothing)
108+
return
178109
end
179110

180111
function _copy_constraint_start(

Diff for: src/diff_opt.jl

+19
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,25 @@ function _enlarge_set(vec::Vector, idx, value)
318318
return
319319
end
320320

321+
# The following `supports` methods are needed because
322+
# `MOI.set(::MOI.ModelLike, ::SlackBridgePrimalDualStart, ::SlackBridge, ::Nothing)`
323+
# checks that the model supports these starting value attributes.
324+
function MOI.supports(
325+
::AbstractModel,
326+
::MOI.VariablePrimalStart,
327+
::Type{<:MOI.VariableIndex},
328+
)
329+
return true
330+
end
331+
332+
function MOI.supports(
333+
::AbstractModel,
334+
::Union{MOI.ConstraintDualStart,MOI.ConstraintPrimalStart},
335+
::Type{<:MOI.ConstraintIndex},
336+
)
337+
return true
338+
end
339+
321340
function MOI.get(
322341
model::AbstractModel,
323342
::MOI.VariablePrimalStart,

Diff for: test/jump.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ function test_differentiating_simple_socp()
465465
db = zeros(5)
466466
dc = zeros(3)
467467
MOI.set.(model, DiffOpt.ReverseVariablePrimal(), vv, 1.0)
468-
@test_broken DiffOpt.reverse_differentiate!(model)
468+
DiffOpt.reverse_differentiate!(model)
469469
# TODO add tests
470470
return
471471
end

0 commit comments

Comments
 (0)