Solve unit commitment in Python (MINLP)
Unit commitment is the classic power-systems planning problem: given several generating units, decide which to switch on and how much each should produce to meet demand at minimum cost. It mixes binary on/off decisions with a nonlinear cost curve — a mixed-integer nonlinear program (MINLP). With quicopt it is a short Pyomo model.
Why it's hard
An off unit costs nothing and produces nothing; an on unit pays a fixed start cost plus a fuel cost that grows with output (here, quadratically). The on/off choices are discrete and the cost is nonlinear, so neither an LP nor a plain nonlinear solver fits — you need MINLP.
Model it
Binary on[i] switches unit i; continuous p[i] is its output, capped at zero
unless the unit is on. Meet demand, minimize fixed + fuel cost. Modeled in
Pyomo (pip install "quicopt[pyomo]"):
import pyomo.environ as pyo
from quicopt import Client
caps, fixed, a = [50.0, 60.0, 40.0], [100.0, 120.0, 80.0], [0.010, 0.008, 0.012]
demand = 100.0
m = pyo.ConcreteModel()
m.on = pyo.Var(range(3), domain=pyo.Binary)
m.p = pyo.Var(range(3), bounds=(0, None))
m.cap = pyo.Constraint(range(3), rule=lambda m, i: m.p[i] <= caps[i] * m.on[i])
m.dem = pyo.Constraint(expr=sum(m.p[i] for i in range(3)) >= demand)
m.obj = pyo.Objective(expr=sum(fixed[i]*m.on[i] + a[i]*m.p[i]**2 for i in range(3)), sense=pyo.minimize)
print(Client("https://try.quicoptapi.pgi.fz-juelich.de").solve(m).display)
├── status: optimal ├── feasible: true ├── objective: 248.0 ├── x: x1=0, x2=1, x3=1, x4=0, x5=60, x6=40 (6 variables) └── solve_time: 0.0136 s
What you get
The least-cost plan switches on units 2 and 3 (x2=1, x3=1) at outputs 60 and
40 to cover demand 100, for a total cost of 248. Unit 1 stays off — its
fixed cost plus fuel would beat neither option. quicopt returns this from binary
on/off decisions and a nonlinear cost in one solve.
status: optimal means quicopt proved this is the least-cost commitment — no
mix of on/off decisions and outputs does better. The quadratic fuel cost is convex
on its own; what makes the problem hard is the binary on/off switching, which
is why it needs a mixed-integer solver rather than a plain nonlinear one. The same
model extends to more units, multiple time periods, and ramp limits by adding
constraints.
Next
- The problem class behind this: Mixed-integer nonlinear (MINLP)
- A runnable model for every supported class: Examples
- Set up the client and solve your first model: Getting started
Reference: A. J. Wood, B. F. Wollenberg, G. B. Sheblé, Power Generation, Operation, and Control, Wiley (3rd ed., 2013).
A bigger fleet — or a different problem?
Tell us what you're optimizing. We'll help you model it and point you at the right approach.
Frequently asked questions
Why isn't this just a linear program?
Two things break linearity: the on/off decisions are binary, and the fuel cost rises nonlinearly with output. Together that is a mixed-integer nonlinear program (MINLP) — quicopt handles both in one model.
Can I use integer (not just binary) unit counts?
On the free tier, nonlinear models accept binary integers only; general integers return a 422. Model each unit as its own binary on/off, which is the standard formulation anyway.
Is quicopt free to use?
Yes — pip install quicopt and your first call sets up a free key, no license.