Repository navigation
01: Framework for retaining and combining partial calculation work - #103
mikenrafter wants to merge 17 commits into
Conversation
Lipponen & Tarvainen (2019), Peltola (2012). The 32-beat cap is an internal ESTIMATE rule, not a published threshold. Include synthetic input recipes and old/new measurements.
Lomb (1976), Scargle (1982), Press & Rybicki (1989). Shift the spectral origin to the first sample before forming trigonometric arguments; pin the unrounded power on synthetic epoch seconds.
Preserve Task Force (1996) and Welch (1967) formulas for finite inputs. Timestamp validity is an implementation guard, preventing endless segment walks and invalid integer conversions.
Nelson et al. (1979), Methods for cosinor-rhythmometry; Welford (1962) centered co-moments. A relative determinant gate replaces the absolute pivot test; preserve upstream significance policy.
Morton, Fitz-Clarke & Banister (1990); Neumaier (1974) compensated summation. Preserve weighting and anchors; pin changed last digits.
Banister et al. (1975); Morton et al. (1990); Neumaier (1974). Preserve EWMA formulas and bounded-prefix priming while matching the arithmetic of the later incremental path.
Karvonen (1957) supports reserve zones only. Duration credit is an internal ESTIMATE rule with low confidence; preserve cadence validation, median capping and tail credit.
Witting (1990); van Someren (1999); Welford (1962). Preserve batch profile sums and first-winner ties; centered variance changes last digits in IS and IV.
Task Force (1996); Welford (1962). Port centered NN, lag and bin moments into batch code and retain shared spectral jitter policy. Rejection and breathing-line exemptions remain internal ESTIMATE rules with low confidence.
Record synthetic old/new observations and freeze twelve batch-only cases before aggregator adoption. Pin unchanged batch timestamp-gap exclusion and circular near-tie selection as controls. Methods and internal-policy limits are documented with the results.
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Tip 🎯 Customize your risk assessments
✅ Automatic approvals, with your rules
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
|
@coderabbitai review |
Action not completed
|
Review updates
Inherited the review fixes from #102, including the spectral-clock and cosinor follow-ups in d059e6e. Dart 3.11.4 analysis clean; full initial fix pass 1,286 passed, 6 existing capture skips. All 58 current output-change cases pass after the follow-ups. This cumulative draft stays on main until #102 merges, then will be rebased to show its own changes and marked ready.
Depends on 00 / #102.
This is draft 01 of the split of #99. It targets
main, so its diff is cumulative and includes the preceding branches. Review this area in its final commit; merge the preceding PRs first, then rebase this branch before merging.Repeated calculations have no common way to retain partial work, merge adjacent slices or validate a saved summary. This adds slice-based aggregators, reusable summary structures and a law checker, with the arithmetic core they require.
What changes
Batch,Aggregator, composition, checkpoint envelopes and JSON number codecs.incremental_core.dart.Momentsimports itsRunningMoments; the same existing file also defines the integer histogram, fixed-grid spectral state and calculation cache.Existing metric entry points retain their parent behavior. Methods remain pure Dart with zero runtime dependencies. Welford 1962 and Chan, Golub and LeVeque 1983 support the moment formulas; Hyndman and Fan 1996 support the histogram's type-7 percentile rule. Source comments retain the citations. Missing observations remain absent.
Algebraic breakdown
The contract consumes mutable states. A combine joins adjacent slices in chronological order. Laws compare finished observations on fresh states, rather than requiring identical private states. Floating-point associativity is approximate, not a mathematical identity of IEEE doubles. For the rows marked ordered monoid, associativity and empty identity apply only with fixed parameters and valid ordered input. Commutativity is not promised by the interface.
Batch,ListBatch,DoubleColumn,RowCodecaggregator_core_test.dart; no numeric tolerance.Aggregator,fold,run,.map,_MappedAggregatorS;empty()laws_harness_test.dartcatches broken identities, associativity, seams, slicing and impure finish.both,Pair,_BothAggregator,_CheckpointValidatedAggregatorCountCountFiniteCountWhereSum_SumStatesum and compensation; zerosprimitives_test.dartandsum_of_test.dart; the primitive law comparator uses absolute1e-6plus relative1e-12. Exceptional IEEE values use explicit semantic equality.SumOf1e-6plus relative1e-12.SumSq1e-6plus relative1e-12.Min,MaxRunningMoments,Momentsmax(1e-9, abs(expected)*1e-8)inincremental_compare.dart; later property laws add commutativity tests.First,Last_EdgeStatewith optional one-row batch; emptyLastRows(k),_RowsStatelast_rows_test.dart; exact row equality with NaN-aware comparisons where needed.GroupBygroup_by_test.dartchecks disjoint and recurring keys, identity and association with child equality.Lookback(k),_LookbackStatelookback_test.dartchecks empty/tiny slices, association, singleton and sliced paths; integer examples exact. Copies cost O(k) per seam.Affine,Ewma_AffineStatecount, scale, offset; identity mapAffine. Ordered, noncommutative monoid algebraically.ewma_prefix_test.dartchecks composition and laws, affine relative1e-12plus absolute1e-15; prefix numeric comparisons use their explicit1e-12/1e-9comparators.Prefix(k, head, tail),_PrefixStateIntHistogramint_histogram_test.dartcompares against expanded sorted inputs exactly, checks merging/removal and decoder refusal.IncrementalLombScarglesyncverifies a growing prefix and accumulates new points, rebuilding on edits; finish reconstructs PSD. Checkpointed ordered fold, not a monoid.lomb_scargle_test.dartchecks prefix parity, restart and work counters usingmax(1e-9, abs(expected)*1e-8); precision tests check time-origin stability.CalculationCache,_CalculationEntryevaluate(key, dependencies, calculate); finish is returned result. Dependency memoization, not an accumulator monoid.CalculationMode; the source is present here because it shares the core file. No new metric is defined.LawViolation,ConversionFailure,_Lcg, law/property supportThe common law set is left/right identity, split equivalence, associativity, singleton and sliced folding, pure finish and supported checkpoint round trips. The law checker does not assert commutativity generically. Commutativity of moments and histograms is checked explicitly by the later cross-area property file. Tolerances are fixture acceptance comparisons, not universal error bounds.
SumandSumOfrequire finite partial sums for chunk invariance; overflow can make IEEE results depend on chunking.Where the speedup comes from
Edge calculates the growing night again at each roughly 15-minute sync: first 15 minutes, then 30, until the last sync covers eight hours. Each batch call costs more as the night grows, so 32 syncs replay 528 chunks of history. Retained state folds each new chunk once and revisits the unfinished tail, moving reusable calculation work from roughly quadratic to roughly linear over the night. Checking old inputs, copying results and rescoring a whole night still cost work. The app gets these paths when area 06 and Edge #657 adopt and retain the states.
I measured generated data only, using AOT on Linux aarch64 with Dart 3.11.4, at least five full schedules per case after warmup; these totals sum the family medians.
The 30,000-beat micro-benchmark measures one HRV pass: its historical 4,956 µs batch, 1,281 µs composed, and 639 µs hand loop compare implementations of that one pass. The hand loop is cheaper than composition, but that comparison does not measure the repeated history that streams avoid across syncs. This framework supplies the operations; its own direct contribution in this workload is 0 s. Later PRs supply the retained calculations, and #102 already contains measured batch changes, so the #102 column keeps those inherited savings separate.
Per sync on the generated night (milliseconds, all nine calculations):
Full recalculation grows with the night; the retained stack stays flat. That growth, summed over 32 syncs, is where most of the saving comes from. Main here is
3a7ca34, the base of #102.How each structure saves work
Counts, extremes and moments combine in O(1). Slice dispatch removes per-row generic calls. Affine recurrences combine in O(1); grouping costs the number of keys; bounded windows copy O(k) context. Integer histograms scale with distinct values, not history length. Fixed-grid Lomb arithmetic changes from O(nF) per pass to O(new points * F), plus O(F) rendering. Its retained-prefix validation still scans O(n) input, so the complete
syncis not O(new points).Fresh timings are in "Where the speedup comes from" above. Older numbers in the docs predate this split.
Tests
Dart 3.11.4, resolved matcher 0.12.20.
dart analyze: no issues. Fulltimeout 3000 nice -n 10 dart test -j 2 --reporter json: 1,272 passed, 6 skipped, 0 failed. Counts include the inherited suite. Elapsed test time 35.979 seconds.Logs:
areas-logs/area-1.analyze.log,areas-logs/area-1.test.jsonl, exit status files and start/finish timestamps. Skips are optional external fixtures/corpora. No assertion was removed and no tolerance was widened. Dart 3.5.0 itself was not run; final test blobs retain the existing NaN-aware matcher fix.Suggested review order
One commit:
b5903fd9a9eeRepeated calculations need summaries that combine without replay. Review the state/empty/combine or append transitions first, the finish/publication rules next, then the area reference/law/checkpoint tests and tools.Change size and stacking
Logic under
lib/: +2,273/-0, 2,273 changed lines. Tests, tools and docs: +5,144/-0, 5,144 changed lines. Other root documentation: +7/-0.Stacks on
split/rr-hrv-outputsatc17280c2139a. This is branch 1 of 6, one compiled and fully tested commit per branch. Apply the stack in numerical order; the final branch must matchorigin/split/aggregatorsexactly.Questions for the reviewer