Callbacks
This example uses the following packages:
using JuMP
import GLPK
import Random
Lazy constraints
An example using a lazy constraint callback.
function example_lazy_constraint()
model = Model(GLPK.Optimizer)
@variable(model, 0 <= x <= 2.5, Int)
@variable(model, 0 <= y <= 2.5, Int)
@objective(model, Max, y)
lazy_called = false
function my_callback_function(cb_data)
lazy_called = true
x_val = callback_value(cb_data, x)
y_val = callback_value(cb_data, y)
println("Called from (x, y) = ($x_val, $y_val)")
status = callback_node_status(cb_data, model)
if status == MOI.CALLBACK_NODE_STATUS_FRACTIONAL
println(" - Solution is integer infeasible!")
elseif status == MOI.CALLBACK_NODE_STATUS_INTEGER
println(" - Solution is integer feasible!")
else
@assert status == MOI.CALLBACK_NODE_STATUS_UNKNOWN
println(" - I don't know if the solution is integer feasible :(")
end
if y_val - x_val > 1 + 1e-6
con = @build_constraint(y - x <= 1)
println("Adding $(con)")
MOI.submit(model, MOI.LazyConstraint(cb_data), con)
elseif y_val + x_val > 3 + 1e-6
con = @build_constraint(y - x <= 1)
println("Adding $(con)")
MOI.submit(model, MOI.LazyConstraint(cb_data), con)
end
end
MOI.set(model, MOI.LazyConstraintCallback(), my_callback_function)
optimize!(model)
println("Optimal solution (x, y) = ($(value(x)), $(value(y)))")
return
end
example_lazy_constraint()
Called from (x, y) = (0.0, 2.0) - Solution is integer feasible! Adding ScalarConstraint{GenericAffExpr{Float64,VariableRef},MathOptInterface.LessThan{Float64}}(y - x, MathOptInterface.LessThan{Float64}(1.0)) Called from (x, y) = (1.0, 2.0) - Solution is integer feasible! Optimal solution (x, y) = (1.0, 2.0)
User-cut
An example using a user-cut callback.
function example_user_cut_constraint()
Random.seed!(1)
N = 30
item_weights, item_values = rand(N), rand(N)
model = Model(GLPK.Optimizer)
@variable(model, x[1:N], Bin)
@constraint(model, sum(item_weights[i] * x[i] for i = 1:N) <= 10)
@objective(model, Max, sum(item_values[i] * x[i] for i = 1:N))
callback_called = false
function my_callback_function(cb_data)
callback_called = true
x_vals = callback_value.(Ref(cb_data), x)
accumulated = sum(item_weights[i] for i = 1:N if x_vals[i] > 1e-4)
println("Called with accumulated = $(accumulated)")
n_terms = sum(1 for i = 1:N if x_vals[i] > 1e-4)
if accumulated > 10
con = @build_constraint(
sum(x[i] for i = 1:N if x_vals[i] > 0.5) <= n_terms - 1
)
println("Adding $(con)")
MOI.submit(model, MOI.UserCut(cb_data), con)
end
end
MOI.set(model, MOI.UserCutCallback(), my_callback_function)
optimize!(model)
@show callback_called
return
end
example_user_cut_constraint()
Called with accumulated = 10.245300779183612 Adding ScalarConstraint{GenericAffExpr{Float64,VariableRef},MathOptInterface.LessThan{Float64}}(x[1] + x[2] + x[4] + x[6] + x[7] + x[9] + x[10] + x[11] + x[12] + x[13] + x[14] + x[15] + x[16] + x[17] + x[18] + x[19] + x[20] + x[21] + x[22] + x[23] + x[24] + x[26] + x[29] + x[30], MathOptInterface.LessThan{Float64}(23.0)) Called with accumulated = 10.276817515233951 Adding ScalarConstraint{GenericAffExpr{Float64,VariableRef},MathOptInterface.LessThan{Float64}}(x[1] + x[2] + x[4] + x[6] + x[7] + x[9] + x[10] + x[11] + x[12] + x[13] + x[14] + x[16] + x[17] + x[18] + x[19] + x[20] + x[21] + x[22] + x[23] + x[24] + x[26] + x[29] + x[30], MathOptInterface.LessThan{Float64}(23.0)) Called with accumulated = 10.812296027897915 Adding ScalarConstraint{GenericAffExpr{Float64,VariableRef},MathOptInterface.LessThan{Float64}}(x[1] + x[2] + x[4] + x[6] + x[7] + x[9] + x[10] + x[11] + x[12] + x[13] + x[14] + x[16] + x[17] + x[18] + x[19] + x[20] + x[21] + x[22] + x[23] + x[24] + x[26] + x[29] + x[30], MathOptInterface.LessThan{Float64}(23.0)) callback_called = true
HeuristicCallback
An example using a heuristic solution callback.
function example_heuristic_solution()
Random.seed!(1)
N = 30
item_weights, item_values = rand(N), rand(N)
model = Model(GLPK.Optimizer)
@variable(model, x[1:N], Bin)
@constraint(model, sum(item_weights[i] * x[i] for i = 1:N) <= 10)
@objective(model, Max, sum(item_values[i] * x[i] for i = 1:N))
callback_called = false
function my_callback_function(cb_data)
callback_called = true
x_vals = callback_value.(Ref(cb_data), x)
ret = MOI.submit(
model, MOI.HeuristicSolution(cb_data), x, floor.(x_vals)
)
println("Heuristic solution status = $(ret)")
end
MOI.set(model, MOI.HeuristicCallback(), my_callback_function)
optimize!(model)
return
end
example_heuristic_solution()
Heuristic solution status = HEURISTIC_SOLUTION_ACCEPTED Heuristic solution status = HEURISTIC_SOLUTION_ACCEPTED Heuristic solution status = HEURISTIC_SOLUTION_REJECTED Heuristic solution status = HEURISTIC_SOLUTION_REJECTED
GLPK solver-dependent callback
An example using GLPK's solver-dependent callback.
function example_solver_dependent_callback()
model = Model(GLPK.Optimizer)
@variable(model, 0 <= x <= 2.5, Int)
@variable(model, 0 <= y <= 2.5, Int)
@objective(model, Max, y)
lazy_called = false
function my_callback_function(cb_data)
lazy_called = true
reason = GLPK.glp_ios_reason(cb_data.tree)
println("Called from reason = $(reason)")
if reason != GLPK.GLP_IROWGEN
return
end
x_val = callback_value(cb_data, x)
y_val = callback_value(cb_data, y)
if y_val - x_val > 1 + 1e-6
con = @build_constraint(y - x <= 1)
println("Adding $(con)")
MOI.submit(model, MOI.LazyConstraint(cb_data), con)
elseif y_val + x_val > 3 + 1e-6
con = @build_constraint(y - x <= 1)
println("Adding $(con)")
MOI.submit(model, MOI.LazyConstraint(cb_data), con)
end
end
MOI.set(model, GLPK.CallbackFunction(), my_callback_function)
optimize!(model)
return
end
example_solver_dependent_callback()
Called from reason = 6 Called from reason = 7 Called from reason = 1 Adding ScalarConstraint{GenericAffExpr{Float64,VariableRef},MathOptInterface.LessThan{Float64}}(y - x, MathOptInterface.LessThan{Float64}(1.0)) Called from reason = 7 Called from reason = 1 Called from reason = 2
This page was generated using Literate.jl.