Repository navigation
refactor(stage1-pass2): rollup from the finest common group, readout requirements, dead-candidate elimination, chain groups (#1207 PR 4) - #1234
Draft
zzylol wants to merge 1 commit into
Conversation
zzylol
force-pushed
the
refactor/1207-pass1
branch
from
November 7, 2026 04:14
d4bde07 to
441f3a9
Compare
zzylol
force-pushed
the
refactor/1207-pass2
branch
from
November 7, 2026 05:10
72a4037 to
24dd00c
Compare
zzylol
force-pushed
the
refactor/1207-pass1
branch
from
November 9, 2026 06:37
2c6d993 to
61f585a
Compare
…requirements, dead-candidate elimination, chain groups (#1207 PR 4) Pass 2 runs, in order: the general rollup rule with one synthesized finest common group per cluster of equal definitions (replaces scan widening, finer-aggregate reuse and the rollup rules); top-k reuse; reach, caps and readout requirements (one readout candidate per requirement level, written with Memo::set_input_requirements); dead-candidate elimination with every root cause (PrunedLogicalCandidate); chain groups SummaryTumblingWindowChain[w](X) for the surviving state groups, widths from the gcd closure of the reaching queries' grids, the window and the offsets; and the logical edges between survivors. The summary-input and window-rollup rules and the local-window-composition step are deleted. - types: LogicalRequirements::error_propagation(memo, consumer, metric) with the constant contracts (key-only Filter by column lineage, abs / clamp / negation, min / max / avg / count, + - / *), b = 0.1 private; AccuracyMetric::ALL; RootPruneReason::HeapSmallerThanTopK; a candidate's input requirements are part of its identity in add_candidate; summary coverage accessors no longer test-only; origins SummaryInput and WidenedScans deleted. - accuracy: theoretical_guarantee at a failure probability (KLL and KMV evaluated at it, others checked against their own), producer_satisfies_logical_requirements returns the failing root reason, readout_metric; node-tree composition, propagation, budget split, function rules, PropagationStats, test_support and the test-only sizing deleted. - devtools: one pass2 stage.
zzylol
force-pushed
the
refactor/1207-pass2
branch
from
November 9, 2026 07:11
bdf0888 to
bcae9e5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #1232 (
refactor/1207-pass1, PR 3). Part of the #1207 merge unit: do not merge on its own.Why
#1207's Order, row "4. Pass 2": the reuse rules over memo groups, each readout's required accuracy, dead-candidate elimination with root causes, chain groups and the logical edges$(u,c,i)$ with $\alpha^{\log}$ , in the order decided on 2026-11-07 and the accuracy design of 2026-11-08 (no θ floors: a readout input carries $\alpha^{\log}$ = guarantee(summary type, θ_u, statistic) at the required δ ≤ required ε). Concepts doc §3 "Stage 1, Pass 2" and §4.
RequiredAccuracy, andWhat
Pass 2 (
generate_logical_asap_memo_candidates(pass1, entries, evidence)) now runs these steps:rules/rollup.rsadd_rollup_candidatesSummaryMerge(group_by)for states,sum/min/maxfor finalized sums, counts, minima, maxima; one synthesized finest common grouprules/topk.rsrequirements.rserror_propagation; each sketch readout gets one candidate per requirement level (single-read query: the cap; composed query: the ε grid × δ grid not looser than the cap and per-value δ)dead_candidates.rsLogicalASAPMemoCandidates::prunedlists each with every root cause (one shortest path per failing edge)rules/chains.rsSummaryTumblingWindowChain[w](X)per width (gcd closure ofTimeShift/TimeRangegroups,SummaryMergein the state group;@ Treuses existing chains only;@ end()/@ start()nonelogical_memo_candidates.rsproducer_satisfies_logical_requirements;evaluation_grid_of_group(gcd of the reaching queries' grids)Deleted (replaced, no shims)
memo/rules/{scan_labels,summary_inputs,finer_aggregate,rollup}.rs,memo/window_candidates.rs,memo.rsTimeRangepass2_local_window_composition,pass2_after_local_window_composition(pub)generate_logical_asap_memo_candidates(chains run after the reach now, so there is no "rule 1 first" stage); devtools prints onepass2stageOriginOfCandidateForMemoGroup::{SummaryInput, WidenedScans}Pass2RuleError::{InvalidGroupReference, TooManyGroups}Group,Candidate,LogicalPropertiesvariants for rule bugsasap_accuracy::{composition, propagation}(node-tree guarantee composition and propagation),budget::per_input_target,function_rules,evidence::PropagationStats,test_supportand thetest-supportfeature (and its three dev-dep uses)LogicalRequirements::error_propagation+ readout requirements (the user agreed 2026-11-06 that node-treebind_guaranteesgoes in PR 4)estimators::size_params,kll::{kll_k,size_params},ddsketch::size_params,cms::{cms_width,cms_depth},cardinality::kmv_k,count_sketch::{count_sketch_width,count_sketch_depth},hll::hll_precision,univmon::{l2_shape,distinct_heap,distinct_chebyshev,size_params},topk_capacity,saturating_ceiland the tests built on themevery_listed_parameters_has_a_guarantee_at_one_percent)The concepts doc already describes this design; it is not changed. The pending items below are not in it yet (added once approved).
Pending approval (new or changed pub items not in the doc)
P1.
error_propagationtakes the memo. The doc's signature is(consumer, metric); the key-onlyFiltercontract (E1(b)) must read the input group's column lineage, which only the memo has.Example: over the readout group R of
quantile by (job)(latency)(columns[job: SourceColumn(latency.job), value: Computed]),Filter(job = "api", R)givesSome { factor_per_input: [1.0], .. }in every metric;Filter(value > 0.5, R)givesNone(it compares the approximate estimate). Alternative: keep the doc signature and have the caller decide filters (two places decide contracts).P2.
producer_satisfies_logical_requirementsreturns the failing reason.Example: KLL k = 26 into the p99 readout requiring relative 0.02 gives
Err(BelowRequiredAccuracy { consumer: G4#2, input: 0, required: relative 0.02 δ 1 });LogicalEdge::satisfies_logical_requirementis.is_ok(). Pass 2's pruned list needs the reason; a bool plus a second function would decide it twice.P3.
RootPruneReason::HeapSmallerThanTopK. The doc's α^log includes "a top-k's heap holds k", but none of its three root reasons names that failure, which happens also without a requirement (accuracy not enforced).Example:
topk(50, …)overCmsWithHeap: the 56 builds with heap 10 or 20 are pruned withHeapSmallerThanTopK { k: 50 }(testa_heap_smaller_than_k_is_pruned).P4.
asap_accuracy::readout_metric.Example:
(Sketch(Kll), Quantile{0.5})→Rank;(Sketch(DDSketch), Quantile{0.5})→Relative;(ExactAggregate(..), _)→None. Used by step 3 (the metric a readout's levels are in) and by the metric rule (a readout's producer metric).P5.
AccuracyMetric::ALL: [AccuracyMetric; 5](ABSOLUTE,ABSOLUTE_STREAM_L1,ABSOLUTE_STREAM_L2,Relative,Rank): caps for a target that names no metric, andconsumer_carriesofMetricRule.P6.
SummaryCoverage::definition(),SummaryCoverage::selection(),SelectionBox::columns()are public (were test-support only): the rollup rule reads them.Design questions (conservative choice taken; please decide)
Q1. A readout over a merge. The doc checks a readout's requirement against θ_u, but a rollup or chain merge candidate has no θ (
LogicalProperties::newrejects θ on a merge). Taken: α^log(merge u → readout r) holds only when every θ the merge may carry (the builds below it, throughFilter/TimeRange/TimeShift/SummaryMergegroups) meets r's requirement and the summary type's merged error isExactorAsIfBuiltOverUnion. Safe, but a chain with weak builds blocks the tight levels. Proposal: a merge (and the window-selectingTimeRange/TimeShiftover a chain) carries the θ of the states it reads — one candidate per θ,LogicalProperties { parameters }allowed onSummaryMerge— and the build → merge edge requires equal θ. Example: chain Gw overlatencywith KLL k ∈ {269, 547}; S's merge readsTimeRange(5m, Gw); readout at rank 0.005 (needs k ≥ 547): today the merge edge fails (269 is below); with the proposalSummaryMerge[k=547]passes andSummaryMerge[k=269]fails.Q2. Metric rule without targets. Taken: the metric rule applies to an edge only when a query with an accuracy target reaches the consumer; with accuracy not enforced every edge passes (test
without_targets_every_edge_is_admissible), matching "(K) has no rows".Q3. Composed query. Taken: a query is composed when a candidate it reaches has two or more inputs below which a readout group lies (a ratio); readouts of one value by different summary types are alternatives, not a composition.
Q4. Levels at the edges of the grid. Taken: when no grid level is within the cap (exact target, cap 0) the readout gets one level at (cap, δ); a whole-result δ with$n_q$ unknown gives per-value δ 0 (no sketch meets it).
Q5. Finest common group construction. Taken: $G^$ is built over the rows of a member whose selection equals the union; a new
Scanof the union of label sets is not built, so{job="a"}with{job="b"}gets no $G^$ (scan widening, R7, not folded in). Members groupedwithoutkeys or per entity are not rolled up. Interval constraints (time window, value ranges) must be equal within a cluster.Q6. Chain builds. Taken: a chain group gets one build per θ of the state group's surviving builds (union over the state groups sharing it).
How
stages/candidates.rs): the constant error contracts inerror_propagation;RELATIVE_OPERAND_VALIDITY_CAP = 0.1private;add_candidatetreats input requirements as part of a candidate's identity (the doc: two readouts with different requirements are different candidates).theoretical_guaranteeevaluates KLL (rank error scaled below δ = 0.01) and KMV (bisection on ε) at the required δ, and checks every other algorithm's own failure probability against it;producer_satisfies_logical_requirementsapplies the readout rule (every carried θ, heap ≥ k) or the metric rule (output_metricsbottom up, cached per group).find_or_add_group/add_candidate, and swallow onlyOutputDiffersFromGroup.Key code interfaces added / modified
crates/stage1-pass2-reuse-candidates/src/lib.rs,logical_memo_candidates.rs,rules.rscrates/types/src/stages/candidates.rs,logical_memo_candidates.rs,ir/properties/accuracy.rscrates/accuracy/src/model.rs,estimators/mod.rsUsage (end to end; the test
dead_candidates_are_pruned_and_listed_before_chain_groupsat bcae9e5):Major algorithm changes
Rollup. Problem: three rules (scan widening, finer aggregate, rollup) each matched their own shapes by column name; no group finer than every member was ever built. Before: rule 2 widened scans, rule 5 read a finer SQL result, rule 6 merged a finer state, each pairwise. After: (1) cluster aggregate groups by coverage definition without keys (a$G^*$ = union selection, keys ∪ narrowing columns, built over a member's rows; (3) every ordered pair gets $G_f$ 's keys, whose rows each combine all raw rows of one key. Complexity: O(groups²) per cluster. Tests:
Scaninput normalized) and equal intervals; (2) per cluster,Rollup(by keys)(Filter(compensation, G_f))when keys ⊆, selection ⊆ on keys by lineage. Correctness: a compensation reads onlya_filtered_coarse_sketch_state_merges_the_finer_states_through_a_compensating_filter,a_finest_common_group_no_query_asks_for_serves_both,a_narrowing_on_a_column_that_is_no_key_gives_no_rollup,a_coarse_exact_sum_rolls_up_the_finer_sum.Readout requirements and dead candidates. Problem: θ floors per input (Pass 1 heap floor, Pass 2 cap floors) mixed ε and δ and could not express multi-readout allocation. After: caps top down ($\alpha^{\log}$ per edge, then elimination to a fixpoint and BFS traces. Correctness: a pruned candidate has no edge to any live consumer, so no plan can use it. Tests:
caps), levels per readout (query_levels),dead_candidates_are_pruned_and_listed_before_chain_groups,a_single_readout_requires_the_query_target,a_whole_result_failure_probability_is_split_per_value,a_ratio_reads_no_rank_error.Chain groups. Problem: tumbling layouts were a property; widths came only from queries reaching a state through Stage 0 expressions, offsets were ignored. After: range-free chain groups after the reach, widths include offsets (
e3_*,e2_*,an_absolute_anchor_reuses_only_existing_chains,no_chain_without_a_merge_an_anchor_or_a_grid).Before / After
Before (PR 3 head): Pass 2's rules and edges were
todo!(); every planning run stopped there. After: Pass 2 producesLogicalASAPMemoCandidates(memo, edges, pruned, evaluation grids); planning stops at Stage 2 (todo!of PR 5).Example (concepts doc "ratio of quantiles", test
dead_candidates_are_pruned_and_listed_before_chain_groups):quantile_over_time(0.99, m[5m]) / quantile_over_time(0.5, m[5m]), relative 0.05, every 60 s at phase 0. Pass 2 prunes both KLL readouts (MetricRule { producer_metric: Rank, consumer_carries: [Relative] }), every KLL build through them, and the DDSketch builds with alpha 0.1 and 0.05 (BelowRequiredAccuracy); each DDSketch readout group has five levels 0.02 … 0.001; one 60 s DDSketch chain with five builds.Representation, rules, enumeration
LogicalRequirements { required_accuracy }on readout inputs;LogicalASAPMemoCandidates { memo, edges, pruned, evaluation_grid_of_group }; chain groups in the memo.Self-review
add_candidatehelper in Pass 2 (swallows onlyOutputDiffersFromGroup), onereadout_metric, contracts only inerror_propagation, θ only inparameter_list(no strongest/weakest/floor tables).#[allow(dead_code)]added (the three existing ones inhll.rs/univmon.rsnow point to PR 8).docs/develop_docs/asap-aware-mapping-*.md,end-to-end-accuracy-guarantees.md) still describe node-tree propagation; they were already stale before this stack and are left for the PR 9 doc pass.planner-layering.md's Pass 2 rows are updated.Verification
cargo fmt --all,cargo clippy --workspace --all-features --all-targets -- -D warnings: clean.Test status at bcae9e5 (
cargo test -p <crate> --all-features, per crate)avgfrom Pass 1's memo: 3; OTHER: calledResult::unwrap()on anErrvalue: Error("invalid type: sequence, expected string or map", line: 0, column: 0): 1PR 3 (61f585a): 1167 / 188 / 9. By test name: no test that passes on PR 3 fails here; every failure stops at a later PR's
todo!()(PR 5 "physical expansion and physical edges", PR 6, PR 9) or was already failing. 26 new tests pass (21 Pass 2, 3 types, 2 accuracy); 39 tests are deleted with the code they tested:asap-accuracy'sbudget::tests(3),composition::tests(16),function_rules::tests(1),propagation::tests(1) and the test-only sizing tests (18:cms2,count_sketch3,hll2,kll4,estimators::parameter_list_is_the_sizing_over_the_error_grid,univmon4,sizing1), replaced byevery_listed_parameters_has_a_guarantee_at_one_percentanda_guarantee_is_evaluated_at_the_required_failure_probability.