math_spec.piecewise
Expand piecewise: blocks into plain variables and constraints.
A block becomes ordinary affine declarations before anything reads the model,
under names prefixed with the block's own; what each method emits is tabled in
docs/reference/language/piecewise.md. Everything the language decides
about a block against its model is decided once, in :func:check, and the
emitters write rows from the facts it settled. A refusal names the link or key
the file wrote rather than an emitted declaration.
ASSUMED = ('complete', 'increasing', 'curvature', 'breakpoints', 'contiguous')
module-attribute
#
GateRow = tuple[str, str | None, str]
module-attribute
#
Curve(name, block, rows, mask, reads, gates, names)
dataclass
#
One piecewise: block held to its model: every fact the rows it writes read.
:func:check is the only thing that builds one, so holding one is the
proof that the block is inside the language, and nothing after it decides
anything.
| ATTRIBUTE | DESCRIPTION |
|---|---|
name |
The block's key.
TYPE:
|
block |
The block as written.
TYPE:
|
rows |
Each link's row frame, in link order — |
mask |
The block's
TYPE:
|
reads |
Whether each walked link reads the |
gates |
The rows the weights sum under, one or two. |
names |
Every name the expansion writes.
TYPE:
|
CurveMask(block, resolved)
#
A block's where:, as each shape of row the expansion writes reads it.
Built from the block and its resolved mask, to answer the one question the expansion asks of it: whether it reads the breakpoint dim. Such a where is ragged — it says how far each curve runs, not only which curves exist — so a row over the frame and the breakpoint dim takes it as written, the rows on a curve's edges shift it, and a row over the frame alone, which cannot read that dim, takes the count of breakpoints it admits. A where over the frame alone reaches every row as written.
Source code in src/math_spec/piecewise.py
along = block.along
instance-attribute
#
dims = resolved.dims if resolved is not None else frozenset()
instance-attribute
#
exists
property
#
What a row over the frame alone takes: the where, or the count of breakpoints a ragged one admits.
frame
property
#
The where as a row over the frame and the breakpoint dim conjoins it onto a position test — none where ragged.
ragged
property
#
Whether the where reads the breakpoint dim, and so says how far each curve runs.
text = block.where
instance-attribute
#
edge(end)
#
The first or last breakpoint of each curve: where the mask holds and does not one step outward.
The vacated edge of a shift in a where is false, which is what
makes the head and the tail of the axis their own edge.
Source code in src/math_spec/piecewise.py
interior()
#
Where a breakpoint has one on either side: the rows a claim about a bend is true of.
Source code in src/math_spec/piecewise.py
neighbours()
#
Where a breakpoint and the one before it are both there: the rows a claim about a segment is true of.
Names(name, weights, convexity, chord, domain_lo, domain_hi, links, sos)
dataclass
#
Every name one block's expansion writes, spelled once for the emitters and the collision check.
Every name is reserved whichever method the block declares: which method
writes which is the method's business, and a collision is the file's
either way. sos holds the names a method that states a set writes
through :func:math_spec.sos.emit.
by_kind
property
#
Each name by the kind of declaration it would collide with.
chord
instance-attribute
#
convexity
instance-attribute
#
domain_hi
instance-attribute
#
domain_lo
instance-attribute
#
links
instance-attribute
#
name
instance-attribute
#
reused
property
#
Each link row whose name the block's own rows or variables already take.
sos
instance-attribute
#
ungated
property
#
The second gate row, where the gate variable does not exist.
weights
instance-attribute
#
of(name, links)
classmethod
#
The names block name writes, a link's row named after the link.
Source code in src/math_spec/piecewise.py
assumptions_of(name, block, where, reads)
#
What block assumes of its numbers, by the name the document prints and a refusal quotes.
Every curve assumes its breakpoints are there: a missing parameter row is
not absence, it is a zero, so an undeclared breakpoint sits the curve on
the origin rather than shortening it. A walked link's breakpoints are over
its own rows, so each is asked of the rows that link reads the curve at,
under a name of its own; reads says, by link, whether that link reads the
where: through its relation (:func:walk_reads). A curve has an x-axis only where two
links tie it, so the increasing condition — and the shape it is checked
with — exist only there; lp alone needs a segment to state a line for;
a ragged where: must mark one run.
Read off the block rather than off an expansion, so a model states what it
assumes whether or not its curves have been written out. Each condition is
a where string over the parameters the file declared: the expansion writes
them into assumptions:, and a model that still declares the block
derives the same text at load. Each is asked only where a curve runs, so
the where: goes into every one of them: a model written out and read
back holds the data to what the block did.
Source code in src/math_spec/piecewise.py
check(schema, name, block)
#
block held to everything the language decides about it against its model, as the facts its rows read.
What the block names by key — dimensions, parameters, relations, the gate
— and the names it writes are checked as the file loads, with every other
cross-declaration rule (:class:~math_spec.model.Spec); the link
expressions and the where are typed with the rest of the model
(:attr:~math_spec.model.Spec.resolved), so a fault in one is named
against the link there. What is left is what needs those typed forms:
each link's row, that each link's expression and values fit it, and that
the where: fits dims:.
| RAISES | DESCRIPTION |
|---|---|
PiecewiseExpansionError
|
A link that does not fit its row, or a where
outside |
Source code in src/math_spec/piecewise.py
declaration_of(block, where=None)
#
The curve of one expanded block, as a program carries it.
| PARAMETER | DESCRIPTION |
|---|---|
block
|
The block as written.
TYPE:
|
where
|
Which coordinates of the frame have a curve, lowered — and so which ones what the block assumes is asked at.
TYPE:
|
Source code in src/math_spec/piecewise.py
expand_piecewise(schema)
#
schema with every piecewise: block written out — schema itself where it declares none.
A method: adjacency block states its restriction as the set
method: sos2 states, and then that set is written out here too: the
binaries are what the method is, so the model that comes back carries no
set of its own (:func:math_spec.sos.emit is where they are spelled).
| RAISES | DESCRIPTION |
|---|---|
PiecewiseExpansionError
|
A block :func: |
Source code in src/math_spec/piecewise.py
through(text, link, *, reads)
#
text as a link's row reads it: through the link's relation where it reads so, else as written.
Source code in src/math_spec/piecewise.py
walk_reads(schema, name, block, where)
#
Whether each walked link reads the block's where: through its relation, by link.
A walked row is over the dims the walk produces, where a mask over the
ones it consumes cannot be read as written. Read through the relation it
can, as at reads it, when the mask carries every dim the walk consumes
or joins on. A mask carrying none of them is over dims the row keeps, and
reads as written.
| RAISES | DESCRIPTION |
|---|---|
PiecewiseExpansionError
|
A mask carrying some of the dims a walk reads through and not the rest. |