Update docs

bugfix/formulations
Alinson S. Xavier 4 years ago
parent 6adf12535e
commit 24871a7f8a

@ -23,7 +23,7 @@
### Citing ### Citing
If you use UnitCommitment.jl in your research (that is, if you use either the provided instances files, the mathematical models, or the algorithms), we kindly request that you cite the package as follows: 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, 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, 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).

@ -11,7 +11,7 @@ Instances
UnitCommitment.jl provides a large collection of benchmark instances collected 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. 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 [UCJL], as well as the original sources. If you use these instances in your research, we request that you cite UnitCommitment.jl, as well as the original sources.
Raw instances files are [available at our GitHub repository](https://github.com/ANL-CEEESA/UnitCommitment.jl/tree/dev/instances). Benchmark instances can also be loaded with Raw instances files are [available at our GitHub repository](https://github.com/ANL-CEEESA/UnitCommitment.jl/tree/dev/instances). Benchmark instances can also be loaded with
`UnitCommitment.read_benchmark(name)`, as explained in the [usage section](usage.md). `UnitCommitment.read_benchmark(name)`, as explained in the [usage section](usage.md).

@ -9,10 +9,7 @@ suffix: .
JuMP Model JuMP Model
========== ==========
In this page, we describe the JuMP optimization model produced by the function `UnitCommitment.build_model`. A detailed understanding of this model is not necessary if you are just interested in using the package to solve some standard unit commitment cases, but it may be useful, for example, if you need to solve a slightly different problem, with additional variables and constraints. In this page, we describe the JuMP optimization model produced by the function `UnitCommitment.build_model`. A detailed understanding of this model is not necessary if you are just interested in using the package to solve some standard unit commitment cases, but it may be useful, for example, if you need to solve a slightly different problem, with additional variables and constraints. The notation in this page generally follows [KnOsWa20].
The notation in this page generally follows [KnOsWa20].
Decision variables Decision variables
------------------ ------------------
@ -25,9 +22,9 @@ Name | Symbol | Description | Unit
`switch_on[g,t]` | $v_{g}(t)$ | True is generator `g` switches on at time `t`. | Binary `switch_on[g,t]` | $v_{g}(t)$ | True is generator `g` switches on at time `t`. | Binary
`switch_off[g,t]` | $w_{g}(t)$ | True if generator `g` switches off at time `t`. | Binary `switch_off[g,t]` | $w_{g}(t)$ | True if generator `g` switches off at time `t`. | Binary
`prod_above[g,t]` |$p'_{g}(t)$ | Amount of power produced by generator `g` above its minimum power output at time `t`. For example, if the minimum power of generator `g` is 100 MW and `g` is producing 115 MW of power at time `t`, then `prod_above[g,t]` equals `15.0`. | MW `prod_above[g,t]` |$p'_{g}(t)$ | Amount of power produced by generator `g` above its minimum power output at time `t`. For example, if the minimum power of generator `g` is 100 MW and `g` is producing 115 MW of power at time `t`, then `prod_above[g,t]` equals `15.0`. | MW
`segprod[g,t,l]` | $p^l_g(t)$ | Amount of power from piecewise linear segment `l` produced by generator `g` at time `t`. For example, if cost curve for generator `g` is defined by the points `(100, 1400)`, `(110, 1600)`, `(130, 2200)` and `(135, 2400)`, and if the generator is producing 115 MW of power at time `t`, then `segprod[g,t,:]` equals `[10.0, 5.0, 0.0]`.| MW `segprod[g,t,k]` | $p^k_g(t)$ | Amount of power from piecewise linear segment `k` produced by generator `g` at time `t`. For example, if cost curve for generator `g` is defined by the points `(100, 1400)`, `(110, 1600)`, `(130, 2200)` and `(135, 2400)`, and if the generator is producing 115 MW of power at time `t`, then `segprod[g,t,:]` equals `[10.0, 5.0, 0.0]`.| MW
`reserve[g,t]` | $r_g(t)$ | Amount of reserves provided by generator `g` at time `t`. | MW `reserve[g,t]` | $r_g(t)$ | Amount of reserves provided by generator `g` at time `t`. | MW
`startup[g,t,s]` | $\delta^s_g(t)$ | True if generator `g` switches on at time `t` incurring start-up costs from start-up type `s`. | Binary `startup[g,t,s]` | $\delta^s_g(t)$ | True if generator `g` switches on at time `t` incurring start-up costs from start-up category `s`. | Binary
### Buses ### Buses
@ -42,7 +39,7 @@ Name | Symbol | Description | Unit
Name | Symbol | Description | Unit Name | Symbol | Description | Unit
-----|:------:|-------------|:------: -----|:------:|-------------|:------:
`loads[ps,t]` | $d_{ps}(t)$ | Amount of power served to price-sensitive load `ps` at time `t`. | MW `loads[s,t]` | $d_{s}(t)$ | Amount of power served to price-sensitive load `s` at time `t`. | MW
### Transmission lines ### Transmission lines
@ -53,43 +50,145 @@ Name | Symbol | Description | Unit
```{danger} ```{danger}
Since transmission and N-1 security constraints are enforced in a lazy way, most of the variables `flow[l,t]` and `overflow[l,t]` are never added to the model. Accessing `model[:flow][l,t]`, for example, without first checking that the variable exists will generate an error. Since transmission and N-1 security constraints are enforced in a lazy way, most of the variables `flow[l,t]` and `overflow[l,t]` are never added to the model. Accessing `model[:flow][l,t]`, for example, without first checking that the variable exists will likely generate an error.
``` ```
Objective function Objective function
------------------ ------------------
$$ $$
\begin{align*} \begin{align}
\text{minimize} \;\; & \text{minimize} \;\; &
\sum_{s \in PS} x \sum_{t \in \mathcal{T}}
\end{align*} \sum_{g \in \mathcal{G}}
C^\text{min}_g(t) u_g(t) \\
&
+ \sum_{t \in \mathcal{T}}
\sum_{g \in \mathcal{G}}
\sum_{g \in \mathcal{K}_g}
C^k_g(t) p^k_g(t) \\
&
+ \sum_{t \in \mathcal{T}}
\sum_{g \in \mathcal{G}}
\sum_{s \in \mathcal{S}_g}
C^s_{g}(t) \delta^s_g(t) \\
&
+ \sum_{t \in \mathcal{T}}
\sum_{l \in \mathcal{L}}
C^\text{overflow}_{l}(t) f^+_l(t) \\
&
+ \sum_{t \in \mathcal{T}}
\sum_{b \in \mathcal{B}}
C^\text{curtail}(t) s^+_b(t) \\
&
- \sum_{t \in \mathcal{T}}
\sum_{s \in \mathcal{PS}}
R_{s}(t) d_{s}(t) \\
\end{align}
$$ $$
where
- $\mathcal{B}$ is the set of buses
- $\mathcal{G}$ is the set of generators
- $\mathcal{L}$ is the set of transmission lines
- $\mathcal{PS}$ is the set of price-sensitive loads
- $\mathcal{S}_g$ is the set of start-up categories for generator $g$
- $\mathcal{T}$ is the set of time steps
- $C^\text{curtail}(t)$ is the curtailment penalty (in \$/MW)
- $C^\text{min}_g(t)$ is the cost of keeping generator $g$ on and producing at minimum power during time $t$ (in \$)
- $C^\text{overflow}_{l}(t)$ is the flow limit penalty for line $l$ at time $t$ (in \$/MW)
- $C^k_g(t)$ is the cost for generator $g$ to produce 1 MW of power at time $t$ under piecewise linear segment $k$
- $C^s_{g}(t)$ is the cost of starting up generator $g$ at time $t$ under start-up category $s$ (in \$)
- $R_{s}(t)$ is the revenue obtained from serving price-sensitive load $s$ at time $t$ (in \$/MW)
Constraints Constraints
----------- -----------
TODO
Querying the model Inspecting and modifying the model
------------------ ----------------------------------
### Accessing decision variables
After building a model using `UnitCommitment.build_model`, it is possible to obtain a reference to the decision variables by calling `model[:varname][index]`. For example, `model[:is_on]["g1",1]` returns a direct reference to the JuMP variable indicating whether generator named "g1" is on at time 1. The script below illustrates how to build a model, solve it and display the solution without using the function `UnitCommitment.solution`.
Modifying the model ```julia
------------------- using Cbc
using Printf
using JuMP
using UnitCommitment
### Adding new constraints # Load benchmark instance
instance = UnitCommitment.read_benchmark("matpower/case118/2017-02-01")
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas a euismod velit. Nulla semper ligula ex, sed maximus lacus eleifend quis. Nam efficitur magna eget lacinia sollicitudin. Vivamus placerat luctus velit, vitae consequat odio hendrerit sit amet. Quisque mattis elit a leo finibus interdum. Nunc aliquam sem lorem, nec feugiat magna feugiat id. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Aliquam malesuada sapien et ex lobortis, et maximus arcu sodales. Donec pretium leo lacus, a efficitur dui ultricies nec. Vestibulum et mauris risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Fusce finibus nunc ut neque scelerisque mollis. Etiam pretium, nulla et luctus lacinia, ante enim lobortis urna, eget tempus ante dolor non lorem. # Build JuMP model
model = UnitCommitment.build_model(
instance=instance,
optimizer=Cbc.Optimizer,
)
# Solve the model
UnitCommitment.optimize!(model)
### Removing existing constraints # Display commitment status
for g in instance.units
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas a euismod velit. Nulla semper ligula ex, sed maximus lacus eleifend quis. Nam efficitur magna eget lacinia sollicitudin. Vivamus placerat luctus velit, vitae consequat odio hendrerit sit amet. Quisque mattis elit a leo finibus interdum. Nunc aliquam sem lorem, nec feugiat magna feugiat id. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Aliquam malesuada sapien et ex lobortis, et maximus arcu sodales. Donec pretium leo lacus, a efficitur dui ultricies nec. Vestibulum et mauris risus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Fusce finibus nunc ut neque scelerisque mollis. Etiam pretium, nulla et luctus lacinia, ante enim lobortis urna, eget tempus ante dolor non lorem. for t in 1:instance.time
@printf(
"%-10s %5d %5.1f %5.1f %5.1f\n",
g.name,
t,
value(model[:is_on][g.name, t]),
value(model[:switch_on][g.name, t]),
value(model[:switch_off][g.name, t]),
)
end
end
```
### Modifying the model
Since we now have a direct reference to the JuMP decision variables, it is possible to fix variables, change the coefficients in the objective function, or even add new constraints to the model before solving it. The script below shows how can this be accomplished. For more information on modifying an existing model, [see the JuMP documentation](https://jump.dev/JuMP.jl/stable/manual/variables/).
```julia
using Cbc
using JuMP
using UnitCommitment
# Load benchmark instance
instance = UnitCommitment.read_benchmark("matpower/case118/2017-02-01")
# Construct JuMP model
model = UnitCommitment.build_model(
instance=instance,
optimizer=Cbc.Optimizer,
)
# Fix a decision variable to 1.0
JuMP.fix(
model[:is_on]["g1",1],
1.0,
force=true,
)
# Change the objective function
JuMP.set_objective_coefficient(
model,
model[:switch_on]["g2",1],
1000.0,
)
# Create a new constraint
@constraint(
model,
model[:is_on]["g3",1] + model[:is_on]["g4",1] <= 1,
)
# Solve the model
UnitCommitment.optimize!(model)
```
References References
---------- ----------

Loading…
Cancel
Save