Python API#
The mathspec package provides the functions that load, compose, print and
check the specification of an optimisation model (a spec).
This page lists each of them with its signature, its arguments and the errors
it raises, grouped by task. The functions you call are at the top level, and
the classes, constants and errors are in three modules:
| What it is | It lives in | Such as | Documented on |
|---|---|---|---|
| a function you call | mathspec |
to_spec, merge, typeset, advice |
this page |
the Spec that to_spec returns, the entries of a Spec, and the operators an expression may call |
mathspec.spec |
Spec, VariableSpec, BUILTIN_NAMES |
Spec API |
the Program that spec.program returns, the nodes of a Program, and what mathspec reports without refusing (advice) |
mathspec.program |
Program, Sum, Mask, Advice |
Program API |
| an error you catch, and the helper that suggests a name | mathspec.errors |
LanguageError, SchemaError, did_you_mean |
Errors below |
SymbolTable and the type FormatName are also at the top level. You pass a
SymbolTable as the symbols argument of a function that prints math
(a typesetting function). You pass a FormatName, such as
'latex', as the fmt argument of typeset or typeset_line.
A module whose name starts with an underscore is private (what counts as public API).
Guarantees#
Every public function keeps three guarantees:
- A function keeps no state, and uses no registry, no plugin, and no setting that changes what a spec means.
- A function returns a value or raises an error, and nothing between.
to_speceither returns aSpec, or raises an error that suggests the rewrite.advice()reports on a file that loads, and changes nothing. - A function writes out no entry that expands into ordinary entries
(a formulation) unless the caller asks. A
piecewise:orsos:entry stays one entry until the caller callsspec.expand().
to_spec#
mathspec.to_spec(spec)
#
Load and validate a spec definition — the language's front door.
Everything decidable without data is decided here: schema shape, every rule one entry is held to against the others, every expression and condition, and every macro template.
| PARAMETER | DESCRIPTION |
|---|---|
spec
|
| RETURNS | DESCRIPTION |
|---|---|
Spec
|
The spec as the file declares it, |
| RAISES | DESCRIPTION |
|---|---|
LanguageError
|
Anything the language does not accept, a text that is not a mapping of sections included. |
FileNotFoundError
|
A |
Source code in src/mathspec/_validation.py
merge and override#
Composing specs describes what merge and override do
with their files, and compose a spec from several files
lists the steps.
mathspec.merge(fragments, description=None)
#
fragments composed as peers, each owning the math it declares.
| PARAMETER | DESCRIPTION |
|---|---|
fragments
|
Each fragment as a YAML path, YAML text, a mapping, or a
loaded
TYPE:
|
description
|
What the composed spec is. A fragment's own
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Spec
|
The composed spec, loaded. A given entry a sibling introduces is |
Spec
|
folded away; one nothing introduces stays under |
| RAISES | DESCRIPTION |
|---|---|
LanguageError
|
A fragment does not load on its own; two fragments
declare one name; two fragments say different things about one
dimension, relation, map or given entry; a fragment reads a name as
something other than what its sibling introduces, as another kind
of thing, or over fewer dimensions than its body carries; a fragment
adds a term to a variable, a parameter, a constraint or a
definition written as |
FileNotFoundError
|
A |
TypeError
|
fragments is one path rather than a list. |
Source code in src/mathspec/_composition.py
mathspec.override(base, patches)
#
base with each patch laid over it in turn.
| PARAMETER | DESCRIPTION |
|---|---|
base
|
The spec being extended: a YAML path, YAML text, a mapping, or a
loaded
TYPE:
|
patches
|
Each patch as a YAML path, YAML text, a mapping, or a loaded
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Spec
|
The patched spec, loaded. |
| RAISES | DESCRIPTION |
|---|---|
LanguageError
|
The base does not load; the patched spec does not
load; a patch edits or removes an entry its base does not
declare; a patch creates one that is not whole; a patch redeclares
or removes a dimension or a relation; or a patch sets a whole
section to |
FileNotFoundError
|
A |
TypeError
|
patches is one path rather than a list. |
Source code in src/mathspec/_composition.py
The typesetting API#
mathspec.to_typst(spec, **options)
#
mathspec.typeset(spec, fmt, *, symbols=None, standalone=False, legend=True, numbered=True, inline_expressions=False)
#
Render spec's math in fmt.
| PARAMETER | DESCRIPTION |
|---|---|
spec
|
Anything |
fmt
|
What spells the math — a
TYPE:
|
symbols
|
How names print, as a
TYPE:
|
standalone
|
Emit a compilable document rather than a fragment.
TYPE:
|
legend
|
Prepend the symbol tables, the notation the equations use
included. The spec's own
TYPE:
|
numbered
|
Number the equations.
TYPE:
|
inline_expressions
|
Substitute each plain named expression into the equations that use it, rather than printing its symbol there and its definition once. A cased expression is a definition either way: its block is taller than the line it would sit in.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str
|
The rendered text. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
fmt names no format. |
LanguageError
|
A spec that does not compile; it does not print. |
SchemaError
|
A symbol table entry naming nothing in the spec, or a table written in a notation fmt does not read. |
Source code in src/mathspec/_typesetting/__init__.py
mathspec.typeset_line(spec, name, fmt, *, symbols=None, inline_expressions=True)
#
Render one entry as the bare line the document prints for it.
The line the whole-spec render prints for it — a named expression's
or a named condition's definition, a constraint, an sos: set, a piecewise:
curve, an assumption, or a variable's domain, quantifier included —
with no document, label, equation number or math delimiters around it, for
a math context the caller lays out: a docstring, a table cell. A line on
its own has no Definitions section beside it, so the plain named
expressions it uses are substituted unless inline_expressions says otherwise; a cased
one prints by symbol, and a second call with its name prints its definition.
| PARAMETER | DESCRIPTION |
|---|---|
spec
|
Anything |
name
|
A named expression, named condition, constraint,
TYPE:
|
fmt
|
What spells the math — a
TYPE:
|
symbols
|
How names print; see
TYPE:
|
inline_expressions
|
Substitute the plain named expressions the line uses, so it
stands on its own;
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
str
|
The line, math only. |
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
fmt names no format. |
LanguageError
|
A spec that does not compile; it does not print. |
SchemaError
|
name is declared as none of the seven, as two — a
constraint may share a variable's name — or under |
Source code in src/mathspec/_typesetting/__init__.py
mathspec.FormatName = Literal['latex', 'markdown', 'typst']
module-attribute
#
The name of an output format, as the command line takes it.
mathspec.SymbolTable(notation, indices=dict(), sets=dict(), names=dict())
dataclass
#
How a reader wants the spec to print — notation only, kept out of the spec.
Every entry is a spelling, printed verbatim. notation: says which
language they are written in, and a render in the other one refuses::
notation: latex
dimensions:
snapshot: {index: t, set: "\\mathcal{T}"}
plant: {index: n}
names:
marginal_cost: "c^{\\mathrm{marg}}"
An entry naming nothing in the spec is an error naming the near miss.
| ATTRIBUTE | DESCRIPTION |
|---|---|
notation |
The language the entries are written in;
TYPE:
|
indices = field(default_factory=dict)
class-attribute
instance-attribute
#
names = field(default_factory=dict)
class-attribute
instance-attribute
#
notation
instance-attribute
#
sets = field(default_factory=dict)
class-attribute
instance-attribute
#
checked_against(program)
#
Reject entries naming nothing in program or in what its formulations state, with the near miss.
A name a piecewise: or sos: entry emits counts as declared, so
one table spells both readings of a spec: the entries as the file states
them, and the rows expand writes out.
Source code in src/mathspec/_typesetting/symbols.py
load(source)
classmethod
#
A table from a YAML path or the mapping it parses to.
| RAISES | DESCRIPTION |
|---|---|
SchemaError
|
An unknown section, a section or a dimension that is
not a mapping, or a |
Source code in src/mathspec/_typesetting/symbols.py
advice#
advice returns a tuple of Advice,
one for each piece of advice.
mathspec.advice(spec)
#
Everything the language advises about spec, decided without data.
Advice is a note, not a refusal: a file with advice still loads.
| PARAMETER | DESCRIPTION |
|---|---|
spec
|
| RETURNS | DESCRIPTION |
|---|---|
Advice
|
The never-an-axis advice sorted by dimension name, then one note per |
...
|
entry the program reads and does not build, then one per variable |
tuple[Advice, ...]
|
whose |
tuple[Advice, ...]
|
unboundedness advice; |
| RAISES | DESCRIPTION |
|---|---|
LanguageError
|
spec does not load; |
FileNotFoundError
|
A |
Source code in src/mathspec/_advising.py
Errors#
mathspec.errors
#
What the language raises: the error tree, and the one wording a consumer's own refusals share.
MathSpecError
#
Bases: ValueError
Base class for every error this package raises on purpose.
LanguageError
#
Bases: MathSpecError
The spec is not sayable in the language, or does not obey its rules.
SchemaError
#
Bases: LanguageError
What a load refuses: an unknown key, a bad dtype, a duplicate YAML key, an unparseable or unresolvable expression.
DimensionError
#
Bases: LanguageError
A dim-set rule was violated. Raised at load time, before any data.
did_you_mean(name, known, *, label='Declared', listing=True)
#
The repair clause for an unrecognised name: the near miss, or the set, or nothing where listing is off.
Source code in src/mathspec/errors.py
unordered(context, construct, dimension)
#
The refusal for construct reading the order of dimension, which is not declared ordered.
Source code in src/mathspec/errors.py
schema_error(exc)
#
A pydantic ValidationError as one of ours.
Returns the original LanguageError subclass where exactly one
error carries one, and a SchemaError otherwise.
Source code in src/mathspec/errors.py
prefixed(context, e)
#
case_context(name, label)
#
The context an error inside one arm of a cased expression is reported under.
| PARAMETER | DESCRIPTION |
|---|---|
name
|
The named expression the arm belongs to.
TYPE:
|
label
|
The case's name, or
TYPE:
|