Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Undesired callback behavior #395

Closed
1ozturkbe opened this issue Feb 19, 2021 · 1 comment · Fixed by #448
Closed

Undesired callback behavior #395

1ozturkbe opened this issue Feb 19, 2021 · 1 comment · Fixed by #448
Labels
bug Help wanted! Wrapper: MathOptInterface Issue is specific to MOI wrapper

Comments

@1ozturkbe
Copy link

Here's a MWE of the issue. I hope it is pretty straightforward.

using JuMP
using Gurobi
m = Model(Gurobi.Optimizer)
@variable(m, x >= 1)
@objective(m, Min, x)
optimize!(m)

Running just the above code, if I check m.moi_backend.optimizer.model.generic_callback, I see that there is already a callback there, even though I didn't add it myself:

Gurobi._CallbackUserData(    sense  : minimize
    number of variables             = 1
    number of linear constraints    = 0
    number of quadratic constraints = 0
    number of sos constraints       = 0
    number of non-zero coeffs       = 0
    number of non-zero qp objective terms  = 0
    number of non-zero qp constraint terms = 0...

For some reason, running optimize! seems to just add a generic callback.
This is problematic, because if I try to add a callback as following:

function cb_fn(cb_data)
    val = JuMP.callback_value(x)
    con = @build_constraint(x >= 2)
    MOI.submit(m, MOI.LazyConstraint(cb_data), con)
end
MOI.set(m, MOI.LazyConstraintCallback(), cb_fn)
optimize!(m)

It throws the following error, since it thinks that I have both a Gurobi.CallbackFunction and an MOI one:

ERROR: Cannot use Gurobi.CallbackFunction as well as MOI.AbstractCallbackFunction
Stacktrace:
 [1] error(::String) at .\error.jl:33
 [2] _check_moi_callback_validity at C:\Users\berko\.julia\packages\Gurobi\Lci9Q\src\MOI_wrapper.jl:2372 [inlined]
 [3] optimize!(::Gurobi.Optimizer) at C:\Users\berko\.julia\packages\Gurobi\Lci9Q\src\MOI_wrapper.jl:2386
 [4] optimize!(::MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}) at C:\Users\iai\builds\InterpretableAI\SystemImage\SysImgBuilder\.julia\packages\MathOptInterface\ZJFKw\src\Bridges\bridge_optimizer.jl:264
 [5] optimize!(::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer,MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}) at C:\Users\iai\builds\InterpretableAI\SystemImage\SysImgBuilder\.julia\packages\MathOptInterface\ZJFKw\src\Utilities\cachingoptimizer.jl:215
 [6] optimize!(::Model, ::Nothing; bridge_constraints::Bool, ignore_optimize_hook::Bool, kwargs::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}) at C:\Users\iai\builds\InterpretableAI\SystemImage\SysImgBuilder\.julia\packages\JuMP\qhoVb\src\optimizer_interface.jl:130
 [7] optimize! at C:\Users\iai\builds\InterpretableAI\SystemImage\SysImgBuilder\.julia\packages\JuMP\qhoVb\src\optimizer_interface.jl:106 [inlined] (repeats 2 times)
 [8] top-level scope at REPL[61]:1

Furthermore, if I try to add the callback without the first optimize! to resolve the issue, it doesn't give the right solution, and returns 1 instead of 2! Please help. I'm using Gurobi 0.9.7 and JuMP 0.21.5.

@odow odow transferred this issue from jump-dev/JuMP.jl Feb 20, 2021
@odow
Copy link
Member

odow commented Feb 20, 2021

Transferred to Gurobi.jl

The issue is because of

Gurobi.jl/src/MOI_wrapper.jl

Lines 2385 to 2398 in 61b1178

# Initialize callbacks if necessary.
if _check_moi_callback_validity(model)
MOI.set(model, CallbackFunction(), _default_moi_callback(model))
model.has_generic_callback = false
elseif !model.has_generic_callback
# From the docstring of disable_sigint, "External functions that do not
# call julia code or julia runtime automatically disable sigint during
# their execution." We don't want this though! We want to be able to
# SIGINT Gurobi, and then catch it as an interrupt. As a hack, until
# Julia introduces an interruptible ccall --- which it likely won't
# https://github.com/JuliaLang/julia/issues/2622 --- set a null
# callback.
MOI.set(model, CallbackFunction(), (x, y) -> nothing)
end

The solution is probably just to set has_generic_callback back to false at the end of optimize! (but only if we set the null callback).

PRs accepted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Help wanted! Wrapper: MathOptInterface Issue is specific to MOI wrapper
Development

Successfully merging a pull request may close this issue.

2 participants