math_spec.degree
Degree — the one admissibility rule that is a scope choice (docs/about/ceiling.md).
Degree 2 in the math, degree 1 in what stands beside it. An objective and a
constraint both take variable * variable; a bound and a piecewise:
link do not — each of those is read affinely. An expressions: entry is not
degree-checked at declaration at all: the math reading it is checked where it
reads, at that position's own ceiling, and an entry the math never reads
(ExpressionDeclaration.in_math) is held to no degree.
A degree-2 product has a second rule: at most one factor may be a sum of
terms. sum(x, over=i) * sum(y, over=j) is a cross join whose size the
file states nowhere. Factors carrying different dims are not that: x[i] *
y[j] broadcasts.
A divisor's shape is decided here too: a quotient is multiplication by one reciprocal factor, so a divisor that adds is refused at load, where the message can name the rewrite.
calls_dual(node)
#
Whether a :class:DualNode stands anywhere in the resolved node.
Asked of the expanded tree, so a dual inlined through a macro or a
named expression is caught alongside one written in place — the whole
point of enforcing the placement rule after expansion rather than at the
call site.
Source code in src/math_spec/degree.py
carries_variable(node)
#
Whether node contains a decision variable, over the core AST.
:func:math_spec.program.carries_variable answers the same question over a
program. An unresolved node reaching here is a resolution bug, so it is refused
rather than silently answered.
Source code in src/math_spec/degree.py
check_binary(node, context, *, ceiling)
#
Check that node stays inside the degree its position allows.
| PARAMETER | DESCRIPTION |
|---|---|
node
|
The product, quotient or sum to judge.
TYPE:
|
context
|
What to name in the message — the declaration being read.
TYPE:
|
ceiling
|
The highest degree this position can honour — 2 in an objective or a constraint, 1 everywhere else.
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
LanguageError
|
A product of two variable-carrying factors where the position allows only degree 1 or where both factors are sums of terms, a power over anything carrying a variable, a divisor carrying a variable or adding. |
Source code in src/math_spec/degree.py
check_expression(node, context, *, ceiling=1)
#
Apply :func:check_binary everywhere in node.
Degree only, deliberately: what a plan node can represent is a consuming lane's question.
Source code in src/math_spec/degree.py
dual_in_math_message(context)
#
Why dual() is refused where the math is built — a placement rule, not a degree.