math_spec.typeset.symbols
Which symbol each declared name prints as — and the sidecar that overrides it.
Derivation aims at unambiguous, not beautiful: it runs with no setup, so it
has to be right rather than elegant. :class:SymbolTable is where a reader
makes it conventional, in a file of its own — presentation is not language, so
it never becomes keys on Model. What a declaration is travels the other
way: description: is a key on the declaration, because it is the model
talking about itself rather than a reader choosing notation.
This module decides which symbol a name gets; a
:class:~math_spec.typeset.format.Format decides how it is written.
SymbolTable(notation, indices=dict(), sets=dict(), names=dict())
dataclass
#
How a reader wants the model to print — kept out of the model.
Presentation is not language: nothing here changes what the file means, no
lane reads it, and a model with no table still renders. Notation is all it
carries — what a declaration is is the model's own description:,
which travels with the declaration and reaches every consumer.
Every entry is a spelling, printed verbatim — nothing parses or translates
notation. 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}}"
Deliberately strict — an unrecognised name is an error naming the near miss, the failure mode of a silent typo being a symbol that never applies and a reader who never finds out.
| 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(schema)
#
Reject entries naming nothing in schema, with the near miss.
Source code in src/math_spec/typeset/symbols.py
load(source)
classmethod
#
A table from a YAML path or the mapping it parses to.
| RAISES | DESCRIPTION |
|---|---|
SchemaError
|
An unknown section, a malformed dimension, or a
|
Source code in src/math_spec/typeset/symbols.py
Symbols(schema, fmt, table, chosen=frozenset())
#
How every declared name prints: overrides first, derivation for the rest.
Assignment order is load-bearing. Name symbols settle before dimension
indices, so an index can be kept off a letter a variable owns — derived
independently, a model with a dimension plant and a variable p
renders p_{t,p} and no reader can tell which p is which. Only
single-letter name symbols are kept off the index letters, a
\mathit{load} never colliding with a t.
Which now means variables, since a parameter is upright: a dimension
may take p beside a parameter p, because \mathrm{p} and p
are not the same symbol on the page. The guard shrank to exactly the
collisions that are still collisions.
| RAISES | DESCRIPTION |
|---|---|
SchemaError
|
If table is written in a notation fmt does not read. |
Source code in src/math_spec/typeset/symbols.py
index = {}
instance-attribute
#
name = {name: table.names[name] if name in table.names else _derive_name_symbol(name, declared, fmt, given=name not in schema.variables and name not in chosen) for name in (*schema.parameters, *schema.variables, *printed)}
instance-attribute
#
overridden = frozenset(table.names) & {*schema.parameters, *schema.variables}
instance-attribute
#
set = {}
instance-attribute
#
printed_expressions(schema)
#
The named expressions that reach the page under their own name.
A named expression is substituted where it is used, so it normally prints nothing a symbol could stand for. A cased one is the exception: its value is defined by region, which reads as a definition of its own and is referred to by name from the equations that use it.