The docs state that JuMP’s solver-independent callback feature supports SCIP.
However, if I replace the lazy constraint example (which uses GLPK) with SCIP, I get the following error
julia> using JuMP
julia> import SCIP
julia> model = Model(SCIP.Optimizer);
julia> @variable(model, x <= 10, Int)
x
julia> @objective(model, Max, x)
x
julia> function my_callback_function(cb_data)
status = callback_node_status(cb_data, model)
if status == MOI.CALLBACK_NODE_STATUS_FRACTIONAL
# `callback_value(cb_data, x)` is not integer (to some tolerance).
# If, for example, your lazy constraint generator requires an
# integer-feasible primal solution, you can add a `return` here.
return
elseif status == MOI.CALLBACK_NODE_STATUS_INTEGER
# `callback_value(cb_data, x)` is integer (to some tolerance).
else
@assert status == MOI.CALLBACK_NODE_STATUS_UNKNOWN
# `callback_value(cb_data, x)` might be fractional or integer.
end
x_val = callback_value(cb_data, x)
if x_val > 2 + 1e-6
con = @build_constraint(x <= 2)
MOI.submit(model, MOI.LazyConstraint(cb_data), con)
end
end
my_callback_function (generic function with 1 method)
julia> set_attribute(model, MOI.LazyConstraintCallback(), my_callback_function)
julia> optimize!(model)
ERROR: MathOptInterface.UnsupportedAttribute{MathOptInterface.LazyConstraintCallback}: Attribute MathOptInterface.LazyConstraintCallback() is not supported by the model.
Stacktrace:
[1] throw_set_error_fallback(model::SCIP.Optimizer, attr::MathOptInterface.LazyConstraintCallback, value::Function; error_if_supported::MathOptInterface.SetAttributeNotAllowed{MathOptInterface.LazyConstraintCallback})
@ MathOptInterface ~/.julia/packages/MathOptInterface/yczX1/src/attributes.jl:586
[2] throw_set_error_fallback(model::SCIP.Optimizer, attr::MathOptInterface.LazyConstraintCallback, value::Function)
@ MathOptInterface ~/.julia/packages/MathOptInterface/yczX1/src/attributes.jl:577
[3] set(model::SCIP.Optimizer, attr::MathOptInterface.LazyConstraintCallback, args::Function)
@ MathOptInterface ~/.julia/packages/MathOptInterface/yczX1/src/attributes.jl:550
[4] set(b::MathOptInterface.Bridges.LazyBridgeOptimizer{SCIP.Optimizer}, attr::MathOptInterface.LazyConstraintCallback, value::Function)
@ MathOptInterface.Bridges ~/.julia/packages/MathOptInterface/yczX1/src/Bridges/bridge_optimizer.jl:955
[5] _pass_attribute(dest::MathOptInterface.Bridges.LazyBridgeOptimizer{SCIP.Optimizer}, src::MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}, index_map::MathOptInterface.Utilities.IndexMap, attr::MathOptInterface.LazyConstraintCallback)
@ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/yczX1/src/Utilities/copy.jl:55
[6] pass_attributes(dest::MathOptInterface.Bridges.LazyBridgeOptimizer{SCIP.Optimizer}, src::MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}, index_map::MathOptInterface.Utilities.IndexMap)
@ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/yczX1/src/Utilities/copy.jl:42
[7] default_copy_to(dest::MathOptInterface.Bridges.LazyBridgeOptimizer{SCIP.Optimizer}, src::MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}})
@ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/yczX1/src/Utilities/copy.jl:506
[8] copy_to
@ ~/.julia/packages/MathOptInterface/yczX1/src/Bridges/bridge_optimizer.jl:455 [inlined]
[9] attach_optimizer(model::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{SCIP.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}})
@ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/yczX1/src/Utilities/cachingoptimizer.jl:220
[10] optimize!(m::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{SCIP.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}})
@ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/yczX1/src/Utilities/cachingoptimizer.jl:312
[11] optimize!(model::Model; ignore_optimize_hook::Bool, _differentiation_backend::MathOptInterface.Nonlinear.SparseReverseMode, kwargs::@Kwargs{})
@ JuMP ~/.julia/packages/JuMP/027Gt/src/optimizer_interface.jl:448
[12] optimize!(model::Model)
@ JuMP ~/.julia/packages/JuMP/027Gt/src/optimizer_interface.jl:409
[13] top-level scope
@ REPL[8]:1
It runs fine if I replace SCIP with GLPK (as in the example from the documentation).
Any ideas on why this might be the case? Are solver-independent callbacks actually supported by SCIP?
Thanks in advance!
Julia version 1.10.0 on WSL2 with
(@v1.10) pkg> st JuMP SCIP
Status `~/.julia/environments/v1.10/Project.toml`
[4076af6c] JuMP v1.18.1
[82193955] SCIP v0.11.14