Algebra looks continuous and clean; decision trees look discrete and procedural. In practice, much of computational mathematics is a translation between the two: an expression defines a function; evaluating it under real machine constraints introduces cases, branches, and control flow. This investigation makes that translation explicit.
The quiet branching inside formulas#
Consider a piecewise definition:
\[ f(x) = \begin{cases} x^2 & \text{if } x \ge 0 \\ -x & \text{if } x < 0 \end{cases} \]On paper this is algebra. In a program it is already a decision tree with two leaves. Compilers, CAS systems, and automatic differentiation frameworks spend enormous effort managing such cases—singularities, domains, and numeric guards—often invisible in the textbook formula.
Expressions as DAGs; evaluation as trees#
An arithmetic expression is naturally a directed acyclic graph of operations. Evaluation order and short-circuiting turn parts of that graph into a tree of decisions:
(x ≥ 0)?
/ \
square neg
| |
x xThe same idea scales. Gaussian elimination is a sequence of pivot decisions. Simplex methods branch on entering variables. Piecewise-polynomial models in statistics are forests of local algebras.
A minimal example#
def f(x: float) -> float:
# Algebra as control flow
if x >= 0:
return x * x
return -x
def f_as_tree(x: float) -> float:
"""Same function, annotated as an explicit tree walk."""
node = ("cmp", "x>=0",
("op", "square", "x"),
("op", "neg", "x"))
kind, *rest = node
if kind == "cmp":
_, true_branch, false_branch = rest
branch = true_branch if x >= 0 else false_branch
return eval_leaf(branch, x)
raise ValueError("unknown node")
def eval_leaf(node, x):
_, op, _ = node
return x * x if op == "square" else -xThe algebra did not disappear; it was scheduled.
Why the translation matters#
Verification#
Proofs about floating-point programs must reason about branches. Interval arithmetic and abstract interpretation are, in part, algebra over sets with join operations at merge points—decision structure again.
Machine learning#
Gradient-boosted decision trees and mixture-of-experts models make the dualism obvious: each leaf holds a simple algebraic model; the tree allocates inputs to leaves. Neural networks hide the branching in continuous gates, but routing and sparsity research keeps rediscovering discrete decisions.
Human understanding#
Experts often think in cases (“if the matrix is singular…”, “if the market is in regime B…”). Writing only the closed form can conceal the real algorithm.
flowchart TD
A[Symbolic expression] --> B{Domain / guards}
B -->|case 1| C[Local algebra]
B -->|case 2| D[Local algebra]
C --> E[Numeric evaluation]
D --> E
E --> F[Result / proof obligation]
A small formal view#
Let \(\mathcal{E}\) be a set of expressions and \(\mathcal{T}\) a set of decision trees whose leaves are expressions in a weaker fragment (for example, polynomials). A lowering map \(L: \mathcal{E} \to \mathcal{T}\) is correct when for all inputs \(x\) in the intended domain:
\[ [\![e]\!](x) = [\![L(e)]\!](x) \]where \([\![\cdot]\!]\) denotes denotational evaluation. Compiler IRs, autodiff traces, and symbolic simplifiers are engineering approximations to such maps.
Closing position#
Treating algebra and decision trees as enemies misreads computation. Algebra specifies; trees schedule and guard. Seeing both at once is a practical skill for anyone who writes numerical code, designs learning systems, or tries to prove programs correct.
Notes and references#
Demonstration essay for layout and technical features (math, code, Mermaid). For production research, replace schematic claims with citations to compiler and ML literature appropriate to the specific lowering you study.