Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,14 @@
# The generator wins. Nobody edits this file by hand, so the formatting is not
# anyone's to prefer.
CHANGELOG.md

# `tools/gallery.py` writes the body of these pages: the model, verbatim, and
# the document the typesetter prints from it. Prettier pads the legend tables
# it emits, the generator writes them unpadded, and each undoes the other — so
# the committed file could never satisfy both, and `tests/test_docs.py` compares
# it to the generator byte for byte.
#
# Same rule as CHANGELOG.md above: the generator wins where nobody edits by
# hand. `index.md` is not listed — it carries no generated block.
docs/examples/dispatch.md
docs/examples/operators.md
88 changes: 88 additions & 0 deletions docs/examples/dispatch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<!--
SPDX-FileCopyrightText: math-spec contributors
SPDX-License-Identifier: CC-BY-4.0
-->

# Least-cost dispatch

The smallest file that is a whole model: generators with a capacity, an hourly
load to meet, and a cost to minimise. It is the model on the
[home page](../index.md) and in the README, and the one the language reference
varies when it needs a base to change one thing in.

Two things worth reading for. The `where:` on `p` deletes the rows where a
generator has no capacity — [absence](../reference/language/absence.md) is a
declaration, not a runtime check. And `sum(p, over=generator)` names the
dimension it reduces, so the constraint's frame is what remains.

<!-- gallery:begin -->
```yaml
description: Least-cost dispatch of a generator fleet against an hourly load.

dimensions:
snapshot: { dtype: int, description: dispatch periods }
generator: { values: [wind, solar, gas], description: generating units }

parameters:
p_max: { dims: [generator], description: installed capacity }
load: { dims: [snapshot], description: demand to be met }
cost: { dims: [generator], description: marginal cost }

variables:
p:
description: output of a generator in a snapshot
foreach: [snapshot, generator]
where: "p_max > 0"
bounds: { lower: 0, upper: p_max }

constraints:
power_balance:
foreach: [snapshot]
expression: sum(p, over=generator) == load

objective:
sense: minimize
expression: sum(p * cost)
```

Least-cost dispatch of a generator fleet against an hourly load.

#### Sets

| Symbol | Meaning |
|---|---|
| $\mathcal{T}$ | index $t$ — `snapshot` — dispatch periods |
| $\mathcal{G}$ | index $g$ — `generator` — generating units |

#### Parameters

| Symbol | Meaning |
|---|---|
| $p^{\mathrm{max}}$ | `p_max` over $\mathcal{G}$ — installed capacity |
| $\mathit{load}$ | `load` over $\mathcal{T}$ — demand to be met |
| $\mathit{cost}$ | `cost` over $\mathcal{G}$ — marginal cost |

#### Variables

| Symbol | Meaning |
|---|---|
| $p$ | `p` over $\mathcal{T} \times \mathcal{G}$ — output of a generator in a snapshot |

#### Objective

$$\min \sum_{t \in \mathcal{T},\enspace g \in \mathcal{G}} p_{t,g} \cdot \mathit{cost}_{g}$$

#### Subject to

**`power_balance`**

$$\sum_{g \in \mathcal{G}} p_{t,g} = \mathit{load}_{t} \qquad \forall\thinspace t \in \mathcal{T}$$

#### Variable domains

**`p`**

$$0 \le p_{t,g} \le p^{\mathrm{max}}_{g} \qquad \forall\thinspace t \in \mathcal{T},\enspace g \in \mathcal{G} \thinspace:\thinspace p^{\mathrm{max}}_{g} > 0$$
<!-- gallery:end -->

Regenerate with `pixi run python -m tools.gallery`.
23 changes: 23 additions & 0 deletions docs/examples/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!--
SPDX-FileCopyrightText: math-spec contributors
SPDX-License-Identifier: CC-BY-4.0
-->

# Examples

Whole models, each shown as the file and as the math it prints. The reference
pages take the language a construct at a time; these take it a **model** at a
time, which is the form anyone writing one actually needs.

Every model here is a real file under `examples/` in the repository, not a
fragment written for the page. They are the same files the test suite loads and
the LaTeX gate compiles, so a model that stopped being valid — or that started
printing different math — fails CI rather than going stale here.

- [Least-cost dispatch](dispatch.md) — the smallest model that is a model: a
balance, a bound, and a cost to minimise.
- [One construct per model](operators.md) — the operator probes: the smallest
file that declares each built-in, beside the equation it renders.

The math on these pages is written by the typesetter, from the file above it —
see [Typeset the math](../reference/typeset.md) for how to print your own.
Loading
Loading