A production-quality implementation of the unit commitment problem using Pyomo and the open-source HiGHS solver.
Unit commitment (UC) is a fundamental optimization problem in power systems operations. Given a fleet of generators and a forecasted electricity demand over a planning horizon, the goal is to decide which generators to turn on or off (commitment) and how much power each should produce (dispatch) at every time step, while minimizing total operating cost and respecting engineering constraints.
This repository solves a simplified but realistic 24-hour UC problem with 5 thermal generators and 1 wind farm.
u[g, t]-- Binary, 1 if generator g is committed (on) at hour tv[g, t]-- Binary, 1 if generator g starts up at hour tw[g, t]-- Binary, 1 if generator g shuts down at hour tp[g, t]-- Continuous, power output of generator g at hour t (MW)
Minimize total cost = fuel cost + startup cost + shutdown cost:
min SUM over g, t of:
fuel_cost[g] * p[g,t] + startup_cost[g] * v[g,t] + shutdown_cost[g] * w[g,t]
-
Power balance -- Total generation must meet demand at every hour:
SUM_g p[g,t] + wind[t] = demand[t] for all t -
Generation limits -- When committed, output must stay within bounds:
p_min[g] * u[g,t] <= p[g,t] <= p_max[g] * u[g,t] for all g, t -
Startup/shutdown logic -- Links commitment, startup, and shutdown variables:
u[g,t] - u[g,t-1] = v[g,t] - w[g,t] for all g, t >= 2 -
Ramp-up limit -- Output cannot increase too fast between hours:
p[g,t] - p[g,t-1] <= ramp_up[g] * u[g,t-1] + p_min[g] * v[g,t] -
Ramp-down limit -- Output cannot decrease too fast between hours:
p[g,t-1] - p[g,t] <= ramp_down[g] * u[g,t] + p_min[g] * w[g,t] -
Minimum up time -- Once started, a generator must stay on for a minimum number of hours:
SUM_{s=t-min_up[g]+1}^{t} v[g,s] <= u[g,t] for all g, t -
Minimum down time -- Once shut down, a generator must stay off for a minimum number of hours:
SUM_{s=t-min_down[g]+1}^{t} w[g,s] <= 1 - u[g,t] for all g, t -
Spinning reserve -- Committed capacity must exceed demand by a reserve margin:
SUM_g p_max[g] * u[g,t] + wind[t] >= demand[t] + reserve[t] for all t
Requires Python 3.10 or later.
# Clone the repository
git clone https://github.com/anzapatab/pyomo-unit-commitment-example.git
cd pyomo-unit-commitment-example
# Create a virtual environment (recommended)
python -m venv .venv
source .venv/bin/activate
# Install dependencies
pip install -e ".[dev]"python -m src.unit_commitment========================================================================================
UNIT COMMITMENT RESULTS
========================================================================================
Solver status : optimal
Total cost : $510,620.00
Solve time : 0.22s
MIP gap : 0.0000%
----------------------------------------------------------------------------------------
COMMITMENT SCHEDULE (1 = on, 0 = off)
----------------------------------------------------------------------------------------
Hour | Coal-1 | Coal-2 | Gas-CC | Gas-CT-1 | Gas-CT-2
01 | 1 | 1 | 0 | 1 | 0
02 | 1 | 1 | 0 | 1 | 0
03 | 1 | 1 | 0 | 0 | 0
...
17 | 1 | 1 | 1 | 1 | 0
18 | 1 | 1 | 1 | 1 | 1
19 | 1 | 1 | 1 | 0 | 1
...
----------------------------------------------------------------------------------------
DISPATCH SCHEDULE (MW)
----------------------------------------------------------------------------------------
Hour | Coal-1 | Coal-2 | Gas-CC | Gas-CT-1 | Gas-CT-2 | Wind | Demand
01 | 300.0 | 210.0 | 0.0 | 40.0 | 0.0 | 150.0 | 700.0
...
18 | 500.0 | 400.0 | 320.0 | 40.0 | 40.0 | 100.0 | 1400.0
...
(Exact values may vary slightly depending on solver version.)
pytest tests/ -vpyomo-unit-commitment-example/
|-- src/
| |-- __init__.py
| |-- data.py # Generator parameters, demand/wind profiles
| |-- unit_commitment.py # Pyomo model construction and solve
|-- tests/
| |-- __init__.py
| |-- test_unit_commitment.py
|-- pyproject.toml
|-- LICENSE
|-- README.md
MIT License. See LICENSE for details.