RegressionTree
Online VFDT-style decision tree partitioning context vectors. Each leaf carries a weighted-variance accumulator; audit leaves additionally track pos/neg sub-arms per candidate split and, every RegressionTreeConfig.splitPeriod observations, evaluate them against the Hoeffding bound to decide whether to convert themselves into a RegressionSplitNode.
Internal split nodes hold no live arm; subtree aggregates (rootSnapshot, the value fields on TreeSplitResult) are derived by combining descendants at snapshot/merge time. The hot update path therefore touches exactly one arm: the leaf the observation routes to. Under Concurrency.Strict this removes the root-arm serialization point that previously bottlenecked multi-threaded throughput.
Concurrency: leaf-arm updates run lock-free (the arms themselves honour concurrency). The split-conversion path; the only one that mutates tree structure; is serialised by a single per-tree lock, fired only every RegressionTreeConfig.splitPeriod observations per audit leaf. Pointer writes on the hot path are skipped when the child reference is unchanged, so the typical update is pure arm arithmetic.
Constructors
Properties
Functions
Walk to the leaf row resolves to.
Snapshot merge using only the immutable result. Falls through to the same rules as merge but the "other" side is a TreeNodeResult tree-of-results rather than a live RegressionTree.
Mean of the leaf row resolves to.
Render the tree as nested if (split) { ... } else { ... } text.
Live root node, for snapshotting.
Aggregate snapshot at the root; derived by walking leaves and any RegressionSplitNode.carryover aggregates. Under concurrent updates with active growth, pointer races at split-time can leak observations into orphaned sub-arms; this walk is therefore best-effort and may drift by a few ULPs of the configured workload under contention. Single-threaded runs are exact.
Fold an observation into the tree, possibly growing it.
RegressionTree
findLeaf
Walk to the leaf row resolves to.
mergeSnapshot
Snapshot merge using only the immutable result. Falls through to the same rules as merge but the "other" side is a TreeNodeResult tree-of-results rather than a live RegressionTree.
merge
Structurally merge other into this tree. other is consumed (its node references may be grafted into this tree) and must not be used afterwards.
Same split predicate: recurse on both children; internal aggregates are derived from leaves, so no per-split merge step is needed.
Both leaves: merge arms directly.
Self leaf, other split: adopt other's structure wholesale and fold self's leaf aggregate into the adopted subtree's leftmost leaf.
Self split, other leaf or different splits: keep self's structure and fold other's aggregate (recursively combined if other is a split) into self's leftmost leaf.
The "leftmost leaf" rule preserves the merged total weight but biases the un-routable observations into a single bucket; an honest fallback when the structures don't align.
nodeCount
predict
Mean of the leaf row resolves to.
prettyPrint
Render the tree as nested if (split) { ... } else { ... } text.
reset
rootNode
Live root node, for snapshotting.
rootSnapshot
Aggregate snapshot at the root; derived by walking leaves and any RegressionSplitNode.carryover aggregates. Under concurrent updates with active growth, pointer races at split-time can leak observations into orphaned sub-arms; this walk is therefore best-effort and may drift by a few ULPs of the configured workload under contention. Single-threaded runs are exact.
update
Fold an observation into the tree, possibly growing it.