From 22d42a5a503202b669d304af9948b3d8a6c3ddff Mon Sep 17 00:00:00 2001 From: odow Date: Sun, 1 Jan 2023 13:59:30 +1300 Subject: [PATCH 1/3] Change heuristic callback status to UNKNOWN instead of REJECTED --- src/MOI_wrapper/MOI_callbacks.jl | 8 ++++++-- test/MOI/MOI_callbacks.jl | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/MOI_wrapper/MOI_callbacks.jl b/src/MOI_wrapper/MOI_callbacks.jl index b7a300fa..7dcb1fb5 100644 --- a/src/MOI_wrapper/MOI_callbacks.jl +++ b/src/MOI_wrapper/MOI_callbacks.jl @@ -299,7 +299,11 @@ function MOI.submit( objP = Ref{Cdouble}() ret = GRBcbsolution(cb.callback_data, solution, objP) _check_ret(model, ret) - return objP[] < GRB_INFINITY ? MOI.HEURISTIC_SOLUTION_ACCEPTED : - MOI.HEURISTIC_SOLUTION_REJECTED + if objP[] < GRB_INFINITY + return MOI.HEURISTIC_SOLUTION_ACCEPTED + end + # Although not accepted at present, Gurobi may cache the solution and use it + # later in the optimization process. + return MOI.HEURISTIC_SOLUTION_UNKNOWN end MOI.supports(::Optimizer, ::MOI.HeuristicSolution{CallbackData}) = true diff --git a/test/MOI/MOI_callbacks.jl b/test/MOI/MOI_callbacks.jl index 4213168a..5530d3ef 100644 --- a/test/MOI/MOI_callbacks.jl +++ b/test/MOI/MOI_callbacks.jl @@ -320,7 +320,7 @@ function test_heuristic_callback() MOI.HeuristicSolution(cb_data), x, ceil.(x_vals), - ) == MOI.HEURISTIC_SOLUTION_REJECTED + ) == MOI.HEURISTIC_SOLUTION_UNKNOWN solution_rejected = true end end, From f1fa254f021acc0f710182e444970456d060a18c Mon Sep 17 00:00:00 2001 From: odow Date: Mon, 2 Jan 2023 10:10:00 +1300 Subject: [PATCH 2/3] Use cb_where to decide status --- src/MOI_wrapper/MOI_callbacks.jl | 4 ++++ test/MOI/MOI_callbacks.jl | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/MOI_wrapper/MOI_callbacks.jl b/src/MOI_wrapper/MOI_callbacks.jl index 7dcb1fb5..071e0f72 100644 --- a/src/MOI_wrapper/MOI_callbacks.jl +++ b/src/MOI_wrapper/MOI_callbacks.jl @@ -302,6 +302,10 @@ function MOI.submit( if objP[] < GRB_INFINITY return MOI.HEURISTIC_SOLUTION_ACCEPTED end + if cb.callback_data.cb_where == GRB_CB_MIPNODE + # In a MIPNODE callback, Gurobi will process the solution immediately. + return MOI.HEURISTIC_SOLUTION_REJECTED + end # Although not accepted at present, Gurobi may cache the solution and use it # later in the optimization process. return MOI.HEURISTIC_SOLUTION_UNKNOWN diff --git a/test/MOI/MOI_callbacks.jl b/test/MOI/MOI_callbacks.jl index 5530d3ef..b5feef9b 100644 --- a/test/MOI/MOI_callbacks.jl +++ b/test/MOI/MOI_callbacks.jl @@ -320,7 +320,7 @@ function test_heuristic_callback() MOI.HeuristicSolution(cb_data), x, ceil.(x_vals), - ) == MOI.HEURISTIC_SOLUTION_UNKNOWN + ) == MOI.HEURISTIC_SOLUTION_REJECTED solution_rejected = true end end, @@ -496,12 +496,18 @@ function test_CallbackFunction_callback_HeuristicSolution() model, x, item_weights = callback_knapsack_model() solution_accepted = false solution_rejected = false + solution_unknown = false cb_calls = Int32[] MOI.set( model, Gurobi.CallbackFunction(), (cb_data, cb_where) -> begin push!(cb_calls, cb_where) + if cb_where == Gurobi.GRB_CB_MIP + attr = MOI.HeuristicSolution(cb_data) + status = MOI.submit(model, attr, x, fill(2.0, length(x))) + solution_unknown |= (status == MOI.HEURISTIC_SOLUTION_UNKNOWN) + end if cb_where != Gurobi.GRB_CB_MIPNODE return end @@ -539,6 +545,7 @@ function test_CallbackFunction_callback_HeuristicSolution() MOI.optimize!(model) @test solution_accepted @test solution_rejected + @test solution_unknown @test Gurobi.GRB_CB_MIPNODE in cb_calls end From 1c80e23ed54938a18db4bc409c4be2e6d59bb913 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Mon, 2 Jan 2023 10:14:27 +1300 Subject: [PATCH 3/3] Update test/MOI/MOI_callbacks.jl --- test/MOI/MOI_callbacks.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/MOI/MOI_callbacks.jl b/test/MOI/MOI_callbacks.jl index b5feef9b..0262d7f8 100644 --- a/test/MOI/MOI_callbacks.jl +++ b/test/MOI/MOI_callbacks.jl @@ -506,7 +506,8 @@ function test_CallbackFunction_callback_HeuristicSolution() if cb_where == Gurobi.GRB_CB_MIP attr = MOI.HeuristicSolution(cb_data) status = MOI.submit(model, attr, x, fill(2.0, length(x))) - solution_unknown |= (status == MOI.HEURISTIC_SOLUTION_UNKNOWN) + solution_unknown |= + (status == MOI.HEURISTIC_SOLUTION_UNKNOWN) end if cb_where != Gurobi.GRB_CB_MIPNODE return