Skip to content

Commit 1a09876

Browse files
committed
Add incumbent callback for moment curve formulation
1 parent 43283ec commit 1a09876

File tree

1 file changed

+29
-7
lines changed

1 file changed

+29
-7
lines changed

src/jump.jl

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ function initPWL!(m::JuMP.Model)
2323
moment_curve_branch_callback(m, d)
2424
end
2525
CPLEX.setbranchcallback!(m.internalModel, branchcallback)
26+
function incumbentcallback(d::MathProgBase.MathProgCallbackData)
27+
state = MathProgBase.cbgetstate(d)
28+
@assert state == :MIPIncumbent
29+
m.colVal = copy(d.sol)
30+
moment_curve_incumbent_callback(m, d)
31+
end
32+
CPLEX.setincumbentcallback!(m.internalModel, incumbentcallback)
2633
end
2734
JuMP.solve(m; ignore_solve_hook=true, kwargs...)
2835
end)
@@ -249,6 +256,11 @@ function sos2_moment_curve_formulation!(m::JuMP.Model, λ)
249256
end
250257

251258
function moment_curve_branch_callback(m, cb)
259+
# if CPLEX was gonna branch anyway, just use their branching decision
260+
if !isempty(cb.nodes)
261+
unsafe_store!(cb.userinteraction_p, Cint(0))
262+
return nothing
263+
end
252264
xval = MathProgBase.cbgetlpsolution(cb)
253265
TOL = 1e-4
254266
branch_id = 0
@@ -262,14 +274,24 @@ function moment_curve_branch_callback(m, cb)
262274
end
263275
if branch_id > 0
264276
L, U = CPLEX.cbgetnodelb(cb), CPLEX.cbgetnodeub(cb)
265-
l, u = L[branch_id], U[branch_id]
266-
uᶠ, lᶜ = floor(xval[branch_id]), ceil(xval[branch_id])
277+
l, u = L[branch_id], U[branch_id]
278+
uᶠ, lᶜ = floor(xval[branch_id]), ceil(xval[branch_id])
279+
CPLEX.addbranch(cb, JuMP.@LinearConstraint((uᶠ-l )*(y[2]-l ^2) (uᶠ^2-l ^2)*(y[1]-l )))
280+
CPLEX.addbranch(cb, JuMP.@LinearConstraint((u -lᶜ)*(y[2]-lᶜ^2) (u ^2-lᶜ^2)*(y[1]-lᶜ)))
281+
else
282+
CPLEX.nobranches(cb)
283+
end
284+
nothing
285+
end
267286

268-
CPLEX.addbranch(cb, JuMP.@LinearConstraint((uᶠ-l )*(y[2]-l ^2) (uᶠ^2-l ^2)*(y[1]-l )))
269-
CPLEX.addbranch(cb, JuMP.@LinearConstraint((u -lᶜ)*(y[2]-lᶜ^2) (u ^2-lᶜ^2)*(y[1]-lᶜ)))
270-
else
271-
CPLEX.nobranches(cb)
287+
function moment_curve_incumbent_callback(m, cb)
288+
xval = MathProgBase.cbgetmipsolution(cb)
289+
for i in m.ext[:PWL].branchvars
290+
if !isapprox(xval[i]^2, xval[i+1], rtol=1e-4)
291+
CPLEX.rejectincumbent(cb)
292+
return nothing
272293
end
273294
end
274-
nothing
295+
CPLEX.acceptincumbent(cb)
296+
return nothing
275297
end

0 commit comments

Comments
 (0)