Start implementing JumpSolver

This commit is contained in:
2023-03-21 10:45:27 -05:00
parent 64101c495c
commit 5bc909d62f
15 changed files with 624 additions and 79 deletions

View File

@@ -0,0 +1,21 @@
# MIPLearn: Extensible Framework for Learning-Enhanced Mixed-Integer Optimization
# Copyright (C) 2020-2023, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.
using HDF5
using MIPLearn
function test_cuts_blackbox_cplex()
# Prepare filenames
mps_filename = "$FIXTURES/bell5.mps.gz"
h5_filename = replace(mps_filename, ".mps.gz" => ".h5")
# Run collector
MIPLearn.collect(mps_filename, CplexBlackBoxCuts())
# Read HDF5 file
h5 = H5File(h5_filename)
rhs = h5.get_array("cuts_cpx_rhs")
h5.file.close()
@test length(rhs) > 0
end

34
test/src/MIPLearnT.jl Normal file
View File

@@ -0,0 +1,34 @@
module MIPLearnT
using Test
using Logging
using JuliaFormatter
using HiGHS
BASEDIR = dirname(@__FILE__)
FIXTURES = "$BASEDIR/../fixtures"
include("Cuts/BlackBox/test_cplex.jl")
include("problems/test_setcover.jl")
include("test_h5.jl")
include("solvers/test_jump.jl")
function runtests()
@testset "MIPLearn" begin
test_cuts_blackbox_cplex()
test_h5()
test_problems_setcover()
test_solvers_jump()
end
end
function format()
JuliaFormatter.format(BASEDIR, verbose = true)
JuliaFormatter.format("$BASEDIR/../../src", verbose = true)
return
end
export runtests, format
end # module MIPLearnT

View File

@@ -0,0 +1,56 @@
using PyCall
function test_problems_setcover()
test_problems_setcover_generator()
test_problems_setcover_model()
end
function test_problems_setcover_generator()
np = pyimport("numpy")
scipy_stats = pyimport("scipy.stats")
randint = scipy_stats.randint
uniform = scipy_stats.uniform
np.random.seed(42)
gen = SetCoverGenerator(
n_elements = randint(low = 3, high = 4),
n_sets = randint(low = 5, high = 6),
costs = uniform(loc = 0.0, scale = 100.0),
costs_jitter = uniform(loc = 0.95, scale = 0.10),
density = uniform(loc = 0.5, scale = 0),
K = uniform(loc = 25, scale = 0),
fix_sets = false,
)
data = gen.generate(2)
@test data[1].costs == [136.75, 86.17, 25.71, 27.31, 102.48]
@test data[1].incidence_matrix == [
1 0 1 0 1
1 1 0 0 0
1 0 0 1 1
]
@test data[2].costs == [63.54, 76.6, 48.09, 74.1, 93.33]
@test data[2].incidence_matrix == [
1 1 0 1 1
0 1 0 1 0
0 1 1 0 0
]
end
function test_problems_setcover_model()
data = SetCoverData(
costs = [5, 10, 12, 6, 8],
incidence_matrix = [
1 0 0 1 0
1 1 0 0 0
0 0 1 1 1
],
)
h5 = H5File(tempname(), "w")
model = build_setcover_model(data)
model.extract_after_load(h5)
model.optimize()
model.extract_after_mip(h5)
@test h5.get_scalar("mip_obj_value") == 11.0
h5.close()
end

View File

@@ -0,0 +1,98 @@
function build_model()
data = SetCoverData(
costs = [5, 10, 12, 6, 8],
incidence_matrix = [
1 0 0 1 0
1 1 0 0 0
0 0 1 1 1
],
)
return build_setcover_model(data)
end
function test_solvers_jump()
test_solvers_jump_extract()
end
function test_solvers_jump_extract()
h5 = H5File(tempname(), "w")
function test_scalar(key, expected)
actual = h5.get_scalar(key)
@test actual !== nothing
@test actual == expected
end
function test_sparse(key, expected)
actual = h5.get_sparse(key)
@test actual !== nothing
@test all(actual == expected)
end
function test_str_array(key, expected)
actual = MIPLearn.from_str_array(h5.get_array(key))
@debug actual, expected
@test actual !== nothing
@test all(actual .== expected)
end
function test_array(key, expected)
actual = h5.get_array(key)
@debug actual, expected
@test actual !== nothing
@test all(actual .≈ expected)
end
model = build_model()
model.extract_after_load(h5)
test_sparse(
"static_constr_lhs",
[
1 0 0 1 0
1 1 0 0 0
0 0 1 1 1
],
)
test_str_array("static_constr_names", ["eqs[0]", "eqs[1]", "eqs[2]"])
test_array("static_constr_rhs", [1, 1, 1])
test_str_array("static_constr_sense", [">", ">", ">"])
test_scalar("static_obj_offset", 0)
test_scalar("static_sense", "min")
test_array("static_var_lower_bounds", [0, 0, 0, 0, 0])
test_str_array("static_var_names", ["x[0]", "x[1]", "x[2]", "x[3]", "x[4]"])
test_array("static_var_obj_coeffs", [5, 10, 12, 6, 8])
test_str_array("static_var_types", ["B", "B", "B", "B", "B"])
test_array("static_var_upper_bounds", [1, 1, 1, 1, 1])
relaxed = model.relax()
relaxed.optimize()
relaxed.extract_after_lp(h5)
test_array("lp_constr_dual_values", [0, 10, 6])
test_array("lp_constr_slacks", [1, 0, 0])
test_scalar("lp_obj_value", 11)
test_array("lp_var_reduced_costs", [-5, 0, 6, 0, 2])
test_array("lp_var_values", [1, 0, 0, 1, 0])
test_str_array("lp_var_basis_status", ["U", "B", "L", "B", "L"])
test_str_array("lp_constr_basis_status", ["B","N","N"])
test_array("lp_constr_sa_rhs_up", [2, 2, 1])
test_array("lp_constr_sa_rhs_down", [-Inf, 1, 0])
test_array("lp_var_sa_obj_up", [10, Inf, Inf, 8, Inf])
test_array("lp_var_sa_obj_down", [-Inf, 5, 6, 0, 6])
test_array("lp_var_sa_ub_up", [1, Inf, Inf, Inf, Inf])
test_array("lp_var_sa_ub_down", [0, 0, 0, 1, 0])
test_array("lp_var_sa_lb_up", [1, 0, 1, 1, 1])
test_array("lp_var_sa_lb_down", [-Inf, -Inf, 0, -Inf, 0])
lp_wallclock_time = h5.get_scalar("lp_wallclock_time")
@test lp_wallclock_time >= 0
model.optimize()
model.extract_after_mip(h5)
test_array("mip_constr_slacks", [1, 0, 0])
test_array("mip_var_values", [1.0, 0.0, 0.0, 1.0, 0.0])
test_scalar("mip_gap", 0)
test_scalar("mip_obj_bound", 11.0)
test_scalar("mip_obj_value", 11.0)
mip_wallclock_time = h5.get_scalar("mip_wallclock_time")
@test mip_wallclock_time >= 0
end

37
test/src/test_h5.jl Normal file
View File

@@ -0,0 +1,37 @@
using MIPLearn
function test_h5()
h5 = H5File(tempname(), "w")
_test_roundtrip_scalar(h5, "A")
_test_roundtrip_scalar(h5, true)
_test_roundtrip_scalar(h5, 1)
_test_roundtrip_scalar(h5, 1.0)
@test h5.get_scalar("unknown-key") === nothing
_test_roundtrip_array(h5, [true, false])
_test_roundtrip_array(h5, [1, 2, 3])
_test_roundtrip_array(h5, [1.0, 2.0, 3.0])
_test_roundtrip_str_array(h5, ["A", "BB", "CCC"])
@test h5.get_array("unknown-key") === nothing
h5.close()
end
function _test_roundtrip_scalar(h5, original)
h5.put_scalar("key", original)
recovered = h5.get_scalar("key")
@test recovered !== nothing
@test original == recovered
end
function _test_roundtrip_array(h5, original)
h5.put_array("key", original)
recovered = h5.get_array("key")
@test recovered !== nothing
@test all(original .== recovered)
end
function _test_roundtrip_str_array(h5, original)
h5.put_array("key", MIPLearn.to_str_array(original))
recovered = MIPLearn.from_str_array(h5.get_array("key"))
@test recovered !== nothing
@test all(original .== recovered)
end