I would like to access the values during each iterations, then plot the objective function (maybe more info) against iterations, I wrote a callback function as below. I found that my cb_where is never equal to GRB_CB_MIP or GRB_CB_SIMPLEX, so that this "I’m here… " phrase is never printed…

Then, I want to try something solver-independent with my_callback_function2, but it’s not working as well…

Thanks ahead for help.

env = Gurobi.Env()
ot_model = direct_model(Gurobi.Optimizer(env))
# ot_model = Model(Gurobi.Optimizer)
@variable(ot_model, p[1:I, 1:J] >= 0)
@variable(ot_model, z[1:I])
@constraint(ot_model, p * ones(J) .== ones(I))
@constraint(ot_model, transpose(p) * μ .== ν)
@constraint(ot_model, [i = 1:I], z[i] >= (X[i] - (p * Y)[i])^2)
@objective(ot_model, Min, sum(μ[i] * z[i] for i = 1:I))
function my_callback_function1(cb_data, cb_where::Cint)
# GRB_CB_SIMPLEX GRB_CB_MIP
if cb_where == GRB_CB_MIP || cb_where == GRB_CB_SIMPLEX ||cb_where == GRB_CB_MIPSOL
print("I'm here... ")
Gurobi.load_callback_variable_primal(cb_data, cb_where)
z_val = callback_value(cb_data, z)
print("The currenct z value is ", z_val)
end
end
function my_callback_function2(cb_data)
z_val = callback_value(cb_data, z)
print("The currenct z value is ", z_val)
end
MOI.set(ot_model, Gurobi.CallbackFunction(), my_callback_function2)
optimize!(ot_model)

If you want to get the current best objective on each new MIP incumbent node, you should use the GRB_CB_MIPSOL_OBJBST code on new MIP nodes (GRB_CB_MIPSOL) as follows:

function my_callback_function(cb_data, cb_where)
if cb_where == GRB_CB_MIPSOL
current_best_obj = Ref{Cdouble}()
GRBcbget(cb_data, cb_where, GRB_CB_MIPSOL_OBJBST, current_best_obj)
current_best_obj_val = current_bestobj[]
println("Current best objective: $current_best_obj_val")
end
end

As for solver independent callbacks, it depends on which solvers you will be working with, personally I find it better to write solver specific callbacks.

Actually I am just looking at your model and you have a quadratic term there so that may have something to do, not sure, will look into it, but I definitely can run the model if you want to.

You could see where the callback is being called from with

function my_callback_function1(cb_data, cb_where::Cint)
print("Calling from $cb_where")
end
MOI.set(ot_model, Gurobi.CallbackFunction(), my_callback_function1)

The answer for your problem is probably that it isn’t a MIP, so GRB_CB_MIP and GRB_CB_MIPSOL are never called, and Gurobi doesn’t solve this with the simplex method, so GRB_CB_SIMPLEX is never called.

For the solver independent callback, you need to follow Solver-independent Callbacks · JuMP. This likely won’t work with Gurobi because these callbacks are intended only for MIPs, and your problem does not have integer variables.