Hi,
I’m currently diving into my first experience with callbacks and have a few doubts that I hope you can help clarify.
The goal is to implement callbacks that add user cuts to the root node (or subsequent nodes) based on the continuous relaxation values of some variables.
Is the solver-independent callback able to control where the user cuts are added in the branch, or is it necessary to use a solver-dependent callback?
I have followed the example in https://github.com/jump-dev/Gurobi.jl (section Callback), which considers Gurobi’s solver-specific callbacks. Instead of lazy constraints, I want to consider User cut.
Therefore, I adapt the code as follows:
- I removed
cb_where != GRB_CB_MIPSOL
because otherwise it returned an error ; in fact, the Gurobi manual says “This routine (user cut) can only be called when the where value on the callback routine is GRB_CB_MIPNODE”. In this way the cut should be add only if the solver is currently exploring a MIP node, and not for example in the presolve.
cb_calls = Cint[]
function my_callback_function(cb_data, cb_where::Cint)
push!(cb_calls, cb_where)
if cb_where != GRB_CB_MIPNODE
return
end
- I also added the following condition MIPNODE_NODCNT!=0 to consider the cut only in the root, but it does not seem to work because the parameter MIPNODE_NODCNT only takes the value 5005 (referred to as the callback constant) and thus it never adds the cut
if MIPNODE_NODCNT!=0
return
end
- I considered MOI.UserCut instead of MOI.LazyConstraint
- Is _val the value that the variable takes in the relaxation?
Gurobi.load_callback_variable_primal(cb_data, cb_where)
variable_val = callback_value(cb_data, variable)
if Condition-val-dependent
return
end
con = @build_constraint(constraint)
MOI.submit(model, MOI.UserCut(cb_data), con)
end # end of the function
MOI.set(model, Gurobi.CallbackFunction(), my_callback_function)
- Without the MIPNODE_NODCNT condition, after some iteration and after adding some cuts, I got the error
LoadError: Gurobi Error 10005
, described as “Attempted to query or set an attribute that could not be accessed at that time”. The error is followed by:
[1] _check_ret
[2] load_callback_variable_primal(cb_data::Gurobi.CallbackData, cb_where::Int32)
Any suggestions?
Thank you in advance,
Martina