mirror of
https://github.com/ANL-CEEESA/MIPLearn.jl.git
synced 2025-12-06 00:18:51 -06:00
Start implementing JumpSolver
This commit is contained in:
@@ -1,6 +1,14 @@
|
||||
name = "MIPLearnT"
|
||||
uuid = "92db8938-9c6a-4af6-8bcc-af424cd0e2d5"
|
||||
authors = ["Alinson S. Xavier <git@axavier.org>"]
|
||||
version = "0.1.0"
|
||||
|
||||
[deps]
|
||||
HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f"
|
||||
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
|
||||
HiGHS = "87dc4568-4c63-4d18-b0c0-bb2238e4078b"
|
||||
JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
|
||||
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
||||
MIPLearn = "2b1277c3-b477-4c49-a15e-7ba350325c68"
|
||||
PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
|
||||
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
|
||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
|
||||
BIN
test/fixtures/bell5.h5
vendored
BIN
test/fixtures/bell5.h5
vendored
Binary file not shown.
@@ -1,13 +0,0 @@
|
||||
# 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 Revise
|
||||
using Test
|
||||
using MIPLearn
|
||||
|
||||
includet("Cuts/BlackBox/test_cplex.jl")
|
||||
|
||||
function runtests()
|
||||
test_cuts_blackbox_cplex()
|
||||
end
|
||||
@@ -7,14 +7,14 @@ using MIPLearn
|
||||
|
||||
function test_cuts_blackbox_cplex()
|
||||
# Prepare filenames
|
||||
mps_filename = joinpath(@__DIR__, "../../fixtures/bell5.mps.gz")
|
||||
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 = Hdf5Sample(h5_filename)
|
||||
h5 = H5File(h5_filename)
|
||||
rhs = h5.get_array("cuts_cpx_rhs")
|
||||
h5.file.close()
|
||||
@test length(rhs) > 0
|
||||
34
test/src/MIPLearnT.jl
Normal file
34
test/src/MIPLearnT.jl
Normal 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
|
||||
56
test/src/problems/test_setcover.jl
Normal file
56
test/src/problems/test_setcover.jl
Normal 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
|
||||
98
test/src/solvers/test_jump.jl
Normal file
98
test/src/solvers/test_jump.jl
Normal 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
37
test/src/test_h5.jl
Normal 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
|
||||
Reference in New Issue
Block a user