Using optimizer callbacks within JuMP to terminate MIP solve

Ideally, something like this. But I’m getting a segfault when I try to terminate. (Edit: I think this may have been due to Julia’s GC mixing with the early terminate. I can’t reproduce if I turn it off.)

using JuMP
import Gurobi

softlimit = 5
hardlimit = 100

model = direct_model(
    Gurobi.Optimizer(
        OutputFlag = 0,
        Cuts = 0,
        Presolve = 0,
        PreCrush = 1,
        Heuristics = 0,
    )
)
@variable(model, 0 <= x <= 2.5, Int)
@variable(model, 0 <= y <= 2.5, Int)
@objective(model, Max, y)

function softtime(cb_data, cb_where)
    if cb_where == Gurobi.CB_MIP
        @info("Executing callback")
        runtime = Gurobi.cbget_runtime(cb_data, cb_where)
        objbst = Gurobi.cbget_mip_objbst(cb_data, cb_where)
        objbnd = Gurobi.cbget_mip_objbnd(cb_data, cb_where)
        gap = abs((objbst - objbnd) / objbst)
        @info("Terminating at $(runtime) with $(gap)")
        Gurobi.terminate(backend(model).inner)
    end
    return
end

set_optimizer_attribute(model, "TimeLimit", hardlimit)
MOI.set(model, Gurobi.CallbackFunction(), softtime)
GC.enable(false)  # You might want this
optimize!(model)
GC.enable(true)  # You might want this
1 Like