Implement lazy callbacks

This commit is contained in:
2021-08-18 17:02:16 -05:00
parent 39072a6290
commit af3a5a69f0
8 changed files with 162 additions and 34 deletions

View File

@@ -2,29 +2,62 @@
# Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.
using Cbc
using JuMP
using MathOptInterface
using MIPLearn
const MOI = MathOptInterface
function find_lazy(model::Model, cb_data)::Vector{String}
x = variable_by_name(model, "x")
y = variable_by_name(model, "y")
x_val = value(cb_data, x)
y_val = value(cb_data, y)
if x_val + y_val > 1 + 1e-6
return ["con"]
end
return []
end
@testset "JuMPInstance" begin
@testset "Save and load" begin
# Build instance and solve
model = model = build_knapsack_model()
function enforce_lazy(model::Model, cb_data, violation::String)::Nothing
if violation == "con"
x = variable_by_name(model, "x")
y = variable_by_name(model, "y")
con = @build_constraint(x + y <= 1)
submit(cb_data, con)
end
return
end
function build_model()
model = Model()
@variable(model, x, Bin)
@variable(model, y, Bin)
@objective(model, Max, 2 * x + y)
@constraint(model, c1, x + y <= 2)
@lazycb(model, find_lazy, enforce_lazy)
return model
end
@testset "Lazy callback" begin
@testset "JuMPInstance" begin
model = build_model()
instance = JuMPInstance(model)
solver = LearningSolver(Gurobi.Optimizer)
stats = solve!(solver, instance)
@test length(instance.py.samples) == 1
solver = LearningSolver(Cbc.Optimizer)
solve!(solver, instance)
@test value(model[:x]) == 1.0
@test value(model[:y]) == 0.0
end
# Save model to file
@testset "FileInstance" begin
model = build_model()
instance = JuMPInstance(model)
filename = tempname()
save(filename, instance)
@test isfile(filename)
# Read model from file
loaded = load_instance(filename)
x = variable_by_name(loaded.model, "x")
@test loaded.model.ext[:miplearn][:variable_features][x] == [1.0]
@test loaded.model.ext[:miplearn][:variable_categories][x] == "cat1"
@test loaded.model.ext[:miplearn][:instance_features] == [5.0]
@test length(loaded.py.samples) == 1
file_instance = FileInstance(filename, lazycb = (find_lazy, enforce_lazy))
solver = LearningSolver(Cbc.Optimizer)
solve!(solver, file_instance)
h5 = MIPLearn.Hdf5Sample(filename)
@test h5.get_array("mip_var_values") == [1.0, 0.0]
end
end
end