Spec's tolerance-not-bit-identity caveat for filtered estimates is conservative #30

Closed
opened 2026-08-27 14:48:59 +00:00 by logaritmisk · 1 comment
Owner

The #19 design argued that filtered results agree only to tolerance rather than bit-identically, because the scratch slice inherits whichever event order the real slice happens to be in and greedy colouring over a permuted input can group differently. An experiment during implementation flipped filtered_step's color_groups_dirty from true to false — which genuinely switches the scratch between the grouped sweep (sweep_color_groups) and the sequential fallback across its entire convergence loop — and the ingestion-order invariance test stayed green. So even a full sweep-path switch agrees within 1e-8 under tight convergence (max_iter: 2_000, epsilon: 1e-12), because EP reaches the same fixed point regardless of sweep order once driven far enough. The caveat is not wrong, but it is more conservative than the code requires. Worth amending the spec.

Note on the flag itself: color_groups_dirty is load-bearing, not inert. iteration(0) with the flag true calls recompute_color_groups, which populates color_groups, so is_empty() is false and the grouped path runs on every iteration; with the flag false no recompute ever runs, the fresh ColorGroups stays empty, and the sequential fallback runs every iteration. Deleting it would silently downgrade the scratch to sequential-only and lose the rayon-parallel sweep above RAYON_THRESHOLD = 64.

The #19 design argued that filtered results agree only to tolerance rather than bit-identically, because the scratch slice inherits whichever event order the real slice happens to be in and greedy colouring over a permuted input can group differently. An experiment during implementation flipped `filtered_step`'s `color_groups_dirty` from `true` to `false` — which genuinely switches the scratch between the grouped sweep (`sweep_color_groups`) and the sequential fallback across its entire convergence loop — and the ingestion-order invariance test stayed green. So even a full sweep-path switch agrees within 1e-8 under tight convergence (`max_iter: 2_000`, `epsilon: 1e-12`), because EP reaches the same fixed point regardless of sweep order once driven far enough. The caveat is not wrong, but it is more conservative than the code requires. Worth amending the spec. Note on the flag itself: `color_groups_dirty` is load-bearing, not inert. `iteration(0)` with the flag `true` calls `recompute_color_groups`, which populates `color_groups`, so `is_empty()` is false and the grouped path runs on every iteration; with the flag `false` no recompute ever runs, the fresh `ColorGroups` stays empty, and the sequential fallback runs every iteration. Deleting it would silently downgrade the scratch to sequential-only and lose the rayon-parallel sweep above `RAYON_THRESHOLD = 64`.
Author
Owner

Spec amended in eeb43e3docs/superpowers/specs/2026-08-27-filtered-estimates-design.md, Risks.

The caveat is kept (it is not wrong) with the measurement recorded beside it: forcing the scratch onto the sequential sweep instead of the grouped one — a far larger perturbation than a permuted event order — still agrees within 1e-8 under max_iter: 2_000, epsilon: 1e-12, because EP reaches the same fixed point regardless of sweep order once driven far enough.

Also recorded there, since it is the thing a reader would otherwise take away: color_groups_dirty is load-bearing, not inert. With it true the scratch takes the grouped path on every iteration; with it false no recompute ever runs, the fresh ColorGroups stays empty, and the sequential fallback runs every iteration — diverging from the production sweep the scratch exists to mirror, and losing the rayon-parallel sweep above RAYON_THRESHOLD = 64.

Spec amended in `eeb43e3` — `docs/superpowers/specs/2026-08-27-filtered-estimates-design.md`, *Risks*. The caveat is kept (it is not wrong) with the measurement recorded beside it: forcing the scratch onto the sequential sweep instead of the grouped one — a far larger perturbation than a permuted event order — still agrees within `1e-8` under `max_iter: 2_000`, `epsilon: 1e-12`, because EP reaches the same fixed point regardless of sweep order once driven far enough. Also recorded there, since it is the thing a reader would otherwise take away: `color_groups_dirty` is **load-bearing**, not inert. With it `true` the scratch takes the grouped path on every iteration; with it `false` no recompute ever runs, the fresh `ColorGroups` stays empty, and the sequential fallback runs every iteration — diverging from the production sweep the scratch exists to mirror, and losing the rayon-parallel sweep above `RAYON_THRESHOLD = 64`.
logaritmisk added the docsnumerics labels 2026-09-07 13:53:34 +00:00
Sign in to join this conversation.