Skip to content

Glossary

The one definition of each name this project uses. The rest hang off one distinction:

A spec is the math you write. A model is that spec with your data on it. A result is one answer read back.

check ──▶ Program ──▶ build ──▶ Model ──▶ solve ──▶ Result
 (spec)   (lowered)   (+data)             (answer)

The chain

Spec
The math before any data: a YAML file, a mapping, or a Spec from math_spec.to_spec. It carries no numbers, and every verb takes it first. What it may contain is the language.
Program
The spec lowered to the plan a build reads its rows off: what check returns, still with no data. The two states are the language's (reading a loaded model).
Model
A spec with data attached: what build returns (lpspec.Model). One model feeds any sink: solve(), write(path), row(...), diagnostics(). update(...) puts new numbers on it in place.
Result
One answer read back from a solve: objective, primal(name), dual(name), evaluate(name). It owns its tables, so it outlives its model.
Archive
A spec, the data it was solved with and what came back, written together as one zip or one directory by archive= (archiving). It reads back as a SolveArchive, or a SweepArchive where the sources were cut. Never "artifact".

The verbs

check · build · solve · write
check(spec) validates and lowers. build(spec, sources) returns a Model. solve and write build and then solve or stream in one call. There is no Python API for constructing a spec.
update
model.update(sources) puts new numbers on a built model in place, naming only what changed. A change that moves a mask rebuilds and solves cold.
load · scan
The two ways a saved answer is read back. load_result, load_runs and load_archive read whole, so the directory is free afterwards. scan_result, scan_runs and scan_archive read each frame at the call that asks for it, so the files have to outlive the value (loading or scanning). Never "open".
Buildable
The type alias for a spec argument: str | Path | dict | Spec. The lowered Program that check returns is not one.
Source
The type alias for one value of sources. The shapes it covers are the data contract.
Label
One member of a dimension, wind say, and its type alias: int | float | str | datetime. A sweep's slice key is a label too, and EachCoordinate(dim) slices on one label of dim at a time.

The data

Index
A dimension's labels in order, supplied under the dimension's own key in sources. shift reads that order positionally (the data contract).
Coordinate
One point of a declaration's dimensions: one snapshot for one generator. A parameter has a value at each coordinate it covers, or no row there. The language calls the dimensions themselves the declaration's frame (named expressions).
Table
A polars DataFrame with one column per dimension, a value column and one row per coordinate: what a parameter arrives as, and what primal hands back. The code calls one a frame and means the same thing. The plural Tables is a different noun: the built model as a sink sees it.
Mask
The where: on a declaration. What an excluded coordinate means is absence.

How it runs

Lane
One of two ways a spec is executed. The relational lane (the default) validates at load time, lowers to the plan and streams on polars. The linopy lane (lpspec.linopy, the [linopy] extra) builds the same spec as a linopy.Model. Both accept the same language (relationship to linopy).
eager
The linopy lane, and nothing else — the eager lane in the differential suite and the benchmark harness. Never a reader: how a saved answer is read is load or scan.
Engine
The relational lane's builder: it fills the model's tables from the attached data and hands them to a sink.
Sink
Where the built tables land: a solver (highs, gurobi, xpress) or a file writer (.lp, .mps). linopy is a lane, not a sink.
Sources
The data you attach: parameter, dimension and relation names to tables, and dimension names to their labels.
attach
Fitting sources onto a spec to make a Model; what build does and update does again. Never "bind", so that bound means one thing.

The built form

Tables
The built model as a sink sees it: cols (bounds, type), obj, rows, matrix (CSR), quad and sos.
keep
How much of a session model.solve carries to the next solve: solver (default), progress (its work too) or nothing (the verbs).
solve_over (a sweep)
Solve one spec once per slice of an axis and fold the answers into a Runs, releasing each slice's model as it goes. A sweep, never a "study".
held · spilled
Where a sweep's frames are. A held sweep carries them in memory, and runs.primal(name) and the exports — the frame readers, the ones that hand back a table — answer off them. A spilled sweep left them in a directory, which is what spill_to= writes and what scan_runs reads: there runs.scan(name) is the reader and the frame readers refuse (spilling).

Row types

Record · Metrics · SliceMetrics
The three saved rows, each a NamedTuple that names its own columns. Where a column is nullable, the type also derives the schema it is written with, so an all-null column keeps its own type instead of the one a single row infers. Record is how a solve terminated, one per solve. Metrics is what it took — the sizes, what the sink added to them, the counters and the clocks, every clock naming its unit — and is what archive.metrics hands back (the attributes). SliceMetrics is one slice of a sweep's share of that, in its own columns, and is the row behind runs.metrics.

A row is a value and gets a type; a table stays a Table. So Record and SliceMetrics are the rows behind runs.objective and runs.metrics rather than what those hand back, and a reader that wants one row of a table asks the frame for it.

bound means one thing

bound
A lower or upper limit on a variable or a constraint row: the bounds: of a declaration, the BOUNDS section of an .mps file, an absent bound the solver reads as infinity. Nothing else; data is attached, never bound.