Does anyone know how to retrieve the number of generated cuts in the informational callback?

Hi,

I would like to retrieve the information contained at the end of the Gurobi log (the summary section MIP Logging)

In particular, I am interested in saving the number of cuts applied to my MIP (MIP_CUTCNT : http://www.gurobi.com/documentation/8.0/refman/callback_codes.html#sec:CallbackCodes).
I couldn’t find a way to retrieve this information with cbget in MathProgbase.

Does anyone know how to do it?

Thanks!

This doesn’t appear to be wrapped at the MathProgBase level in Gurobi.jl, but following the example of cbgetmipsolution (Gurobi.jl/MPBWrapper.jl at 120d606da08facffb206d73d932dbb0bf7d7001d · jump-dev/Gurobi.jl · GitHub) you could write a similar wrapper that calls Gurobi.cbget_mip_cutcnt. I don’t have a Gurobi license so I can’t test this.

Thanks for your reply. I will try to write the wrapper for the mip_cutcnt myself.
Question: Can I just locally modify the MPBWrapper.jl function on my computer?

Considering the quite simple addition to MPBWrapper.jl and the relevance of such addition for the Julia/JuMP users implementing callback functions, I believe it would be nice to just add the wrapper to MathProgBase. Is this something you would consider?

As for the Gurobi licence, I think you can get a size-limited gurobi licence for free (Software Downloads and License Center - Gurobi).

Can I just locally modify the MPBWrapper.jl function on my computer?

Yes.

Is this something you would consider?

Yes! Have a look at the contributing guide (just replace any references to JuMP with Gurobi.jl).

If you’re not sure how to make a pull request: implement the wrapper locally, test that it works, then open an issue on the Gurobi.jl page, post the code you want to add, and we’ll walk you through the process.

Thanks for your reply.

Actually, implementing the wrapper does not appear to be that straight-forward (or at least not for me).
Following the example of cbgetmipsolution posted by @miles.lubin, I tried to implement the following in the MPBWrapper.jl :

function cbgetmipcutcnt(d::GurobiCallbackData)
@assert d.state == :MIPSol
return cbget_mip_cutcnt(d.cbdata, d.where)
end

function cbgetmipcutcnt(d::GurobiCallbackData,output)
@assert d.state == :MIPSol
return cbget_mip_cutcnt(d.cbdata, d.where, output)
end

but then i get the following error when running my code:

Could you please give any hint or help on how to code the wrapper?
Thanks!

A few pointers

  1. wrap your code in triple-backticks like so
    ```julia
    # code goes here
    ```
  1. copy the text of the error, rather than a screenshot since screenshots are usually really hard to read.
  2. Your error says cbgetmipcutcnt not defined. That probably means that you changed the Gurobi source file, but didn’t restart Julia (or use something like https://github.com/timholy/Revise.jl).
  3. You need to implement the function cbget_mip_cutcnt. This should be as simple as adding a new tuple to the list in this line with the value (:cbget_mip_cutcnt, XXXX), where XXX is the callback code you can look up in the Gurobi documentation http://www.gurobi.com/documentation/7.5/refman/callback_codes.html#sec:CallbackCodes. It’s actually already wrapped Gurobi.jl/grb_callbacks.jl at 120d606da08facffb206d73d932dbb0bf7d7001d · jump-dev/Gurobi.jl · GitHub

@odow thanks for your help.
Question: I see that there is a method definition for “mip_cutcnt”. Does it mean there is a way to call mip_cutcnt – For example numcuts=cbget_mip_cutcnt(cb,Cint(3))? (Gurobi.jl/grb_callbacks.jl at 120d606da08facffb206d73d932dbb0bf7d7001d · jump-dev/Gurobi.jl · GitHub)

When I try

#Produce an info callback
bbdata = Vector{Float64}[]
function infocallback(cb)
node = MathProgBase.cbgetexplorednodes(cb)
obj = MathProgBase.cbgetobj(cb)
bestbound = MathProgBase.cbgetbestbound(cb)
gap=(abs(bestbound-obj)/abs(obj))*100
**numcuts=cbget_mip_cutcnt(cb,Cint(3))**
push!(bbdata, [time(), node, obj, bestbound, gap])
end
addinfocallback(m, infocallback, when = :Intermediate)

I get the following error:

MethodError: no method matching cbget_mip_cutcnt(::Gurobi.GurobiCallbackData, ::Int32)e[0m
Closest candidates are:
cbget_mip_cutcnt(e[91m::Gurobi.CallbackDatae[39m, ::Int32) at C:\Users\bongiova.julia\v0.6\Gurobi\src\grb_callbacks.jl:138
(::#infocallback#238)(::Gurobi.GurobiCallbackData) at model_callback_full.jl:1205
infocallback(::Gurobi.GurobiCallbackData, ::JuMP.Model, ::Array{JuMP.InfoCallback,1}) at callbacks.jl:175
(::JuMP.##146#147{JuMP.Model,Array{JuMP.InfoCallback,1}})(::Gurobi.GurobiCallbackData) at callbacks.jl:192
mastercallback(::Ptr{Void}, ::Ptr{Void}, ::Int32, ::Ptr{Void}) at MPBWrapper.jl:695
optimize(::Gurobi.Model) at grb_solve.jl:5
optimize!(::Gurobi.GurobiMathProgModel) at MPBWrapper.jl:425
#solve#116(::Bool, ::Bool, ::Bool, ::Array{Any,1}, ::Function, ::JuMP.Model) at solvers.jl:175
macro expansion at model_callback_full.jl:1218 [inlined]
anonymous at :?
include_string(::String, ::String) at loading.jl:522
include_string(::String, ::String, ::Int64) at eval.jl:30
include_string(::Module, ::String, ::String, ::Int64, ::Vararg{Int64,N} where N) at eval.jl:34
(::Atom.##102#107{String,Int64,String})() at eval.jl:82
withpath(::Atom.##102#107{String,Int64,String}, ::String) at utils.jl:30
withpath(::Function, ::String) at eval.jl:38
hideprompt(::Atom.##101#106{String,Int64,String}) at repl.jl:67
macro expansion at eval.jl:80 [inlined]
(::Atom.##100#105{Dict{String,Any}})() at task.jl:80

I see that there is a method definition for “mip_cutcnt”.

Good spotting! In which case, the function you had above should work (once you add it to MPBWrapper.jl).

You should be able to call it as numcuts = Gurobi.cbgetmipcutcnt(cb).

@odow Thanks for your help!
The code is working. I opened an issue on the Gurobi.jl page with the code I want to add as you suggested :slight_smile:
https://github.com/JuliaOpt/Gurobi.jl/issues/160