simplify_branches
Stable function · Differentiate a model
Tier: stable · Kind: function · Topic: Differentiate a model
| Julia | Python | Rust |
|---|---|---|
simplify_branches | simplify_branches | simplify_branches |
Julia
simplify_branches(e::EarthSciAST.ASTExpr)
simplify_branches(e::ASTExpr) -> ASTExpr
Conditional-specific simplification, complementing EarthSciAST.simplify:
ifelse(lit, a, b)→a(lit ≠ 0) orb(lit == 0);ifelse(c, a, a)→awhen the branches are structurally equal;- same-condition pruning along a path: inside the true branch of
ifelse(c, …)any nestedifelse(c, a₂, b₂)collapses toa₂, inside the false branch tob₂(conditions compared structurally).
Bottom-up; nodes are rebuilt only where something changed.
STRUCTURAL EQUALITY, AND ITS COST. Conditions and branches are compared by
structure, and the pass asks for that comparison at every ifelse node it
meets. Doing it with skey — a full re-serialization of the subtree
— makes the pass Θ(n·depth): each of the k levels of an index(makearray…)
region chain re-serializes the whole chain below it, and the product rule
replicates such chains along a path. The
comparisons therefore go through hashcons.jl: a shash mismatch —
O(1) per node — settles the common case where the two differ, and only a
match pays for the exact answer from StructIndex, whose bottom-up
interning keys a node from its own shell plus its children’s ids (Θ(n) for
the tree, O(1) per compare) and memoizes on node identity, so the
identity-preserving rewrites below re-key nothing they did not change. Same
equality relation as skey, so the pass is unchanged.
The second Θ(n·depth) term is _assume, which re-descends a branch looking
for a condition that is usually not there at all. A running count of the
conditions the bottom-up pass has already built decides that in O(1) at the
branch, so a k-level chain costs Θ(n) instead of Θ(n·k); see _sbr.
Python
simplify_branches(e: Expr) -> Expr
Literal-condition fold, equal-branch collapse, same-condition pruning.
Rust
pub fn simplify_branches(e: &Expr) -> Expr
ifelse-aware simplification, the swell control for coefficients of
limiter-heavy schemes: equal branches collapse and same-condition tests
are pruned.
Conditions and branches are compared by structure at every ifelse the
pass meets, so the comparison must not cost the subtree’s size (a
limiter nests its tests, and each level would re-serialize everything
below it). As in the reference (simplify_branches.jl): a structural hash
(StructHash) settles the common unequal case in one compare, a match
is confirmed by structural id (StructIndex), the rewrites keep every
unchanged node (map_children_shared) so the identity memos of both
see each node once, and a census of the conditions already built skips
the same-condition descent when there is nothing to prune.