diff --git a/Project.toml b/Project.toml index 2a45202..c1b9ded 100644 --- a/Project.toml +++ b/Project.toml @@ -13,13 +13,15 @@ JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" JuMP = "4076af6c-e467-56ae-b986-b466b2749572" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" +MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" PackageCompiler = "9b87118b-4619-50d2-8e1e-99f35a4d4d9d" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +Requires = "ae029012-a4dd-5104-9daa-d747884805df" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb" TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" -MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" [compat] DataStructures = "0.18" @@ -27,8 +29,8 @@ Distributions = "0.25" GZip = "0.5" JSON = "0.21" JuMP = "1" -MathOptInterface = "1" MPI = "0.20" +MathOptInterface = "1" PackageCompiler = "1" +TimerOutputs = "0.5" julia = "1" -TimerOutputs = "0.5" \ No newline at end of file diff --git a/src/UnitCommitment.jl b/src/UnitCommitment.jl index d46d71e..d447228 100644 --- a/src/UnitCommitment.jl +++ b/src/UnitCommitment.jl @@ -4,6 +4,8 @@ module UnitCommitment +using Requires + using Base: String include("instance/structs.jl") @@ -72,4 +74,11 @@ include("lmp/conventional.jl") include("lmp/aelmp.jl") include("market/market.jl") +function __init__() + @require MIPLearn = "2b1277c3-b477-4c49-a15e-7ba350325c68" begin + include("solution/methods/MIPLearn/structs.jl") + include("solution/methods/MIPLearn/miplearn.jl") + end +end + end diff --git a/src/solution/methods/MIPLearn/miplearn.jl b/src/solution/methods/MIPLearn/miplearn.jl new file mode 100644 index 0000000..dc4f8ba --- /dev/null +++ b/src/solution/methods/MIPLearn/miplearn.jl @@ -0,0 +1,71 @@ +# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment +# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. +# Released under the modified BSD license. See COPYING.md for more details. + +using .MIPLearn +using Suppressor +using JuMP + +function _build_ucjl_model(instance, method) + if instance isa String + instance = UnitCommitment.read(instance) + end + model = UnitCommitment.build_model( + instance = instance, + optimizer = method.optimizer, + variable_names = true, + ) + write_to_file(model, "/tmp/model.lp") + return JumpModel(model) +end + +function _set_default_collectors!(method::MIPLearnMethod) + method.collectors = [BasicCollector()] + return +end + +function _set_default_solver!(method::MIPLearnMethod) + KNN = MIPLearn.pyimport("sklearn.neighbors").KNeighborsClassifier + method.solver = LearningSolver( + components = [ + MemorizingPrimalComponent( + clf = KNN(n_neighbors = 30), + extractor = H5FieldsExtractor( + instance_fields = ["static_var_obj_coeffs"], + ), + constructor = MergeTopSolutions(30, [0.0, 1.0]), + action = FixVariables(), + ), + ], + ) + return +end + +function collect!(filenames::Vector, method::MIPLearnMethod) + build(x) = _build_ucjl_model(x, method) + if method.collectors === nothing + _set_default_collectors!(method) + end + for c in method.collectors + c.collect(filenames, build) + end +end + +function fit!(filenames::Vector, method::MIPLearnMethod) + if method.solver === nothing + _set_default_solver!(method) + end + return method.solver.fit(filenames) +end + +function optimize!(filename::AbstractString, method::MIPLearnMethod) + build(x) = _build_ucjl_model(x, method) + method.solver.optimize(filename, build) + return +end + +function optimize!(instance::UnitCommitmentInstance, method::MIPLearnMethod) + model = _build_ucjl_model(instance, method) + method.solver.optimize(model) + return +end \ No newline at end of file diff --git a/src/solution/methods/MIPLearn/structs.jl b/src/solution/methods/MIPLearn/structs.jl new file mode 100644 index 0000000..893cee9 --- /dev/null +++ b/src/solution/methods/MIPLearn/structs.jl @@ -0,0 +1,11 @@ +# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment +# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. +# Released under the modified BSD license. See COPYING.md for more details. + +using Suppressor + +Base.@kwdef mutable struct MIPLearnMethod + optimizer::Any + collectors::Any = nothing + solver::Any = nothing +end diff --git a/test/Project.toml b/test/Project.toml index 167e679..e326b64 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -13,6 +13,7 @@ JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" JuMP = "4076af6c-e467-56ae-b986-b466b2749572" JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +MIPLearn = "2b1277c3-b477-4c49-a15e-7ba350325c68" MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" diff --git a/test/fixtures/case14.json.gz.h5 b/test/fixtures/case14.json.gz.h5 new file mode 100644 index 0000000..3439024 Binary files /dev/null and b/test/fixtures/case14.json.gz.h5 differ diff --git a/test/src/UnitCommitmentT.jl b/test/src/UnitCommitmentT.jl index ae28329..f72b1e9 100644 --- a/test/src/UnitCommitmentT.jl +++ b/test/src/UnitCommitmentT.jl @@ -1,6 +1,7 @@ module UnitCommitmentT using JuliaFormatter +using MIPLearn using UnitCommitment using Test @@ -16,6 +17,7 @@ include("solution/methods/ProgressiveHedging/usage_test.jl") include("solution/methods/TimeDecomposition/initial_status_test.jl") include("solution/methods/TimeDecomposition/optimize_test.jl") include("solution/methods/TimeDecomposition/update_solution_test.jl") +include("solution/methods/MIPLearn/usage_test.jl") include("transform/initcond_test.jl") include("transform/slice_test.jl") include("transform/randomize/XavQiuAhm2021_test.jl") @@ -46,6 +48,7 @@ function runtests() solution_methods_TimeDecomposition_initial_status_test() solution_methods_TimeDecomposition_optimize_test() solution_methods_TimeDecomposition_update_solution_test() + solution_methods_MIPLearn_usage_test() transform_initcond_test() transform_slice_test() transform_randomize_XavQiuAhm2021_test() diff --git a/test/src/solution/methods/MIPLearn/usage_test.jl b/test/src/solution/methods/MIPLearn/usage_test.jl new file mode 100644 index 0000000..1abc98e --- /dev/null +++ b/test/src/solution/methods/MIPLearn/usage_test.jl @@ -0,0 +1,20 @@ +# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment +# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved. +# Released under the modified BSD license. See COPYING.md for more details. + +using HiGHS + +function solution_methods_MIPLearn_usage_test() + dirname = mktempdir() + cp(fixture("case14.json.gz"), "$dirname/case14.json.gz") + train_data = ["$dirname/case14.json.gz"] + + method = UnitCommitment.MIPLearnMethod(optimizer = HiGHS.Optimizer) + UnitCommitment.collect!(train_data, method) + UnitCommitment.fit!(train_data, method) + UnitCommitment.optimize!(train_data[1], method) + + instance = UnitCommitment.read(train_data[1]) + UnitCommitment.optimize!(instance, method) + return +end