Version: v0.5.0

simplify_branches

Stable function · Differentiate a model

Tier: stable · Kind: function · Topic: Differentiate a model

JuliaPythonRust
simplify_branchessimplify_branchessimplify_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) or b (lit == 0);
  • ifelse(c, a, a) → a when the branches are structurally equal;
  • same-condition pruning along a path: inside the true branch of ifelse(c, …) any nested ifelse(c, a₂, b₂) collapses to a₂, inside the false branch to b₂ (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.

Source

Python

simplify_branches(e: Expr) -> Expr

Literal-condition fold, equal-branch collapse, same-condition pruning.

Source

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.

Source · Rust docs