Skip to content

Add BlockCovariance: memory-efficient block-diagonal online covariance (O(p·b) state) - #49

Merged
microprediction merged 1 commit into
mainfrom
block-covariance
Jun 10, 2026
Merged

Add BlockCovariance: memory-efficient block-diagonal online covariance (O(p·b) state)#49
microprediction merged 1 commit into
mainfrom
block-covariance

Conversation

@microprediction

Copy link
Copy Markdown
Owner

Summary

Adds BlockCovariance — a memory-efficient block-diagonal online covariance addressing the streaming-memory angle of #47.

SchurCovariance(gamma=0) produces a block-diagonal estimate but keeps the full p×p EWA covariance in state and zeroes cross-block entries only at read time. BlockCovariance instead tracks only the within-block (contiguous n_blocks) recency-weighted covariances:

  • State and per-step cost ~ O(p·b) (block size b), not O(p²) — it never allocates the dense matrix while streaming; it densifies only on a covariance_ request.
  • PD by construction — a block-diagonal of positive-definite blocks is positive-definite, so no global O(p³) eigen-projection; the precision is block-wise too.
  • It is the memory-light gamma=0 (block-diagonal / composite) member of the Schur family — useful at high p where the dense covariance is expensive or impossible to hold (the regime Block-streaming Schur pseudo-likelihood: avoid materializing the full p×p covariance #47 targets), and a natural generalization of DiagonalCovariance (the b=1 case).

Tests

  • Covered by the parametrized all_estimators() conformance suite (contract, fit == stream, state roundtrip, real-JSON state).
  • New tests/test_block_covariance.py: block-diagonal structure (off-block entries exactly zero), positive-definiteness, sub-quadratic state (sum of block elements < p²), JSON-serializable state that roundtrips, and blocks matching a within-block EwaCovariance.
  • ruff, mypy, and full pytest pass locally.

Notes

This is the block-diagonal case of #47. A general bounded-conditioning (Vecchia-style) streaming variant that keeps limited cross-block coupling without the dense matrix is a natural follow-up. Complementary to #48 (SchurLedoitWolfCovariance, the analytic cross-block damping).

…e (O(p*b) state)

Tracks only the within-block (contiguous n_blocks) EWA covariances, so the running state
and per-step cost scale with block size b, not p: ~O(p*b) vs O(p^2). Cross-block entries
are zero -- the memory-light gamma=0 (block-diagonal / composite) member of the Schur
family, for high p where the dense p x p covariance is costly to hold while streaming.
Block-diagonal of PD blocks is PD, so no global O(p^3) eigen-projection. Explicit JSON
get_state/set_state (flat per-block lists). Registered; parametrized conformance suite +
dedicated tests (block-diagonal structure, PD, sub-quadratic state, JSON roundtrip,
blocks match within-block EWA). Verified locally: ruff, mypy, pytest all pass. Refs #47.
@microprediction
microprediction merged commit 74b2e03 into main Jun 10, 2026
6 checks passed
@microprediction
microprediction deleted the block-covariance branch June 11, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant