Compare commits

...

2 Commits

Author SHA1 Message Date
6e30645084 Allow v0.3 to read v0.2 instance files 2022-07-12 11:57:55 -05:00
678e6aa2f5 Update docs 2022-07-11 12:16:06 -05:00
29 changed files with 123 additions and 62 deletions

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.
VERSION := 0.2
VERSION := 0.3
clean:
rm -rfv build Manifest.toml test/Manifest.toml deps/formatter/build deps/formatter/Manifest.toml

View File

@@ -1,7 +1,7 @@
project = "UnitCommitment.jl"
copyright = "2020-2021, UChicago Argonne, LLC"
copyright = "2020-2022, UChicago Argonne, LLC"
author = ""
release = "0.2"
release = "0.3"
extensions = ["myst_parser"]
templates_path = ["_templates"]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
@@ -10,7 +10,7 @@ html_static_path = ["_static"]
html_css_files = ["custom.css"]
html_theme_options = {
"repository_url": "https://github.com/ANL-CEEESA/UnitCommitment.jl/",
"use_repository_button": True,
"use_repository_button": False,
"extra_navbar": "",
}
html_title = f"UnitCommitment.jl<br/><small>{release}</small>"

View File

@@ -24,7 +24,9 @@ Instances are specified by JSON files containing the following main sections:
* Reserves
* Contingencies
Each section is described in detail below. For a complete example, see [case14](https://github.com/ANL-CEEESA/UnitCommitment.jl/tree/dev/instances/matpower/case14).
Each section is described in detail below. See [case118/2017-01-01.json.gz][example] for a complete example.
[example]: https://axavier.org/UnitCommitment.jl/0.3/instances/matpower/case118/2017-01-01.json.gz
### Parameters
@@ -303,3 +305,4 @@ Current limitations
* Only N-1 transmission contingencies are supported. Generator contingencies are not currently supported.
* Time-varying minimum production amounts are not currently compatible with ramp/startup/shutdown limits.
* Flexible ramping products can only be acquired under the `WanHob2016` formulation, which does not support spinning reserves.

View File

@@ -21,6 +21,7 @@
### Authors
* **Alinson S. Xavier** (Argonne National Laboratory)
* **Aleksandr M. Kazachkov** (University of Florida)
* **Ogün Yurdakul** (Technische Universität Berlin)
* **Feng Qiu** (Argonne National Laboratory)
### Acknowledgments
@@ -35,7 +36,7 @@
If you use UnitCommitment.jl in your research (instances, models or algorithms), we kindly request that you cite the package as follows:
* **Alinson S. Xavier, Aleksandr M. Kazachkov, Feng Qiu**, "UnitCommitment.jl: A Julia/JuMP Optimization Package for Security-Constrained Unit Commitment". Zenodo (2020). [DOI: 10.5281/zenodo.4269874](https://doi.org/10.5281/zenodo.4269874).
* **Alinson S. Xavier, Aleksandr M. Kazachkov, Ogün Yurdakul, Feng Qiu**, "UnitCommitment.jl: A Julia/JuMP Optimization Package for Security-Constrained Unit Commitment". Zenodo (2020). [DOI: 10.5281/zenodo.4269874](https://doi.org/10.5281/zenodo.4269874).
If you use the instances, we additionally request that you cite the original sources, as described in the [instances page](instances.md).

View File

@@ -9,7 +9,7 @@ suffix: .
Instances
=========
UnitCommitment.jl provides a large collection of benchmark instances collected from the literature and converted to a [common data format](format.md). In some cases, as indicated below, the original instances have been extended, with realistic parameters, using data-driven methods. If you use these instances in your research, we request that you cite UnitCommitment.jl, as well as the original sources, as listed below. Benchmark instances can be loaded with `UnitCommitment.read_benchmark(name)`, as explained in the [usage section](usage.md).
UnitCommitment.jl provides a large collection of benchmark instances collected from the literature and converted to a [common data format](format.md). In some cases, as indicated below, the original instances have been extended, with realistic parameters, using data-driven methods. If you use these instances in your research, we request that you cite UnitCommitment.jl, as well as the original sources, as listed below. Benchmark instances can be loaded with `UnitCommitment.read_benchmark(name)`, as explained in the [usage section](usage.md). Instance files can also be [directly downloaded from our website](https://axavier.org/UnitCommitment.jl/0.3/instances/).
```{warning}
The instances included in UC.jl are still under development and may change in the future. If you use these instances in your research, for reproducibility, you should specify what version of UC.jl they came from.
@@ -33,7 +33,7 @@ Because most MATPOWER test cases were originally designed for power flow studies
* **Contingencies** were set to include all N-1 transmission line contingencies that do not generate islands or isolated buses. More specifically, there is one contingency for each transmission line, as long as that transmission line is not a bridge in the network graph.
For each MATPOWER test case, UC.jl provides two variations (`2017-02-01` and `2017-08-01`) corresponding respectively to a winter and to a summer test case.
For each MATPOWER test case, UC.jl provides 364 variations (`2017-01-01` to `2017-12-30`) corresponding different days of the year.
### MATPOWER/UW-PSTCA
@@ -41,11 +41,11 @@ A variety of smaller IEEE test cases, [compiled by University of Washington](htt
| Name | Buses | Generators | Lines | Contingencies | References |
|------|-------|------------|-------|---------------|--------|
| `matpower/case14/2017-02-01` | 14 | 5 | 20 | 19 | [MTPWR, PSTCA]
| `matpower/case30/2017-02-01` | 30 | 6 | 41 | 38 | [MTPWR, PSTCA]
| `matpower/case57/2017-02-01` | 57 | 7 | 80 | 79 | [MTPWR, PSTCA]
| `matpower/case118/2017-02-01` | 118 | 54 | 186 | 177 | [MTPWR, PSTCA]
| `matpower/case300/2017-02-01` | 300 | 69 | 411 | 320 | [MTPWR, PSTCA]
| `matpower/case14/2017-01-01` | 14 | 5 | 20 | 19 | [MTPWR, PSTCA]
| `matpower/case30/2017-01-01` | 30 | 6 | 41 | 38 | [MTPWR, PSTCA]
| `matpower/case57/2017-01-01` | 57 | 7 | 80 | 79 | [MTPWR, PSTCA]
| `matpower/case118/2017-01-01` | 118 | 54 | 186 | 177 | [MTPWR, PSTCA]
| `matpower/case300/2017-01-01` | 300 | 69 | 411 | 320 | [MTPWR, PSTCA]
### MATPOWER/Polish
@@ -54,14 +54,14 @@ Test cases based on the Polish 400, 220 and 110 kV networks, originally provided
| Name | Buses | Generators | Lines | Contingencies | References |
|------|-------|------------|-------|---------------|--------|
| `matpower/case2383wp/2017-02-01` | 2383 | 323 | 2896 | 2240 | [MTPWR]
| `matpower/case2736sp/2017-02-01` | 2736 | 289 | 3504 | 3159 | [MTPWR]
| `matpower/case2737sop/2017-02-01` | 2737 | 267 | 3506 | 3161 | [MTPWR]
| `matpower/case2746wop/2017-02-01` | 2746 | 443 | 3514 | 3155 | [MTPWR]
| `matpower/case2746wp/2017-02-01` | 2746 | 457 | 3514 | 3156 | [MTPWR]
| `matpower/case3012wp/2017-02-01` | 3012 | 496 | 3572 | 2854 | [MTPWR]
| `matpower/case3120sp/2017-02-01` | 3120 | 483 | 3693 | 2950 | [MTPWR]
| `matpower/case3375wp/2017-02-01` | 3374 | 590 | 4161 | 3245 | [MTPWR]
| `matpower/case2383wp/2017-01-01` | 2383 | 323 | 2896 | 2240 | [MTPWR]
| `matpower/case2736sp/2017-01-01` | 2736 | 289 | 3504 | 3159 | [MTPWR]
| `matpower/case2737sop/2017-01-01` | 2737 | 267 | 3506 | 3161 | [MTPWR]
| `matpower/case2746wop/2017-01-01` | 2746 | 443 | 3514 | 3155 | [MTPWR]
| `matpower/case2746wp/2017-01-01` | 2746 | 457 | 3514 | 3156 | [MTPWR]
| `matpower/case3012wp/2017-01-01` | 3012 | 496 | 3572 | 2854 | [MTPWR]
| `matpower/case3120sp/2017-01-01` | 3120 | 483 | 3693 | 2950 | [MTPWR]
| `matpower/case3375wp/2017-01-01` | 3374 | 590 | 4161 | 3245 | [MTPWR]
### MATPOWER/PEGASE
@@ -69,11 +69,11 @@ Test cases from the [Pan European Grid Advanced Simulation and State Estimation
| Name | Buses | Generators | Lines | Contingencies | References |
|------|-------|------------|-------|---------------|--------|
| `matpower/case89pegase/2017-02-01` | 89 | 12 | 210 | 192 | [JoFlMa16, FlPaCa13, MTPWR]
| `matpower/case1354pegase/2017-02-01` | 1354 | 260 | 1991 | 1288 | [JoFlMa16, FlPaCa13, MTPWR]
| `matpower/case2869pegase/2017-02-01` | 2869 | 510 | 4582 | 3579 | [JoFlMa16, FlPaCa13, MTPWR]
| `matpower/case9241pegase/2017-02-01` | 9241 | 1445 | 16049 | 13932 | [JoFlMa16, FlPaCa13, MTPWR]
| `matpower/case13659pegase/2017-02-01` | 13659 | 4092 | 20467 | 13932 | [JoFlMa16, FlPaCa13, MTPWR]
| `matpower/case89pegase/2017-01-01` | 89 | 12 | 210 | 192 | [JoFlMa16, FlPaCa13, MTPWR]
| `matpower/case1354pegase/2017-01-01` | 1354 | 260 | 1991 | 1288 | [JoFlMa16, FlPaCa13, MTPWR]
| `matpower/case2869pegase/2017-01-01` | 2869 | 510 | 4582 | 3579 | [JoFlMa16, FlPaCa13, MTPWR]
| `matpower/case9241pegase/2017-01-01` | 9241 | 1445 | 16049 | 13932 | [JoFlMa16, FlPaCa13, MTPWR]
| `matpower/case13659pegase/2017-01-01` | 13659 | 4092 | 20467 | 13932 | [JoFlMa16, FlPaCa13, MTPWR]
### MATPOWER/RTE
@@ -81,14 +81,14 @@ Test cases from the R&D Division at [Reseau de Transport d'Electricite](https://
| Name | Buses | Generators | Lines | Contingencies | References |
|------|-------|------------|-------|---------------|--------|
| `matpower/case1888rte/2017-02-01` | 1888 | 296 | 2531 | 1484 | [MTPWR, JoFlMa16]
| `matpower/case1951rte/2017-02-01` | 1951 | 390 | 2596 | 1497 | [MTPWR, JoFlMa16]
| `matpower/case2848rte/2017-02-01` | 2848 | 544 | 3776 | 2242 | [MTPWR, JoFlMa16]
| `matpower/case2868rte/2017-02-01` | 2868 | 596 | 3808 | 2260 | [MTPWR, JoFlMa16]
| `matpower/case6468rte/2017-02-01` | 6468 | 1262 | 9000 | 6094 | [MTPWR, JoFlMa16]
| `matpower/case6470rte/2017-02-01` | 6470 | 1306 | 9005 | 6085 | [MTPWR, JoFlMa16]
| `matpower/case6495rte/2017-02-01` | 6495 | 1352 | 9019 | 6060 | [MTPWR, JoFlMa16]
| `matpower/case6515rte/2017-02-01` | 6515 | 1368 | 9037 | 6063 | [MTPWR, JoFlMa16]
| `matpower/case1888rte/2017-01-01` | 1888 | 296 | 2531 | 1484 | [MTPWR, JoFlMa16]
| `matpower/case1951rte/2017-01-01` | 1951 | 390 | 2596 | 1497 | [MTPWR, JoFlMa16]
| `matpower/case2848rte/2017-01-01` | 2848 | 544 | 3776 | 2242 | [MTPWR, JoFlMa16]
| `matpower/case2868rte/2017-01-01` | 2868 | 596 | 3808 | 2260 | [MTPWR, JoFlMa16]
| `matpower/case6468rte/2017-01-01` | 6468 | 1262 | 9000 | 6094 | [MTPWR, JoFlMa16]
| `matpower/case6470rte/2017-01-01` | 6470 | 1306 | 9005 | 6085 | [MTPWR, JoFlMa16]
| `matpower/case6495rte/2017-01-01` | 6495 | 1352 | 9019 | 6060 | [MTPWR, JoFlMa16]
| `matpower/case6515rte/2017-01-01` | 6515 | 1368 | 9037 | 6063 | [MTPWR, JoFlMa16]
PGLIB-UC Instances
@@ -288,7 +288,7 @@ Tejada19
References
----------
* [UCJL] **Alinson S. Xavier, Aleksandr M. Kazachkov, Feng Qiu.** "UnitCommitment.jl: A Julia/JuMP Optimization Package for Security-Constrained Unit Commitment". Zenodo (2020). [DOI: 10.5281/zenodo.4269874](https://doi.org/10.5281/zenodo.4269874)
* [UCJL] **Alinson S. Xavier, Aleksandr M. Kazachkov, Ogün Yurdakul, Feng Qiu.** "UnitCommitment.jl: A Julia/JuMP Optimization Package for Security-Constrained Unit Commitment". Zenodo (2020). [DOI: 10.5281/zenodo.4269874](https://doi.org/10.5281/zenodo.4269874)
* [KnOsWa20] **Bernard Knueven, James Ostrowski and Jean-Paul Watson.** "On Mixed-Integer Programming Formulations for the Unit Commitment Problem". INFORMS Journal on Computing (2020). [DOI: 10.1287/ijoc.2019.0944](https://doi.org/10.1287/ijoc.2019.0944)

4
docs/requirements.txt Normal file
View File

@@ -0,0 +1,4 @@
Sphinx==3.5.4
sphinx-book-theme==0.1.0
myst-parser==0.14.0
Jinja2==3.0.2

View File

@@ -12,10 +12,10 @@ Usage
Installation
------------
UnitCommitment.jl was tested and developed with [Julia 1.6](https://julialang.org/). To install Julia, please follow the [installation guide on the official Julia website](https://julialang.org/downloads/platform.html). To install UnitCommitment.jl, run the Julia interpreter, type `]` to open the package manager, then type:
UnitCommitment.jl was tested and developed with [Julia 1.7](https://julialang.org/). To install Julia, please follow the [installation guide on the official Julia website](https://julialang.org/downloads/). To install UnitCommitment.jl, run the Julia interpreter, type `]` to open the package manager, then type:
```text
pkg> add UnitCommitment@0.2
pkg> add UnitCommitment@0.3
```
To test that the package has been correctly installed, run:

Binary file not shown.

View File

@@ -20,6 +20,7 @@ include("model/formulations/WanHob2016/structs.jl")
include("import/egret.jl")
include("instance/read.jl")
include("instance/migrate.jl")
include("model/build.jl")
include("model/formulations/ArrCon2000/ramp.jl")
include("model/formulations/base/bus.jl")

38
src/instance/migrate.jl Normal file
View File

@@ -0,0 +1,38 @@
# 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 DataStructures
using JSON
function _migrate(json)
version = json["Parameters"]["Version"]
if version === nothing
error(
"The provided input file cannot be loaded because it does not " *
"specify what version of UnitCommitment.jl it was written for. " *
"Please modify the \"Parameters\" section of the file and include " *
"a \"Version\" entry. For example: {\"Parameters\":{\"Version\":\"0.3\"}}",
)
end
version = VersionNumber(version)
version >= v"0.3" || _migrate_to_v03(json)
return
end
function _migrate_to_v03(json)
# Migrate reserves
if json["Reserves"] !== nothing &&
json["Reserves"]["Spinning (MW)"] !== nothing
amount = json["Reserves"]["Spinning (MW)"]
json["Reserves"] = DefaultOrderedDict(nothing)
json["Reserves"]["r1"] = DefaultOrderedDict(nothing)
json["Reserves"]["r1"]["Type"] = "spinning"
json["Reserves"]["r1"]["Amount (MW)"] = amount
for (gen_name, gen) in json["Generators"]
if gen["Provides spinning reserves?"] == true
gen["Reserve eligibility"] = ["r1"]
end
end
end
end

View File

@@ -80,6 +80,7 @@ function _read_json(path::String)::OrderedDict
end
function _from_json(json; repair = true)
_migrate(json)
units = Unit[]
buses = Bus[]
contingencies = Contingency[]

Binary file not shown.

BIN
test/fixtures/case14-flex.json.gz vendored Normal file

Binary file not shown.

BIN
test/fixtures/case14-sub-hourly.json.gz vendored Normal file

Binary file not shown.

BIN
test/fixtures/case14.json.gz vendored Normal file

Binary file not shown.

BIN
test/fixtures/ucjl-0.2.json.gz vendored Normal file

Binary file not shown.

BIN
test/fixtures/ucjl-0.3.json.gz vendored Normal file

Binary file not shown.

View File

@@ -4,12 +4,9 @@
using UnitCommitment
basedir = @__DIR__
@testset "read_egret_solution" begin
solution = UnitCommitment.read_egret_solution(
"$basedir/../fixtures/egret_output.json.gz",
)
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])

View File

@@ -0,0 +1,18 @@
# 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 v0.2" begin
instance = UnitCommitment.read("$FIXTURES/ucjl-0.2.json.gz")
@test length(instance.reserves_by_name["r1"].amount) == 4
@test instance.units_by_name["g2"].reserves[1].name == "r1"
end
@testset "read v0.3" begin
instance = UnitCommitment.read("$FIXTURES/ucjl-0.3.json.gz")
@test length(instance.units) == 6
@test length(instance.buses) == 14
@test length(instance.lines) == 20
end

View File

@@ -5,7 +5,7 @@
using UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip
@testset "read_benchmark" begin
instance = UnitCommitment.read_benchmark("test/case14")
instance = UnitCommitment.read("$FIXTURES/case14.json.gz")
@test length(instance.lines) == 20
@test length(instance.buses) == 14
@@ -112,7 +112,7 @@ using UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip
end
@testset "read_benchmark sub-hourly" begin
instance = UnitCommitment.read_benchmark("test/case14-sub-hourly")
instance = UnitCommitment.read("$FIXTURES/case14-sub-hourly.json.gz")
@test instance.time == 4
unit = instance.units[1]
@test unit.name == "g1"

View File

@@ -20,11 +20,11 @@ import UnitCommitment:
function _test(
formulation::Formulation;
instances = ["test/case14"],
instances = ["case14"],
dump::Bool = false,
)::Nothing
for instance_name in instances
instance = UnitCommitment.read_benchmark(instance_name)
instance = UnitCommitment.read("$(FIXTURES)/$(instance_name).json.gz")
model = UnitCommitment.build_model(
instance = instance,
formulation = formulation,
@@ -78,7 +78,7 @@ end
@testset "WanHob2016" begin
_test(
Formulation(ramping = WanHob2016.Ramping()),
instances = ["test/case14-flex"],
instances = ["case14-flex"],
)
end
end

View File

@@ -8,6 +8,8 @@ using UnitCommitment
push!(Base.LOAD_PATH, @__DIR__)
UnitCommitment._setup_logger(level = Base.CoreLogging.Error)
FIXTURES = "$(@__DIR__)/fixtures"
@testset "UnitCommitment" begin
include("usage.jl")
@testset "import" begin
@@ -15,6 +17,7 @@ UnitCommitment._setup_logger(level = Base.CoreLogging.Error)
end
@testset "instance" begin
include("instance/read_test.jl")
include("instance/migrate_test.jl")
end
@testset "model" begin
include("model/formulations_test.jl")

View File

@@ -6,7 +6,7 @@ using UnitCommitment, Test, LinearAlgebra
import UnitCommitment: _Violation, _offer, _query
@testset "_ViolationFilter" begin
instance = UnitCommitment.read_benchmark("test/case14")
instance = UnitCommitment.read("$FIXTURES/case14.json.gz")
filter = UnitCommitment._ViolationFilter(max_per_line = 1, max_total = 2)
_offer(

View File

@@ -6,7 +6,7 @@ using UnitCommitment, Test, LinearAlgebra
import UnitCommitment: _Violation, _offer, _query
@testset "find_violations" begin
instance = UnitCommitment.read_benchmark("test/case14")
instance = UnitCommitment.read("$FIXTURES/case14.json.gz")
for line in instance.lines, t in 1:instance.time
line.normal_flow_limit[t] = 1.0
line.emergency_flow_limit[t] = 1.0

View File

@@ -5,7 +5,7 @@
using UnitCommitment, Test, LinearAlgebra
@testset "_susceptance_matrix" begin
instance = UnitCommitment.read_benchmark("test/case14")
instance = UnitCommitment.read("$FIXTURES/case14.json.gz")
actual = UnitCommitment._susceptance_matrix(instance.lines)
@test size(actual) == (20, 20)
expected = Diagonal([
@@ -34,7 +34,7 @@ using UnitCommitment, Test, LinearAlgebra
end
@testset "_reduced_incidence_matrix" begin
instance = UnitCommitment.read_benchmark("test/case14")
instance = UnitCommitment.read("$FIXTURES/case14.json.gz")
actual = UnitCommitment._reduced_incidence_matrix(
lines = instance.lines,
buses = instance.buses,
@@ -81,7 +81,7 @@ end
end
@testset "_injection_shift_factors" begin
instance = UnitCommitment.read_benchmark("test/case14")
instance = UnitCommitment.read("$FIXTURES/case14.json.gz")
actual = UnitCommitment._injection_shift_factors(
lines = instance.lines,
buses = instance.buses,
@@ -112,7 +112,7 @@ end
end
@testset "_line_outage_factors" begin
instance = UnitCommitment.read_benchmark("test/case14")
instance = UnitCommitment.read("$FIXTURES/case14.json.gz")
isf_before = UnitCommitment._injection_shift_factors(
lines = instance.lines,
buses = instance.buses,

View File

@@ -4,12 +4,9 @@
using UnitCommitment, Cbc, JuMP
basedir = @__DIR__
@testset "generate_initial_conditions!" begin
# Load instance
instance =
UnitCommitment.read("$basedir/../fixtures/case118-initcond.json.gz")
instance = UnitCommitment.read("$FIXTURES/case118-initcond.json.gz")
optimizer = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0)
# All units should have unknown initial conditions

View File

@@ -5,7 +5,7 @@
using UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON, GZip
@testset "slice" begin
instance = UnitCommitment.read_benchmark("test/case14")
instance = UnitCommitment.read("$FIXTURES/case14.json.gz")
modified = UnitCommitment.slice(instance, 1:2)
# Should update all time-dependent fields

View File

@@ -5,7 +5,7 @@
using UnitCommitment, LinearAlgebra, Cbc, JuMP, JSON
@testset "usage" begin
instance = UnitCommitment.read_benchmark("test/case14")
instance = UnitCommitment.read("$FIXTURES/case14.json.gz")
for line in instance.lines, t in 1:4
line.normal_flow_limit[t] = 10.0
end

View File

@@ -4,11 +4,9 @@
using UnitCommitment, JSON, GZip, DataStructures
basedir = @__DIR__
function parse_case14()
return JSON.parse(
GZip.gzopen("$basedir/../../instances/test/case14.json.gz"),
GZip.gzopen("$FIXTURES/case14.json.gz"),
dicttype = () -> DefaultOrderedDict(nothing),
)
end