From 38259428e40194e2a8c3651483e10708670b7874 Mon Sep 17 00:00:00 2001 From: Alinson S Xavier Date: Tue, 1 Jun 2021 08:21:47 -0500 Subject: [PATCH] Reorganize test folder --- .gitignore | 1 + test/convert_test.jl | 22 --- test/import/egret_test.jl | 20 +++ test/instance/read_test.jl | 115 +++++++++++++ test/instance_test.jl | 158 ------------------ test/model/build_test.jl | 37 ++++ test/model_test.jl | 39 ----- test/runtests.jl | 28 +++- test/screening_test.jl | 115 ------------- test/sensitivity_test.jl | 145 ---------------- .../methods/XavQiuWanThi19/filter_test.jl | 83 +++++++++ .../methods/XavQiuWanThi19/find_test.jl | 35 ++++ .../XavQiuWanThi19/sensitivity_test.jl | 143 ++++++++++++++++ test/{ => transform}/initcond_test.jl | 2 +- test/transform/slice_test.jl | 46 +++++ test/validate_test.jl | 43 ----- test/validation/repair_test.jl | 39 +++++ 17 files changed, 541 insertions(+), 530 deletions(-) delete mode 100644 test/convert_test.jl create mode 100644 test/import/egret_test.jl create mode 100644 test/instance/read_test.jl delete mode 100644 test/instance_test.jl create mode 100644 test/model/build_test.jl delete mode 100644 test/model_test.jl delete mode 100644 test/screening_test.jl delete mode 100644 test/sensitivity_test.jl create mode 100644 test/solution/methods/XavQiuWanThi19/filter_test.jl create mode 100644 test/solution/methods/XavQiuWanThi19/find_test.jl create mode 100644 test/solution/methods/XavQiuWanThi19/sensitivity_test.jl rename test/{ => transform}/initcond_test.jl (95%) create mode 100644 test/transform/slice_test.jl delete mode 100644 test/validate_test.jl create mode 100644 test/validation/repair_test.jl diff --git a/.gitignore b/.gitignore index c390e5b..f6abaa9 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ benchmark/results benchmark/runs benchmark/tables +benchmark/tmp.json build instances/**/*.json instances/_source diff --git a/test/convert_test.jl b/test/convert_test.jl deleted file mode 100644 index 82c8239..0000000 --- a/test/convert_test.jl +++ /dev/null @@ -1,22 +0,0 @@ -# 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 UnitCommitment - -@testset "convert" begin - @testset "EGRET solution" begin - solution = - UnitCommitment.read_egret_solution("fixtures/egret_output.json.gz") - for attr in ["Is on", "Production (MW)", "Production cost (\$)"] - @test attr in keys(solution) - @test "115_STEAM_1" in keys(solution[attr]) - @test length(solution[attr]["115_STEAM_1"]) == 48 - end - @test solution["Production cost (\$)"]["315_CT_6"][15:20] == - [0.0, 0.0, 884.44, 1470.71, 1470.71, 884.44] - @test solution["Startup cost (\$)"]["315_CT_6"][15:20] == - [0.0, 0.0, 5665.23, 0.0, 0.0, 0.0] - @test length(keys(solution["Is on"])) == 154 - end -end diff --git a/test/import/egret_test.jl b/test/import/egret_test.jl new file mode 100644 index 0000000..60b481d --- /dev/null +++ b/test/import/egret_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 UnitCommitment + +@testset "read_egret_solution" begin + solution = + UnitCommitment.read_egret_solution("fixtures/egret_output.json.gz") + for attr in ["Is on", "Production (MW)", "Production cost (\$)"] + @test attr in keys(solution) + @test "115_STEAM_1" in keys(solution[attr]) + @test length(solution[attr]["115_STEAM_1"]) == 48 + end + @test solution["Production cost (\$)"]["315_CT_6"][15:20] == + [0.0, 0.0, 884.44, 1470.71, 1470.71, 884.44] + @test solution["Startup cost (\$)"]["315_CT_6"][15:20] == + [0.0, 0.0, 5665.23, 0.0, 0.0, 0.0] + @test length(keys(solution["Is on"])) == 154 +end diff --git a/test/instance/read_test.jl b/test/instance/read_test.jl new file mode 100644 index 0000000..915a5c8 --- /dev/null +++ b/test/instance/read_test.jl @@ -0,0 +1,115 @@ +# 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 UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip + +@testset "read_benchmark" begin + instance = UnitCommitment.read_benchmark("test/case14") + + @test length(instance.lines) == 20 + @test length(instance.buses) == 14 + @test length(instance.units) == 6 + @test length(instance.contingencies) == 19 + @test length(instance.price_sensitive_loads) == 1 + @test instance.time == 4 + + @test instance.lines[5].name == "l5" + @test instance.lines[5].source.name == "b2" + @test instance.lines[5].target.name == "b5" + @test instance.lines[5].reactance ≈ 0.17388 + @test instance.lines[5].susceptance ≈ 10.037550333 + @test instance.lines[5].normal_flow_limit == [1e8 for t in 1:4] + @test instance.lines[5].emergency_flow_limit == [1e8 for t in 1:4] + @test instance.lines[5].flow_limit_penalty == [5e3 for t in 1:4] + + @test instance.lines[1].name == "l1" + @test instance.lines[1].source.name == "b1" + @test instance.lines[1].target.name == "b2" + @test instance.lines[1].reactance ≈ 0.059170 + @test instance.lines[1].susceptance ≈ 29.496860773945 + @test instance.lines[1].normal_flow_limit == [300.0 for t in 1:4] + @test instance.lines[1].emergency_flow_limit == [400.0 for t in 1:4] + @test instance.lines[1].flow_limit_penalty == [1e3 for t in 1:4] + + @test instance.buses[9].name == "b9" + @test instance.buses[9].load == [35.36638, 33.25495, 31.67138, 31.14353] + + unit = instance.units[1] + @test unit.name == "g1" + @test unit.bus.name == "b1" + @test unit.ramp_up_limit == 1e6 + @test unit.ramp_down_limit == 1e6 + @test unit.startup_limit == 1e6 + @test unit.shutdown_limit == 1e6 + @test unit.must_run == [false for t in 1:4] + @test unit.min_power_cost == [1400.0 for t in 1:4] + @test unit.min_uptime == 1 + @test unit.min_downtime == 1 + @test unit.provides_spinning_reserves == [true for t in 1:4] + for t in 1:1 + @test unit.cost_segments[1].mw[t] == 10.0 + @test unit.cost_segments[2].mw[t] == 20.0 + @test unit.cost_segments[3].mw[t] == 5.0 + @test unit.cost_segments[1].cost[t] ≈ 20.0 + @test unit.cost_segments[2].cost[t] ≈ 30.0 + @test unit.cost_segments[3].cost[t] ≈ 40.0 + end + @test length(unit.startup_categories) == 3 + @test unit.startup_categories[1].delay == 1 + @test unit.startup_categories[2].delay == 2 + @test unit.startup_categories[3].delay == 3 + @test unit.startup_categories[1].cost == 1000.0 + @test unit.startup_categories[2].cost == 1500.0 + @test unit.startup_categories[3].cost == 2000.0 + + unit = instance.units[2] + @test unit.name == "g2" + @test unit.must_run == [false for t in 1:4] + + unit = instance.units[3] + @test unit.name == "g3" + @test unit.bus.name == "b3" + @test unit.ramp_up_limit == 70.0 + @test unit.ramp_down_limit == 70.0 + @test unit.startup_limit == 70.0 + @test unit.shutdown_limit == 70.0 + @test unit.must_run == [true for t in 1:4] + @test unit.min_power_cost == [0.0 for t in 1:4] + @test unit.min_uptime == 1 + @test unit.min_downtime == 1 + @test unit.provides_spinning_reserves == [true for t in 1:4] + for t in 1:4 + @test unit.cost_segments[1].mw[t] ≈ 33 + @test unit.cost_segments[2].mw[t] ≈ 33 + @test unit.cost_segments[3].mw[t] ≈ 34 + @test unit.cost_segments[1].cost[t] ≈ 33.75 + @test unit.cost_segments[2].cost[t] ≈ 38.04 + @test unit.cost_segments[3].cost[t] ≈ 44.77853 + end + + @test instance.reserves.spinning == zeros(4) + + @test instance.contingencies[1].lines == [instance.lines[1]] + @test instance.contingencies[1].units == [] + + load = instance.price_sensitive_loads[1] + @test load.name == "ps1" + @test load.bus.name == "b3" + @test load.revenue == [100.0 for t in 1:4] + @test load.demand == [50.0 for t in 1:4] +end + +@testset "read_benchmark sub-hourly" begin + instance = UnitCommitment.read_benchmark("test/case14-sub-hourly") + @test instance.time == 4 + unit = instance.units[1] + @test unit.name == "g1" + @test unit.min_uptime == 2 + @test unit.min_downtime == 2 + @test length(unit.startup_categories) == 3 + @test unit.startup_categories[1].delay == 2 + @test unit.startup_categories[2].delay == 4 + @test unit.startup_categories[3].delay == 6 + @test unit.initial_status == -200 +end diff --git a/test/instance_test.jl b/test/instance_test.jl deleted file mode 100644 index 52e0189..0000000 --- a/test/instance_test.jl +++ /dev/null @@ -1,158 +0,0 @@ -# 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 UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip - -@testset "Instance" begin - @testset "read" begin - instance = UnitCommitment.read_benchmark("test/case14") - - @test length(instance.lines) == 20 - @test length(instance.buses) == 14 - @test length(instance.units) == 6 - @test length(instance.contingencies) == 19 - @test length(instance.price_sensitive_loads) == 1 - @test instance.time == 4 - - @test instance.lines[5].name == "l5" - @test instance.lines[5].source.name == "b2" - @test instance.lines[5].target.name == "b5" - @test instance.lines[5].reactance ≈ 0.17388 - @test instance.lines[5].susceptance ≈ 10.037550333 - @test instance.lines[5].normal_flow_limit == [1e8 for t in 1:4] - @test instance.lines[5].emergency_flow_limit == [1e8 for t in 1:4] - @test instance.lines[5].flow_limit_penalty == [5e3 for t in 1:4] - - @test instance.lines[1].name == "l1" - @test instance.lines[1].source.name == "b1" - @test instance.lines[1].target.name == "b2" - @test instance.lines[1].reactance ≈ 0.059170 - @test instance.lines[1].susceptance ≈ 29.496860773945 - @test instance.lines[1].normal_flow_limit == [300.0 for t in 1:4] - @test instance.lines[1].emergency_flow_limit == [400.0 for t in 1:4] - @test instance.lines[1].flow_limit_penalty == [1e3 for t in 1:4] - - @test instance.buses[9].name == "b9" - @test instance.buses[9].load == [35.36638, 33.25495, 31.67138, 31.14353] - - unit = instance.units[1] - @test unit.name == "g1" - @test unit.bus.name == "b1" - @test unit.ramp_up_limit == 1e6 - @test unit.ramp_down_limit == 1e6 - @test unit.startup_limit == 1e6 - @test unit.shutdown_limit == 1e6 - @test unit.must_run == [false for t in 1:4] - @test unit.min_power_cost == [1400.0 for t in 1:4] - @test unit.min_uptime == 1 - @test unit.min_downtime == 1 - @test unit.provides_spinning_reserves == [true for t in 1:4] - for t in 1:1 - @test unit.cost_segments[1].mw[t] == 10.0 - @test unit.cost_segments[2].mw[t] == 20.0 - @test unit.cost_segments[3].mw[t] == 5.0 - @test unit.cost_segments[1].cost[t] ≈ 20.0 - @test unit.cost_segments[2].cost[t] ≈ 30.0 - @test unit.cost_segments[3].cost[t] ≈ 40.0 - end - @test length(unit.startup_categories) == 3 - @test unit.startup_categories[1].delay == 1 - @test unit.startup_categories[2].delay == 2 - @test unit.startup_categories[3].delay == 3 - @test unit.startup_categories[1].cost == 1000.0 - @test unit.startup_categories[2].cost == 1500.0 - @test unit.startup_categories[3].cost == 2000.0 - - unit = instance.units[2] - @test unit.name == "g2" - @test unit.must_run == [false for t in 1:4] - - unit = instance.units[3] - @test unit.name == "g3" - @test unit.bus.name == "b3" - @test unit.ramp_up_limit == 70.0 - @test unit.ramp_down_limit == 70.0 - @test unit.startup_limit == 70.0 - @test unit.shutdown_limit == 70.0 - @test unit.must_run == [true for t in 1:4] - @test unit.min_power_cost == [0.0 for t in 1:4] - @test unit.min_uptime == 1 - @test unit.min_downtime == 1 - @test unit.provides_spinning_reserves == [true for t in 1:4] - for t in 1:4 - @test unit.cost_segments[1].mw[t] ≈ 33 - @test unit.cost_segments[2].mw[t] ≈ 33 - @test unit.cost_segments[3].mw[t] ≈ 34 - @test unit.cost_segments[1].cost[t] ≈ 33.75 - @test unit.cost_segments[2].cost[t] ≈ 38.04 - @test unit.cost_segments[3].cost[t] ≈ 44.77853 - end - - @test instance.reserves.spinning == zeros(4) - - @test instance.contingencies[1].lines == [instance.lines[1]] - @test instance.contingencies[1].units == [] - - load = instance.price_sensitive_loads[1] - @test load.name == "ps1" - @test load.bus.name == "b3" - @test load.revenue == [100.0 for t in 1:4] - @test load.demand == [50.0 for t in 1:4] - end - - @testset "read sub-hourly" begin - instance = UnitCommitment.read_benchmark("test/case14-sub-hourly") - @test instance.time == 4 - unit = instance.units[1] - @test unit.name == "g1" - @test unit.min_uptime == 2 - @test unit.min_downtime == 2 - @test length(unit.startup_categories) == 3 - @test unit.startup_categories[1].delay == 2 - @test unit.startup_categories[2].delay == 4 - @test unit.startup_categories[3].delay == 6 - @test unit.initial_status == -200 - end - - @testset "slice" begin - instance = UnitCommitment.read_benchmark("test/case14") - modified = UnitCommitment.slice(instance, 1:2) - - # Should update all time-dependent fields - @test modified.time == 2 - @test length(modified.power_balance_penalty) == 2 - @test length(modified.reserves.spinning) == 2 - for u in modified.units - @test length(u.max_power) == 2 - @test length(u.min_power) == 2 - @test length(u.must_run) == 2 - @test length(u.min_power_cost) == 2 - @test length(u.provides_spinning_reserves) == 2 - for s in u.cost_segments - @test length(s.mw) == 2 - @test length(s.cost) == 2 - end - end - for b in modified.buses - @test length(b.load) == 2 - end - for l in modified.lines - @test length(l.normal_flow_limit) == 2 - @test length(l.emergency_flow_limit) == 2 - @test length(l.flow_limit_penalty) == 2 - end - for ps in modified.price_sensitive_loads - @test length(ps.demand) == 2 - @test length(ps.revenue) == 2 - end - - # Should be able to build model without errors - optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0) - model = UnitCommitment.build_model( - instance = modified, - optimizer = optimizer, - variable_names = true, - ) - end -end diff --git a/test/model/build_test.jl b/test/model/build_test.jl new file mode 100644 index 0000000..3273359 --- /dev/null +++ b/test/model/build_test.jl @@ -0,0 +1,37 @@ +# 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 UnitCommitment, LinearAlgebra, Cbc, JuMP + +@testset "build_model" begin + instance = UnitCommitment.read_benchmark("test/case14") + for line in instance.lines, t in 1:4 + line.normal_flow_limit[t] = 10.0 + end + optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0) + model = UnitCommitment.build_model( + instance = instance, + optimizer = optimizer, + variable_names = true, + ) + @test name(model[:is_on]["g1", 1]) == "is_on[g1,1]" + + # Optimize and retrieve solution + UnitCommitment.optimize!(model) + solution = UnitCommitment.solution(model) + + # Write solution to a file + filename = tempname() + UnitCommitment.write(filename, solution) + loaded = JSON.parsefile(filename) + @test length(loaded["Is on"]) == 6 + + # Verify solution + @test UnitCommitment.validate(instance, solution) + + # Reoptimize with fixed solution + UnitCommitment.fix!(model, solution) + UnitCommitment.optimize!(model) + @test UnitCommitment.validate(instance, solution) +end diff --git a/test/model_test.jl b/test/model_test.jl deleted file mode 100644 index 9242555..0000000 --- a/test/model_test.jl +++ /dev/null @@ -1,39 +0,0 @@ -# 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 UnitCommitment, LinearAlgebra, Cbc, JuMP - -@testset "Model" begin - @testset "Run" begin - instance = UnitCommitment.read_benchmark("test/case14") - for line in instance.lines, t in 1:4 - line.normal_flow_limit[t] = 10.0 - end - optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0) - model = UnitCommitment.build_model( - instance = instance, - optimizer = optimizer, - variable_names = true, - ) - @test name(model[:is_on]["g1", 1]) == "is_on[g1,1]" - - # Optimize and retrieve solution - UnitCommitment.optimize!(model) - solution = UnitCommitment.solution(model) - - # Write solution to a file - filename = tempname() - UnitCommitment.write(filename, solution) - loaded = JSON.parsefile(filename) - @test length(loaded["Is on"]) == 6 - - # Verify solution - @test UnitCommitment.validate(instance, solution) - - # Reoptimize with fixed solution - UnitCommitment.fix!(model, solution) - UnitCommitment.optimize!(model) - @test UnitCommitment.validate(instance, solution) - end -end diff --git a/test/runtests.jl b/test/runtests.jl index 672860f..5abbcb5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,11 +8,25 @@ using UnitCommitment UnitCommitment._setup_logger() @testset "UnitCommitment" begin - include("instance_test.jl") - include("model_test.jl") - include("sensitivity_test.jl") - include("screening_test.jl") - include("convert_test.jl") - include("validate_test.jl") - include("initcond_test.jl") + @testset "import" begin + include("import/egret_test.jl") + end + @testset "instance" begin + include("instance/read_test.jl") + end + @testset "model" begin + include("model/build_test.jl") + end + @testset "XavQiuWanThi19" begin + include("solution/methods/XavQiuWanThi19/filter_test.jl") + include("solution/methods/XavQiuWanThi19/find_test.jl") + include("solution/methods/XavQiuWanThi19/sensitivity_test.jl") + end + @testset "transform" begin + include("transform/initcond_test.jl") + include("transform/slice_test.jl") + end + @testset "validation" begin + include("validation/repair_test.jl") + end end diff --git a/test/screening_test.jl b/test/screening_test.jl deleted file mode 100644 index 19e24c4..0000000 --- a/test/screening_test.jl +++ /dev/null @@ -1,115 +0,0 @@ -# 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 UnitCommitment, Test, LinearAlgebra -import UnitCommitment: _Violation, _offer, _query - -@testset "Screening" begin - @testset "_Violation filter" begin - instance = UnitCommitment.read_benchmark("test/case14") - filter = - UnitCommitment._ViolationFilter(max_per_line = 1, max_total = 2) - - _offer( - filter, - _Violation( - time = 1, - monitored_line = instance.lines[1], - outage_line = nothing, - amount = 100.0, - ), - ) - _offer( - filter, - _Violation( - time = 1, - monitored_line = instance.lines[1], - outage_line = instance.lines[1], - amount = 300.0, - ), - ) - _offer( - filter, - _Violation( - time = 1, - monitored_line = instance.lines[1], - outage_line = instance.lines[5], - amount = 500.0, - ), - ) - _offer( - filter, - _Violation( - time = 1, - monitored_line = instance.lines[1], - outage_line = instance.lines[4], - amount = 400.0, - ), - ) - _offer( - filter, - _Violation( - time = 1, - monitored_line = instance.lines[2], - outage_line = instance.lines[1], - amount = 200.0, - ), - ) - _offer( - filter, - _Violation( - time = 1, - monitored_line = instance.lines[2], - outage_line = instance.lines[8], - amount = 100.0, - ), - ) - - actual = _query(filter) - expected = [ - _Violation( - time = 1, - monitored_line = instance.lines[2], - outage_line = instance.lines[1], - amount = 200.0, - ), - _Violation( - time = 1, - monitored_line = instance.lines[1], - outage_line = instance.lines[5], - amount = 500.0, - ), - ] - @test actual == expected - end - - @testset "find_violations" begin - instance = UnitCommitment.read_benchmark("test/case14") - for line in instance.lines, t in 1:instance.time - line.normal_flow_limit[t] = 1.0 - line.emergency_flow_limit[t] = 1.0 - end - isf = UnitCommitment._injection_shift_factors( - lines = instance.lines, - buses = instance.buses, - ) - lodf = UnitCommitment._line_outage_factors( - lines = instance.lines, - buses = instance.buses, - isf = isf, - ) - inj = [1000.0 for b in 1:13, t in 1:instance.time] - overflow = [0.0 for l in instance.lines, t in 1:instance.time] - violations = UnitCommitment._find_violations( - instance = instance, - net_injections = inj, - overflow = overflow, - isf = isf, - lodf = lodf, - max_per_line = 1, - max_per_period = 5, - ) - @test length(violations) == 20 - end -end diff --git a/test/sensitivity_test.jl b/test/sensitivity_test.jl deleted file mode 100644 index 3032a93..0000000 --- a/test/sensitivity_test.jl +++ /dev/null @@ -1,145 +0,0 @@ -# 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 UnitCommitment, Test, LinearAlgebra - -@testset "Sensitivity" begin - @testset "Susceptance matrix" begin - instance = UnitCommitment.read_benchmark("test/case14") - actual = UnitCommitment._susceptance_matrix(instance.lines) - @test size(actual) == (20, 20) - expected = Diagonal([ - 29.5, - 7.83, - 8.82, - 9.9, - 10.04, - 10.2, - 41.45, - 8.35, - 3.14, - 6.93, - 8.77, - 6.82, - 13.4, - 9.91, - 15.87, - 20.65, - 6.46, - 9.09, - 8.73, - 5.02, - ]) - @test round.(actual, digits = 2) == expected - end - - @testset "Reduced incidence matrix" begin - instance = UnitCommitment.read_benchmark("test/case14") - actual = UnitCommitment._reduced_incidence_matrix( - lines = instance.lines, - buses = instance.buses, - ) - @test size(actual) == (20, 13) - @test actual[1, 1] == -1.0 - @test actual[3, 1] == 1.0 - @test actual[4, 1] == 1.0 - @test actual[5, 1] == 1.0 - @test actual[3, 2] == -1.0 - @test actual[6, 2] == 1.0 - @test actual[4, 3] == -1.0 - @test actual[6, 3] == -1.0 - @test actual[7, 3] == 1.0 - @test actual[8, 3] == 1.0 - @test actual[9, 3] == 1.0 - @test actual[2, 4] == -1.0 - @test actual[5, 4] == -1.0 - @test actual[7, 4] == -1.0 - @test actual[10, 4] == 1.0 - @test actual[10, 5] == -1.0 - @test actual[11, 5] == 1.0 - @test actual[12, 5] == 1.0 - @test actual[13, 5] == 1.0 - @test actual[8, 6] == -1.0 - @test actual[14, 6] == 1.0 - @test actual[15, 6] == 1.0 - @test actual[14, 7] == -1.0 - @test actual[9, 8] == -1.0 - @test actual[15, 8] == -1.0 - @test actual[16, 8] == 1.0 - @test actual[17, 8] == 1.0 - @test actual[16, 9] == -1.0 - @test actual[18, 9] == 1.0 - @test actual[11, 10] == -1.0 - @test actual[18, 10] == -1.0 - @test actual[12, 11] == -1.0 - @test actual[19, 11] == 1.0 - @test actual[13, 12] == -1.0 - @test actual[19, 12] == -1.0 - @test actual[20, 12] == 1.0 - @test actual[17, 13] == -1.0 - @test actual[20, 13] == -1.0 - end - - @testset "Injection Shift Factors (ISF)" begin - instance = UnitCommitment.read_benchmark("test/case14") - actual = UnitCommitment._injection_shift_factors( - lines = instance.lines, - buses = instance.buses, - ) - @test size(actual) == (20, 13) - @test round.(actual, digits = 2) == [ - -0.84 -0.75 -0.67 -0.61 -0.63 -0.66 -0.66 -0.65 -0.65 -0.64 -0.63 -0.63 -0.64 - -0.16 -0.25 -0.33 -0.39 -0.37 -0.34 -0.34 -0.35 -0.35 -0.36 -0.37 -0.37 -0.36 - 0.03 -0.53 -0.15 -0.1 -0.12 -0.14 -0.14 -0.14 -0.13 -0.13 -0.12 -0.12 -0.13 - 0.06 -0.14 -0.32 -0.22 -0.25 -0.3 -0.3 -0.29 -0.28 -0.27 -0.25 -0.26 -0.27 - 0.08 -0.07 -0.2 -0.29 -0.26 -0.22 -0.22 -0.22 -0.23 -0.25 -0.26 -0.26 -0.24 - 0.03 0.47 -0.15 -0.1 -0.12 -0.14 -0.14 -0.14 -0.13 -0.13 -0.12 -0.12 -0.13 - 0.08 0.31 0.5 -0.3 -0.03 0.36 0.36 0.28 0.23 0.1 -0.0 0.02 0.17 - 0.0 0.01 0.02 -0.01 -0.22 -0.63 -0.63 -0.45 -0.41 -0.32 -0.24 -0.25 -0.36 - 0.0 0.01 0.01 -0.01 -0.12 -0.17 -0.17 -0.26 -0.24 -0.18 -0.14 -0.14 -0.21 - -0.0 -0.02 -0.03 0.02 -0.66 -0.2 -0.2 -0.29 -0.36 -0.5 -0.63 -0.61 -0.43 - -0.0 -0.01 -0.02 0.01 0.21 -0.12 -0.12 -0.17 -0.28 -0.53 0.18 0.15 -0.03 - -0.0 -0.0 -0.0 0.0 0.03 -0.02 -0.02 -0.03 -0.02 0.01 -0.52 -0.17 -0.09 - -0.0 -0.01 -0.01 0.01 0.11 -0.06 -0.06 -0.09 -0.05 0.02 -0.28 -0.59 -0.31 - -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -1.0 -0.0 -0.0 -0.0 -0.0 -0.0 0.0 - 0.0 0.01 0.02 -0.01 -0.22 0.37 0.37 -0.45 -0.41 -0.32 -0.24 -0.25 -0.36 - 0.0 0.01 0.02 -0.01 -0.21 0.12 0.12 0.17 -0.72 -0.47 -0.18 -0.15 0.03 - 0.0 0.01 0.01 -0.01 -0.14 0.08 0.08 0.12 0.07 -0.03 -0.2 -0.24 -0.6 - 0.0 0.01 0.02 -0.01 -0.21 0.12 0.12 0.17 0.28 -0.47 -0.18 -0.15 0.03 - -0.0 -0.0 -0.0 0.0 0.03 -0.02 -0.02 -0.03 -0.02 0.01 0.48 -0.17 -0.09 - -0.0 -0.01 -0.01 0.01 0.14 -0.08 -0.08 -0.12 -0.07 0.03 0.2 0.24 -0.4 - ] - end - - @testset "Line Outage Distribution Factors (LODF)" begin - instance = UnitCommitment.read_benchmark("test/case14") - isf_before = UnitCommitment._injection_shift_factors( - lines = instance.lines, - buses = instance.buses, - ) - lodf = UnitCommitment._line_outage_factors( - lines = instance.lines, - buses = instance.buses, - isf = isf_before, - ) - for contingency in instance.contingencies - for lc in contingency.lines - prev_susceptance = lc.susceptance - lc.susceptance = 0.0 - isf_after = UnitCommitment._injection_shift_factors( - lines = instance.lines, - buses = instance.buses, - ) - lc.susceptance = prev_susceptance - for lm in instance.lines - expected = isf_after[lm.offset, :] - actual = - isf_before[lm.offset, :] + - lodf[lm.offset, lc.offset] * isf_before[lc.offset, :] - @test norm(expected - actual) < 1e-6 - end - end - end - end -end diff --git a/test/solution/methods/XavQiuWanThi19/filter_test.jl b/test/solution/methods/XavQiuWanThi19/filter_test.jl new file mode 100644 index 0000000..961dc4b --- /dev/null +++ b/test/solution/methods/XavQiuWanThi19/filter_test.jl @@ -0,0 +1,83 @@ +# 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 UnitCommitment, Test, LinearAlgebra +import UnitCommitment: _Violation, _offer, _query + +@testset "_ViolationFilter" begin + instance = UnitCommitment.read_benchmark("test/case14") + filter = UnitCommitment._ViolationFilter(max_per_line = 1, max_total = 2) + + _offer( + filter, + _Violation( + time = 1, + monitored_line = instance.lines[1], + outage_line = nothing, + amount = 100.0, + ), + ) + _offer( + filter, + _Violation( + time = 1, + monitored_line = instance.lines[1], + outage_line = instance.lines[1], + amount = 300.0, + ), + ) + _offer( + filter, + _Violation( + time = 1, + monitored_line = instance.lines[1], + outage_line = instance.lines[5], + amount = 500.0, + ), + ) + _offer( + filter, + _Violation( + time = 1, + monitored_line = instance.lines[1], + outage_line = instance.lines[4], + amount = 400.0, + ), + ) + _offer( + filter, + _Violation( + time = 1, + monitored_line = instance.lines[2], + outage_line = instance.lines[1], + amount = 200.0, + ), + ) + _offer( + filter, + _Violation( + time = 1, + monitored_line = instance.lines[2], + outage_line = instance.lines[8], + amount = 100.0, + ), + ) + + actual = _query(filter) + expected = [ + _Violation( + time = 1, + monitored_line = instance.lines[2], + outage_line = instance.lines[1], + amount = 200.0, + ), + _Violation( + time = 1, + monitored_line = instance.lines[1], + outage_line = instance.lines[5], + amount = 500.0, + ), + ] + @test actual == expected +end diff --git a/test/solution/methods/XavQiuWanThi19/find_test.jl b/test/solution/methods/XavQiuWanThi19/find_test.jl new file mode 100644 index 0000000..ddd02c1 --- /dev/null +++ b/test/solution/methods/XavQiuWanThi19/find_test.jl @@ -0,0 +1,35 @@ +# 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 UnitCommitment, Test, LinearAlgebra +import UnitCommitment: _Violation, _offer, _query + +@testset "find_violations" begin + instance = UnitCommitment.read_benchmark("test/case14") + for line in instance.lines, t in 1:instance.time + line.normal_flow_limit[t] = 1.0 + line.emergency_flow_limit[t] = 1.0 + end + isf = UnitCommitment._injection_shift_factors( + lines = instance.lines, + buses = instance.buses, + ) + lodf = UnitCommitment._line_outage_factors( + lines = instance.lines, + buses = instance.buses, + isf = isf, + ) + inj = [1000.0 for b in 1:13, t in 1:instance.time] + overflow = [0.0 for l in instance.lines, t in 1:instance.time] + violations = UnitCommitment._find_violations( + instance = instance, + net_injections = inj, + overflow = overflow, + isf = isf, + lodf = lodf, + max_per_line = 1, + max_per_period = 5, + ) + @test length(violations) == 20 +end diff --git a/test/solution/methods/XavQiuWanThi19/sensitivity_test.jl b/test/solution/methods/XavQiuWanThi19/sensitivity_test.jl new file mode 100644 index 0000000..fda4272 --- /dev/null +++ b/test/solution/methods/XavQiuWanThi19/sensitivity_test.jl @@ -0,0 +1,143 @@ +# 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 UnitCommitment, Test, LinearAlgebra + +@testset "_susceptance_matrix" begin + instance = UnitCommitment.read_benchmark("test/case14") + actual = UnitCommitment._susceptance_matrix(instance.lines) + @test size(actual) == (20, 20) + expected = Diagonal([ + 29.5, + 7.83, + 8.82, + 9.9, + 10.04, + 10.2, + 41.45, + 8.35, + 3.14, + 6.93, + 8.77, + 6.82, + 13.4, + 9.91, + 15.87, + 20.65, + 6.46, + 9.09, + 8.73, + 5.02, + ]) + @test round.(actual, digits = 2) == expected +end + +@testset "_reduced_incidence_matrix" begin + instance = UnitCommitment.read_benchmark("test/case14") + actual = UnitCommitment._reduced_incidence_matrix( + lines = instance.lines, + buses = instance.buses, + ) + @test size(actual) == (20, 13) + @test actual[1, 1] == -1.0 + @test actual[3, 1] == 1.0 + @test actual[4, 1] == 1.0 + @test actual[5, 1] == 1.0 + @test actual[3, 2] == -1.0 + @test actual[6, 2] == 1.0 + @test actual[4, 3] == -1.0 + @test actual[6, 3] == -1.0 + @test actual[7, 3] == 1.0 + @test actual[8, 3] == 1.0 + @test actual[9, 3] == 1.0 + @test actual[2, 4] == -1.0 + @test actual[5, 4] == -1.0 + @test actual[7, 4] == -1.0 + @test actual[10, 4] == 1.0 + @test actual[10, 5] == -1.0 + @test actual[11, 5] == 1.0 + @test actual[12, 5] == 1.0 + @test actual[13, 5] == 1.0 + @test actual[8, 6] == -1.0 + @test actual[14, 6] == 1.0 + @test actual[15, 6] == 1.0 + @test actual[14, 7] == -1.0 + @test actual[9, 8] == -1.0 + @test actual[15, 8] == -1.0 + @test actual[16, 8] == 1.0 + @test actual[17, 8] == 1.0 + @test actual[16, 9] == -1.0 + @test actual[18, 9] == 1.0 + @test actual[11, 10] == -1.0 + @test actual[18, 10] == -1.0 + @test actual[12, 11] == -1.0 + @test actual[19, 11] == 1.0 + @test actual[13, 12] == -1.0 + @test actual[19, 12] == -1.0 + @test actual[20, 12] == 1.0 + @test actual[17, 13] == -1.0 + @test actual[20, 13] == -1.0 +end + +@testset "_injection_shift_factors" begin + instance = UnitCommitment.read_benchmark("test/case14") + actual = UnitCommitment._injection_shift_factors( + lines = instance.lines, + buses = instance.buses, + ) + @test size(actual) == (20, 13) + @test round.(actual, digits = 2) == [ + -0.84 -0.75 -0.67 -0.61 -0.63 -0.66 -0.66 -0.65 -0.65 -0.64 -0.63 -0.63 -0.64 + -0.16 -0.25 -0.33 -0.39 -0.37 -0.34 -0.34 -0.35 -0.35 -0.36 -0.37 -0.37 -0.36 + 0.03 -0.53 -0.15 -0.1 -0.12 -0.14 -0.14 -0.14 -0.13 -0.13 -0.12 -0.12 -0.13 + 0.06 -0.14 -0.32 -0.22 -0.25 -0.3 -0.3 -0.29 -0.28 -0.27 -0.25 -0.26 -0.27 + 0.08 -0.07 -0.2 -0.29 -0.26 -0.22 -0.22 -0.22 -0.23 -0.25 -0.26 -0.26 -0.24 + 0.03 0.47 -0.15 -0.1 -0.12 -0.14 -0.14 -0.14 -0.13 -0.13 -0.12 -0.12 -0.13 + 0.08 0.31 0.5 -0.3 -0.03 0.36 0.36 0.28 0.23 0.1 -0.0 0.02 0.17 + 0.0 0.01 0.02 -0.01 -0.22 -0.63 -0.63 -0.45 -0.41 -0.32 -0.24 -0.25 -0.36 + 0.0 0.01 0.01 -0.01 -0.12 -0.17 -0.17 -0.26 -0.24 -0.18 -0.14 -0.14 -0.21 + -0.0 -0.02 -0.03 0.02 -0.66 -0.2 -0.2 -0.29 -0.36 -0.5 -0.63 -0.61 -0.43 + -0.0 -0.01 -0.02 0.01 0.21 -0.12 -0.12 -0.17 -0.28 -0.53 0.18 0.15 -0.03 + -0.0 -0.0 -0.0 0.0 0.03 -0.02 -0.02 -0.03 -0.02 0.01 -0.52 -0.17 -0.09 + -0.0 -0.01 -0.01 0.01 0.11 -0.06 -0.06 -0.09 -0.05 0.02 -0.28 -0.59 -0.31 + -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -1.0 -0.0 -0.0 -0.0 -0.0 -0.0 0.0 + 0.0 0.01 0.02 -0.01 -0.22 0.37 0.37 -0.45 -0.41 -0.32 -0.24 -0.25 -0.36 + 0.0 0.01 0.02 -0.01 -0.21 0.12 0.12 0.17 -0.72 -0.47 -0.18 -0.15 0.03 + 0.0 0.01 0.01 -0.01 -0.14 0.08 0.08 0.12 0.07 -0.03 -0.2 -0.24 -0.6 + 0.0 0.01 0.02 -0.01 -0.21 0.12 0.12 0.17 0.28 -0.47 -0.18 -0.15 0.03 + -0.0 -0.0 -0.0 0.0 0.03 -0.02 -0.02 -0.03 -0.02 0.01 0.48 -0.17 -0.09 + -0.0 -0.01 -0.01 0.01 0.14 -0.08 -0.08 -0.12 -0.07 0.03 0.2 0.24 -0.4 + ] +end + +@testset "_line_outage_factors" begin + instance = UnitCommitment.read_benchmark("test/case14") + isf_before = UnitCommitment._injection_shift_factors( + lines = instance.lines, + buses = instance.buses, + ) + lodf = UnitCommitment._line_outage_factors( + lines = instance.lines, + buses = instance.buses, + isf = isf_before, + ) + for contingency in instance.contingencies + for lc in contingency.lines + prev_susceptance = lc.susceptance + lc.susceptance = 0.0 + isf_after = UnitCommitment._injection_shift_factors( + lines = instance.lines, + buses = instance.buses, + ) + lc.susceptance = prev_susceptance + for lm in instance.lines + expected = isf_after[lm.offset, :] + actual = + isf_before[lm.offset, :] + + lodf[lm.offset, lc.offset] * isf_before[lc.offset, :] + @test norm(expected - actual) < 1e-6 + end + end + end +end diff --git a/test/initcond_test.jl b/test/transform/initcond_test.jl similarity index 95% rename from test/initcond_test.jl rename to test/transform/initcond_test.jl index 4cb127c..8de438b 100644 --- a/test/initcond_test.jl +++ b/test/transform/initcond_test.jl @@ -4,7 +4,7 @@ using UnitCommitment, Cbc, JuMP -@testset "Initial conditions" begin +@testset "generate_initial_conditions!" begin # Load instance instance = UnitCommitment.read("$(pwd())/fixtures/case118-initcond.json.gz") optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0) diff --git a/test/transform/slice_test.jl b/test/transform/slice_test.jl new file mode 100644 index 0000000..f330bda --- /dev/null +++ b/test/transform/slice_test.jl @@ -0,0 +1,46 @@ +# 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 UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip + +@testset "slice" begin + instance = UnitCommitment.read_benchmark("test/case14") + modified = UnitCommitment.slice(instance, 1:2) + + # Should update all time-dependent fields + @test modified.time == 2 + @test length(modified.power_balance_penalty) == 2 + @test length(modified.reserves.spinning) == 2 + for u in modified.units + @test length(u.max_power) == 2 + @test length(u.min_power) == 2 + @test length(u.must_run) == 2 + @test length(u.min_power_cost) == 2 + @test length(u.provides_spinning_reserves) == 2 + for s in u.cost_segments + @test length(s.mw) == 2 + @test length(s.cost) == 2 + end + end + for b in modified.buses + @test length(b.load) == 2 + end + for l in modified.lines + @test length(l.normal_flow_limit) == 2 + @test length(l.emergency_flow_limit) == 2 + @test length(l.flow_limit_penalty) == 2 + end + for ps in modified.price_sensitive_loads + @test length(ps.demand) == 2 + @test length(ps.revenue) == 2 + end + + # Should be able to build model without errors + optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0) + model = UnitCommitment.build_model( + instance = modified, + optimizer = optimizer, + variable_names = true, + ) +end diff --git a/test/validate_test.jl b/test/validate_test.jl deleted file mode 100644 index c1f047e..0000000 --- a/test/validate_test.jl +++ /dev/null @@ -1,43 +0,0 @@ -# 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 UnitCommitment, JSON, GZip, DataStructures - -function parse_case14() - return JSON.parse( - GZip.gzopen("../instances/test/case14.json.gz"), - dicttype = () -> DefaultOrderedDict(nothing), - ) -end - -@testset "Validation" begin - @testset "repair!" begin - @testset "Cost curve should be convex" begin - json = parse_case14() - json["Generators"]["g1"]["Production cost curve (MW)"] = - [100, 150, 200] - json["Generators"]["g1"]["Production cost curve (\$)"] = - [10, 25, 30] - instance = UnitCommitment._from_json(json, repair = false) - @test UnitCommitment.repair!(instance) == 4 - end - - @testset "Startup limit must be greater than Pmin" begin - json = parse_case14() - json["Generators"]["g1"]["Production cost curve (MW)"] = [100, 150] - json["Generators"]["g1"]["Production cost curve (\$)"] = [100, 150] - json["Generators"]["g1"]["Startup limit (MW)"] = 80 - instance = UnitCommitment._from_json(json, repair = false) - @test UnitCommitment.repair!(instance) == 1 - end - - @testset "Startup costs and delays must be increasing" begin - json = parse_case14() - json["Generators"]["g1"]["Startup costs (\$)"] = [300, 200, 100] - json["Generators"]["g1"]["Startup delays (h)"] = [8, 4, 2] - instance = UnitCommitment._from_json(json, repair = false) - @test UnitCommitment.repair!(instance) == 4 - end - end -end diff --git a/test/validation/repair_test.jl b/test/validation/repair_test.jl new file mode 100644 index 0000000..f53e087 --- /dev/null +++ b/test/validation/repair_test.jl @@ -0,0 +1,39 @@ +# 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 UnitCommitment, JSON, GZip, DataStructures + +function parse_case14() + return JSON.parse( + GZip.gzopen("../instances/test/case14.json.gz"), + dicttype = () -> DefaultOrderedDict(nothing), + ) +end + +@testset "repair!" begin + @testset "Cost curve should be convex" begin + json = parse_case14() + json["Generators"]["g1"]["Production cost curve (MW)"] = [100, 150, 200] + json["Generators"]["g1"]["Production cost curve (\$)"] = [10, 25, 30] + instance = UnitCommitment._from_json(json, repair = false) + @test UnitCommitment.repair!(instance) == 4 + end + + @testset "Startup limit must be greater than Pmin" begin + json = parse_case14() + json["Generators"]["g1"]["Production cost curve (MW)"] = [100, 150] + json["Generators"]["g1"]["Production cost curve (\$)"] = [100, 150] + json["Generators"]["g1"]["Startup limit (MW)"] = 80 + instance = UnitCommitment._from_json(json, repair = false) + @test UnitCommitment.repair!(instance) == 1 + end + + @testset "Startup costs and delays must be increasing" begin + json = parse_case14() + json["Generators"]["g1"]["Startup costs (\$)"] = [300, 200, 100] + json["Generators"]["g1"]["Startup delays (h)"] = [8, 4, 2] + instance = UnitCommitment._from_json(json, repair = false) + @test UnitCommitment.repair!(instance) == 4 + end +end