Skip to content

Commit 9af7199

Browse files
igerberclaude
andcommitted
Fix CI: collapse dCDH bootstrap-baseline to single backend-invariant value
The PR's RNG unification is working as intended — Rust now produces the same bootstrap SE as pure-Python under the same seed — but the pinned `TestBootstrapCellPeriod::test_bootstrap_se_matches_pre_pr4_baseline` guard held two separate per-backend baselines from the pre-RNG-unified era. The Rust backend now produces exactly the value that was formerly pinned as the Python-only baseline (0.3030802540369796), so the split is obsolete. Collapse the two constants into one, drop the HAS_RUST_BACKEND branch + os env-var check, and document the convergence in the comment. The regression guard's semantic is unchanged: under PSU=group the dispatcher still routes through the legacy group-level bootstrap path, and the assertion is still ULP-precision bit-identity against the captured baseline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d58fa64 commit 9af7199

1 file changed

Lines changed: 17 additions & 30 deletions

File tree

tests/test_survey_dcdh.py

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"""Survey support tests for ChaisemartinDHaultfoeuille (dCDH)."""
22

3-
import os
43
from typing import Optional
54

65
import numpy as np
@@ -1815,17 +1814,16 @@ class TestBootstrapCellPeriod:
18151814
"""
18161815

18171816
# Captured on pre-PR-4 code (origin/main at SHA ac181b7f — PR #329
1818-
# merge) via a scratch fit on the fixture below. Pinned here as
1819-
# the bit-identity regression guard for the dispatcher's
1820-
# PSU-within-group-constant legacy-path routing. If this test
1821-
# drifts, the dispatcher is no longer reproducing pre-PR-4
1822-
# behavior under PSU=group and the legacy fast path has
1823-
# regressed. Values differ between Rust and pure-Python backends
1824-
# because `_generate_bootstrap_weights_batch` and `solve_ols`
1825-
# take different numeric paths; bit-identity still holds within
1826-
# each backend.
1827-
_BASELINE_OVERALL_SE_RUST = 0.30560839419979546
1828-
_BASELINE_OVERALL_SE_PYTHON = 0.3030802540369796
1817+
# merge) via a scratch fit on the fixture below, on the pure-Python
1818+
# backend. Pinned here as the bit-identity regression guard for the
1819+
# dispatcher's PSU-within-group-constant legacy-path routing: if
1820+
# this test drifts, the dispatcher is no longer reproducing pre-PR-4
1821+
# behavior under PSU=group and the legacy fast path has regressed.
1822+
# Both backends now converge on this value — PR #362 unified the
1823+
# multiplier-weight RNG on the numpy PCG64 path (previously Rust
1824+
# seeded Xoshiro per-row, producing a different Rust baseline of
1825+
# 0.30560839419979546 under the same fixture).
1826+
_BASELINE_OVERALL_SE = 0.3030802540369796
18291827

18301828
@staticmethod
18311829
def _make_baseline_fixture() -> pd.DataFrame:
@@ -1861,21 +1859,11 @@ def _make_baseline_fixture() -> pd.DataFrame:
18611859
def test_bootstrap_se_matches_pre_pr4_baseline(self):
18621860
"""Bit-identity regression guard: under PSU=group the
18631861
dispatcher routes through the legacy group-level bootstrap
1864-
path, so the overall bootstrap SE must match pre-PR-4 code
1865-
to ULP precision. The baseline values were captured on
1866-
`origin/main` at `ac181b7f` (the PR #329 merge) under each
1867-
backend independently.
1862+
path, so the overall bootstrap SE must match the pre-PR-4
1863+
pure-Python baseline to ULP precision under either backend
1864+
(PR #362 unified the multiplier-weight RNG on numpy PCG64, so
1865+
Rust and Python now produce the same value).
18681866
"""
1869-
from diff_diff._backend import HAS_RUST_BACKEND
1870-
pure_python = (
1871-
os.environ.get("DIFF_DIFF_BACKEND", "auto").lower() == "python"
1872-
or not HAS_RUST_BACKEND
1873-
)
1874-
expected = (
1875-
self._BASELINE_OVERALL_SE_PYTHON
1876-
if pure_python
1877-
else self._BASELINE_OVERALL_SE_RUST
1878-
)
18791867
df_ = self._make_baseline_fixture()
18801868
sd = SurveyDesign(weights="pw", psu="group")
18811869
res = ChaisemartinDHaultfoeuille(n_bootstrap=500, seed=42).fit(
@@ -1885,12 +1873,11 @@ def test_bootstrap_se_matches_pre_pr4_baseline(self):
18851873
)
18861874
assert res.bootstrap_results is not None
18871875
observed_se = float(res.bootstrap_results.overall_se)
1888-
backend_label = "pure-python" if pure_python else "rust"
18891876
assert observed_se == pytest.approx(
1890-
expected, rel=0.0, abs=1e-15,
1877+
self._BASELINE_OVERALL_SE, rel=0.0, abs=1e-15,
18911878
), (
1892-
f"Bootstrap SE drifted from pre-PR-4 baseline "
1893-
f"(backend={backend_label}). expected={expected!r}, "
1879+
f"Bootstrap SE drifted from pre-PR-4 baseline. "
1880+
f"expected={self._BASELINE_OVERALL_SE!r}, "
18941881
f"observed={observed_se!r}. The dispatcher's "
18951882
f"PSU-within-group-constant routing is no longer "
18961883
f"bit-identical to the legacy group-level bootstrap."

0 commit comments

Comments
 (0)