One construct per model#
For each built-in operator, the smallest model that declares it, beside the equation it prints. The reference page shows the same equations as one table. This page shows the file that produced each one.
sum(array)#
examples/operators/sum_all.yaml
description: Every dimension at once — `sum(array)` names none of them and takes them all.
dimensions:
snapshot: { dtype: int }
generator: { dtype: str }
parameters:
budget: { dims: [] }
variables:
p:
dims: [snapshot, generator]
bounds: { lower: 0 }
constraints:
fleet_budget:
dims: []
expression: sum(p) <= budget
objective: { sense: minimize, expression: sum(p) }
\(\sum_{t \in \mathcal{T},\ g \in \mathcal{G}} p_{t,g} \le \mathrm{budget}\)
sum(array, over=dim)#
examples/operators/sum.yaml
description: The plain reduction — `sum(array, over=dim)` collapses one dimension.
dimensions:
snapshot: { dtype: int }
generator: { dtype: str }
parameters:
limit: { dims: [snapshot] }
variables:
p:
dims: [snapshot, generator]
bounds: { lower: 0 }
constraints:
fleet_total:
dims: [snapshot]
expression: sum(p, over=generator) <= limit
objective: { sense: minimize, expression: sum(p) }
\(\sum_{g \in \mathcal{G}} p_{t,g} \le \mathrm{limit}_{t} \qquad \forall\, t \in \mathcal{T}\)
sum(array, by=relation, over=a, into=b)#
examples/operators/sum_by.yaml
description: >-
The membership reduction — `sum(array, by=relation, over=a, into=b)` lands the result on the
column the relation is read to, which is what makes topology data rather than
structure.
dimensions:
snapshot: { dtype: int }
generator: { dtype: str }
bus: { dtype: str }
relations:
gen_bus: { key: generator, values: bus }
parameters:
limit: { dims: [snapshot, bus] }
variables:
p:
dims: [snapshot, generator]
bounds: { lower: 0 }
constraints:
bus_total:
dims: [snapshot, bus]
expression: sum(p, by=gen_bus, over=generator, into=bus) <= limit
objective: { sense: minimize, expression: sum(p) }
\(\sum_{g \in \mathcal{G} \,:\, \mathrm{gen\_bus}(g) = b} p_{t,g} \le \mathrm{limit}_{t,b} \qquad \forall\, t \in \mathcal{T},\ b \in \mathcal{B}\)
sum(array, by=relation, over=a, into=b), joining on the rest of the key#
examples/operators/sum_by_columns.yaml
description: >-
A call that names its ends — `sum(array, by=relation, over=a, into=b)`
consumes column `a` and lands on column `b`, and the other key column is
joined on, so each zone's total is taken per period.
dimensions:
generator: { dtype: str }
period: { dtype: int }
zone: { dtype: str }
relations:
zone_of: { key: [generator, period], values: zone }
parameters:
demand: { dims: [zone, period] }
variables:
p:
dims: [generator, period]
bounds: { lower: 0 }
constraints:
zone_balance:
dims: [zone, period]
expression: sum(p, by=zone_of, over=generator, into=zone) >= demand
objective: { sense: minimize, expression: sum(p) }
\(\sum_{g \in \mathcal{G} \,:\, \mathrm{zone\_of}(g,\ e) = z} p_{g,e} \ge \mathrm{demand}_{z,e} \qquad \forall\, z \in \mathcal{Z},\ e \in \mathcal{E}\)
sum(array, by=relation, over=[a, …], into=[b, …])#
examples/operators/sum_by_column_lists.yaml
description: >-
A call with several columns at each end — `sum(array, by=relation, over=[a, …], into=[b, …])`
consumes both key columns at once and lands on the product of both value
columns in one join.
dimensions:
generator: { dtype: str }
period: { dtype: int }
bus: { dtype: str }
technology: { dtype: str }
relations:
slot_of: { key: [generator, period], values: [bus, technology] }
parameters:
cap: { dims: [bus, technology] }
variables:
p:
dims: [generator, period]
bounds: { lower: 0 }
constraints:
slot_cap:
dims: [bus, technology]
expression: sum(p, by=slot_of, over=[generator, period], into=[bus, technology]) <= cap
objective: { sense: minimize, expression: sum(p) }
\(\sum_{g \in \mathcal{G},\ e \in \mathcal{E} \,:\, \mathrm{slot\_of.bus}(g,\ e) = b \wedge \mathrm{slot\_of.technology}(g,\ e) = t} p_{g,e} \le \mathrm{cap}_{b,t} \qquad \forall\, b \in \mathcal{B},\ t \in \mathcal{T}\)
at(array, by=relation, over=a, into=b)#
examples/operators/at.yaml
description: >-
The adjoint of the membership reduction — `at(array, by=relation, over=a, into=b)` reads one
coarse value once per fine label pointing at it.
dimensions:
snapshot: { dtype: int }
period: { dtype: int }
relations:
period_of: { key: snapshot, values: period }
parameters:
cap: { dims: [period] }
variables:
p:
dims: [snapshot]
bounds: { lower: 0 }
constraints:
within_cap:
dims: [snapshot]
expression: p <= at(cap, by=period_of, over=period, into=snapshot)
objective: { sense: minimize, expression: sum(p) }
\(p_{t} \le \mathrm{cap}_{\mathrm{period\_of}(t)} \qquad \forall\, t \in \mathcal{T}\)
at(array, by=relation, over=a, into=b), two columns over one dimension#
examples/operators/at_columns.yaml
description: >-
A read that names its ends — `at(array, by=relation, over=a, into=b)`
reads column `a` where a table has two columns over one dimension, here the
sending end of a line.
dimensions:
line: { dtype: str }
bus: { dtype: str }
relations:
ends: { key: line, values: { bus0: bus, bus1: bus } }
parameters:
cap: { dims: [bus] }
variables:
f:
dims: [line]
bounds: { lower: 0 }
constraints:
sending_cap:
dims: [line]
expression: f <= at(cap, by=ends, over=bus0, into=line)
objective: { sense: minimize, expression: sum(f) }
\(f_{l} \le \mathrm{cap}_{\mathrm{ends.bus0}(l)} \qquad \forall\, l \in \mathcal{L}\)
shift(array, along=dim, offset=n)#
examples/operators/shift.yaml
description: >-
Translation with no edge policy — the vacated position is absent, so the row
it would have fed is not built.
dimensions:
snapshot: { dtype: int }
variables:
p:
dims: [snapshot]
bounds: { lower: 0 }
constraints:
no_faster_than_before:
dims: [snapshot]
expression: p <= shift(p, along=snapshot, offset=1)
objective: { sense: minimize, expression: sum(p) }
\(p_{t} \le p_{t - 1} \qquad \forall\, t \in \mathcal{T}\)
shift(array, along=dim, offset=n, edge='wrap')#
examples/operators/shift_wrap.yaml
description: >-
Cyclic translation — the horizon closed on itself, so the first position
reads the last and nothing is vacated.
dimensions:
snapshot: { dtype: int }
variables:
p:
dims: [snapshot]
bounds: { lower: 0 }
constraints:
no_faster_than_before:
dims: [snapshot]
expression: p <= shift(p, along=snapshot, offset=1, edge='wrap')
objective: { sense: minimize, expression: sum(p) }
\(p_{t} \le p_{t \ominus 1} \qquad \forall\, t \in \mathcal{T}\)
shift(array, along=dim, offset=n, edge=v)#
examples/operators/shift_edge.yaml
description: >-
Translation with a value at the edge — the vacated position contributes the
number instead of being absent, so the row survives.
dimensions:
snapshot: { dtype: int }
variables:
p:
dims: [snapshot]
bounds: { lower: 0 }
constraints:
no_faster_than_before:
dims: [snapshot]
expression: p <= shift(p, along=snapshot, offset=1, edge=0)
objective: { sense: minimize, expression: sum(p) }
\(p_{t} \le p_{t \boxminus_{0} 1} \qquad \forall\, t \in \mathcal{T}\)
shift(array, along=dim, offset=p, edge=…)#
examples/operators/shift_by_parameter.yaml
description: >-
Translation by an offset that differs per entity — `by:` names an integer
parameter, so each technology is reached by its own lead time rather than by
one the file had to fix.
dimensions:
technology: { dtype: str }
month: { dtype: int }
parameters:
lead: { dims: [technology], dtype: int }
demand: { dims: [technology, month] }
variables:
order:
dims: [technology, month]
bounds: { lower: 0 }
constraints:
arrives_after_its_lead:
dims: [technology, month]
expression: shift(order, along=month, offset=lead, edge=0) >= demand
objective: { sense: minimize, expression: sum(order) }
\(\mathit{order}_{t,m \boxminus_{0} \mathrm{lead}} \ge \mathrm{demand}_{t,m} \qquad \forall\, t \in \mathcal{T},\ m \in \mathcal{M}\)
shift(array, along=dim, offset=n, by=relation, within=c)#
examples/operators/shift_partitioned.yaml
description: >-
Translation inside a group — each season closed on itself, so a season's first
snapshot reads that season's last and no level crosses the boundary.
dimensions:
snapshot: { dtype: int }
season: { dtype: str }
relations:
season_of: { key: snapshot, values: season }
variables:
p:
dims: [snapshot]
bounds: { lower: 0 }
constraints:
no_faster_than_before_in_season:
dims: [snapshot]
expression: p <= shift(p, along=snapshot, offset=1, edge='wrap', by=season_of, within=season)
objective: { sense: minimize, expression: sum(p) }
\(p_{t} \le p_{t \ominus^{\mathrm{season\_of}(t)} 1} \qquad \forall\, t \in \mathcal{T}\)
sum_back(array, along=dim, window=n)#
examples/operators/sum_back.yaml
description: >-
A trailing window of a fixed width: a unit that started in the last three
hours is still on.
dimensions:
unit: { dtype: str }
hour: { dtype: int }
parameters:
min_up: { dims: [unit], dtype: int }
variables:
started:
dims: [unit, hour]
domain: binary
on:
dims: [unit, hour]
domain: binary
constraints:
stays_up_its_own_time:
dims: [unit, hour]
expression: sum_back(started, along=hour, window=3) <= on
objective: { sense: minimize, expression: sum(on) }
\(\sum_{h' \in \mathcal{H} \,:\, 0 \le h - h' < 3} \mathit{started}_{u,h'} \le \mathit{on}_{u,h} \qquad \forall\, u \in \mathcal{U},\ h \in \mathcal{H}\)
sum_back(array, along=dim, window=p)#
examples/operators/sum_back_by_parameter.yaml
description: >-
A trailing window whose width is data — `within:` names an integer parameter,
so a unit stays up for its *own* minimum time rather than one the file fixed.
dimensions:
unit: { dtype: str }
hour: { dtype: int }
parameters:
min_up: { dims: [unit], dtype: int }
variables:
started:
dims: [unit, hour]
domain: binary
on:
dims: [unit, hour]
domain: binary
constraints:
stays_up_its_own_time:
dims: [unit, hour]
expression: sum_back(started, along=hour, window=min_up) <= on
objective: { sense: minimize, expression: sum(on) }
\(\sum_{h' \in \mathcal{H} \,:\, 0 \le h - h' < \mathrm{min\_up}} \mathit{started}_{u,h'} \le \mathit{on}_{u,h} \qquad \forall\, u \in \mathcal{U},\ h \in \mathcal{H}\)
sum_back(array, along=dim, window=p, edge='wrap')#
examples/operators/sum_back_wrap.yaml
description: >-
A trailing window on a representative period that repeats, so the window at
the first hour reaches back into the last.
dimensions:
unit: { dtype: str }
hour: { dtype: int }
parameters:
min_up: { dims: [unit], dtype: int }
variables:
started:
dims: [unit, hour]
domain: binary
on:
dims: [unit, hour]
domain: binary
constraints:
stays_up_its_own_time:
dims: [unit, hour]
expression: sum_back(started, along=hour, window=min_up, edge='wrap') <= on
objective: { sense: minimize, expression: sum(on) }
\(\sum_{h' \in \mathcal{H} \,:\, 0 \le h \ominus h' < \mathrm{min\_up}} \mathit{started}_{u,h'} \le \mathit{on}_{u,h} \qquad \forall\, u \in \mathcal{U},\ h \in \mathcal{H}\)
sum_back(array, along=dim, window=n, by=relation, within=c)#
examples/operators/sum_back_partitioned.yaml
description: >-
A window that stops at each group's edge: representative days are separate
samples rather than consecutive hours, so a window must not reach across the
boundary between two of them.
dimensions:
unit: { dtype: str }
hour: { dtype: int }
day: { dtype: str }
relations:
day_of: { key: hour, values: day }
variables:
started:
dims: [unit, hour]
domain: binary
on:
dims: [unit, hour]
domain: binary
constraints:
stays_up_inside_its_day:
dims: [unit, hour]
expression: sum_back(started, along=hour, window=3, by=day_of, within=day) <= on
objective: { sense: minimize, expression: sum(on) }
\(\sum_{h' \in \mathcal{H} \,:\, 0 \le h -^{\mathrm{day\_of}(h)} h' < 3} \mathit{started}_{u,h'} \le \mathit{on}_{u,h} \qquad \forall\, u \in \mathcal{U},\ h \in \mathcal{H}\)
dual(constraint)#
examples/operators/dual.yaml
description: The row dual — `dual(constraint)` reads a solved constraint's shadow price over its own frame.
dimensions:
snapshot: { dtype: int }
parameters:
load: { dims: [snapshot] }
variables:
p:
dims: [snapshot]
bounds: { lower: 0 }
constraints:
balance:
dims: [snapshot]
expression: p >= load
expressions:
price: dual(balance)
objective: { sense: minimize, expression: sum(p) }
\(\mathit{price}_{t} = \lambda_{\mathrm{balance},t} \qquad \forall\, t \in \mathcal{T}\)
Regenerate with pixi run python -m tools.gallery.