# JUMP - Get MIP Gap during optimization

**URL:** <https://discourse.julialang.org/t/jump-get-mip-gap-during-optimization/44258>\
**Category:** Optimization (Mathematical)\
**Tags:** jump\
**Created:** [August 4, 2020, 1:48pm UTC](https://discourse.julialang.org/t/jump-get-mip-gap-during-optimization/44258 "2020-08-04T13:48:54Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tmart](https://avatars.discourse-cdn.com/v4/letter/t/bbe5ce/32.png) [@Tmart](https://discourse.julialang.org/u/Tmart)\
**Post date:** [August 4, 2020, 1:48pm UTC](https://discourse.julialang.org/t/jump-get-mip-gap-during-optimization/44258/1 "2020-08-04T13:48:55Z")

</div>

Hello,

I was wondering if it was possible to obtain the value of the MIP Gap at each step of the optimization process.

Thank you in advance,  
KR

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [August 4, 2020, 2:19pm UTC](https://discourse.julialang.org/t/jump-get-mip-gap-during-optimization/44258/2 "2020-08-04T14:19:11Z")

</div>

In general, no. Although some solvers (e.g., Gurobi or CPLEX) offer callbacks that you can access this information.

For example, here is an example setting a Gurobi-specific callback:  
[https://github.com/jump-dev/Gurobi.jl/blob/183a1c5916ff6253193e7242eba48a172ea7365f/test/MOI/MOI\_callbacks.jl#L315-L344](https://github.com/jump-dev/Gurobi.jl/blob/183a1c5916ff6253193e7242eba48a172ea7365f/test/MOI/MOI_callbacks.jl#L315-L344)

Implementing this will require you to understand Gurobi’s C API for callbacks.

---

<div class="post-metadata">

**Author:** ![ccoffrin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ccoffrin/32/400_2.png) [@ccoffrin](https://discourse.julialang.org/u/ccoffrin)\
**Post date:** [August 4, 2020, 2:34pm UTC](https://discourse.julialang.org/t/jump-get-mip-gap-during-optimization/44258/3 "2020-08-04T14:34:56Z")

</div>

Another option is to parse the text output log of the solver and extract the gap-overtime information from there. This is also a solver-specific solution.

---

<div class="post-metadata">

**Author:** ![mike\_k](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mike_k/32/211864_2.png) [@mike\_k](https://discourse.julialang.org/u/mike_k)\
**Post date:** [August 4, 2020, 3:09pm UTC](https://discourse.julialang.org/t/jump-get-mip-gap-during-optimization/44258/4 "2020-08-04T15:09:44Z")

</div>

Using CPLEX 12.9, I do this within solver-specific callbacks via function `CPXcallbackgetinfodbl`. For convenience define:

```julia
const CPXCALLBACKINFO_THREADID = convert(Cint,0)
const CPXCALLBACKINFO_NODECOUNT = convert(Cint,1)
const CPXCALLBACKINFO_ITCOUNT = convert(Cint,2)
const CPXCALLBACKINFO_BEST_SOL = convert(Cint,3)
const CPXCALLBACKINFO_BEST_BND = convert(Cint,4)
const CPXCALLBACKINFO_THREADS = convert(Cint,5)
const CPXCALLBACKINFO_FEASIBLE = convert(Cint,6)
const CPXCALLBACKINFO_TIME = convert(Cint,7)
const CPXCALLBACKINFO_DETTIME = convert(Cint,8)

```

and functions:

```julia
#current current best bound
function cpx_get_best_bnd( cb_data::CPLEX.CallbackContext )
    data_p = Ref{Cdouble}()
    return_status = CPLEX.@cpx_ccall(callbackgetinfodbl,
                                        Cint,
                                        (Ptr{Cvoid}, Cint, Ref{Cdouble}),
                                        cb_data.context, CPXCALLBACKINFO_BEST_BND, data_p)
    best_bnd = data_p[]

    if return_status != 0
        @warn "error retrieving best_bound"
    end
    return best_bnd::Float64
end

#current current best sol
function cpx_get_best_sol( cb_data::CPLEX.CallbackContext )
    data_p = Ref{Cdouble}()
    return_status = CPLEX.@cpx_ccall(callbackgetinfodbl,
                                        Cint,
                                        (Ptr{Cvoid}, Cint, Ref{Cdouble}),
                                        cb_data.context, CPXCALLBACKINFO_BEST_SOL, data_p)
    best_sol = data_p[]

    if return_status != 0
        @warn "error retrieving best_sol"
    end
    return best_sol::Float64
end

```

and then compute the current gap according to the CPLEX documentation as:

```julia
#compute current mip gap [%]
function cpx_get_mip_gap( cb_data::CPLEX.CallbackContext )
    mip_gap::Float64 = 0.0
    best_bnd = cpx_get_best_bnd( cb_data )
    best_sol = cpx_get_best_sol( cb_data )
    mip_gap = ((best_bnd - best_sol) / (0.0000000001 + best_sol)) * 100
    return mip_gap::Float64
end

```

Then simply call, e.g., `mygap = cpx_get_mip_gap( cb_data )` within a callback.

---

<div class="post-metadata">

**Author:** ![Tmart](https://avatars.discourse-cdn.com/v4/letter/t/bbe5ce/32.png) [@Tmart](https://discourse.julialang.org/u/Tmart)\
**Post date:** [August 5, 2020, 2:00pm UTC](https://discourse.julialang.org/t/jump-get-mip-gap-during-optimization/44258/5 "2020-08-05T14:00:04Z")

</div>

Thank you very much for your answers.

I am currently using Xpress. I see here [Callbacks · JuMP](https://jump.dev/JuMP.jl/v0.21.1/callbacks/) that callbacks are possible for CPLEX, GUROBI and GLPK. Are you aware if callbacks are possible for Xpress?

Thank you very much!

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [August 5, 2020, 2:05pm UTC](https://discourse.julialang.org/t/jump-get-mip-gap-during-optimization/44258/6 "2020-08-05T14:05:38Z")

</div>

Not yet: [https://github.com/jump-dev/Xpress.jl/pull/85](https://github.com/jump-dev/Xpress.jl/pull/85)
