perf(linalg): scores-based CR2 Bell-McCaffrey DOF (PT2018 Appendix B)#656
perf(linalg): scores-based CR2 Bell-McCaffrey DOF (PT2018 Appendix B)#656igerber wants to merge 2 commits into
Conversation
|
Overall Assessment ✅ Looks good. No unmitigated P0/P1 findings. Executive Summary
Methodology No blocking findings. Severity: P3 informational Code Quality No findings. Performance Severity: P2 Maintainability No blocking findings. Severity: P3 Tech Debt No new untracked correctness debt found. The old TODO row for CR2-BM dense residual-maker allocation is reasonably removed, subject to the P2 memory follow-up above. Security No findings. Documentation/Tests Severity: P3 |
cb5c83e to
7bc8d10
Compare
The unweighted per-contrast Satterthwaite DOF materialized the dense n x n residual-maker M = I - X(X'X)^-1 X' and contracted it over all cluster pairs (O(n^2) time per contrast, O(n^2) memory — 3.2 GB at n=20k). With Omega the (n, G) matrix stacking omega_g on disjoint cluster supports, B = Omega' M Omega collapses to diag(||omega_g||^2) - P' M_U P with P = X' Omega: O(nk + G^2 k) per contrast, no n x n allocation. ~32x at n=5k/G=50 (0.57s -> 0.018s); n=20k/G=100 in 0.12s. Algebraically identical — frozen pair-loop oracle parity at rtol 1e-10 (balanced, unbalanced, compound contrasts); both NaN-reliability guards unchanged; 432 consumer tests pass unmodified. REGISTRY notes updated (per-fit setup wording + Appendix-B evaluation sentence). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…P2) + doc syncs (P3s) P2: P_all was (G, k, m) — O(G*k^2) on the batched per-coefficient sweep (contrasts=eye(k)), contradicting the stated O(Gk) bound. The per-cluster product buffers are now contrast-chunked under a 64 MB module-constant cap (monkeypatchable); each contrast's B is computed independently so chunking is bit-identical (locked by a forced one-contrast-chunk test with assert_array_equal). P3s: stale residual-maker-M mention removed from the shared-core docstring; CHANGELOG + REGISTRY memory claims updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
7bc8d10 to
47d22dd
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment ✅ Looks good. No unmitigated P0/P1 findings. Executive Summary
Methodology Severity: P3 Severity: P2 Code Quality No findings. Performance Severity: P3 Maintainability No findings. The stale shared-core docstring was corrected. Tech Debt No new untracked correctness debt found. Removing the old CR2-BM dense residual-maker TODO is reasonable given the current implementation. Security No findings. Documentation/Tests Severity: P3 |
Summary
n×nresidual-makerM = I − X(X'X)⁻¹X'and contracted it over all cluster pairs —O(n²)time per contrast andO(n²)memory (3.2 GB at n=20k). Per Pustejovsky-Tipton (2018) Appendix B, withΩthe(n, G)matrix stackingω_gon disjoint cluster supports, the pairwise matrix collapses toB = Ω'MΩ = diag(‖ω_g‖²) − P'M_U PwithP = X'Ω—O(nk + G²k)per contrast, non×nallocation.max|B|, cluster-count boundDOF ≤ G) operate unchanged on the sameBvalues.n×nM). All 432 consumer tests (linalg, vcov-type incl. the CI-inversiondof_hc2_bmpins, stacked-DiD methodology, estimators) pass unmodified. REGISTRY: per-fit setup wording updated + an Appendix-B evaluation sentence on the existing unweighted-DOF-guard Note.Methodology references (required if estimator / math changes)
Validation
tests/test_linalg.py::TestCR2BMScoresBasedDOF(3 frozen-oracle parity tests).Security / privacy
Generated with Claude Code