Repository navigation
Conversation
…aphy derived (#696) Max's 2026-09-27 ruling: draw one 2020 census block per household with probability proportional to block population within the finest geography its source provides (ACS: observed PUMA; CPS ASEC: identified county, else its state outside the counties that are both on Census's List 4 for that ASEC year and coded in that year's file; else state), and look every other geography up from the block. One function, us_runtime/block_location.py, wired into the base-h5 line, the stacked multispine pool (with h5_io consumer validation) and the ACS local-release line behind --location-rule block_v1; the default 'legacy' path stays byte-identical. - Keyed draws (stable_identity_uniforms over household id and clone), exact inverse CDF, optional K clones at weight/K (refused on every line until Route A admits location clones). - Block-ladder builder adds an additive per-block 'puma' array. - Census's CPS ASEC identified-county lists (List 4, ASEC 2023-2026) packaged with PDF digests and a per-year whole-county-guarantee flag. - Property tests (Hypothesis) for consistency, containment, exactness, convergence, determinism, row-order invariance and clone conservation; differential tests against the PUMA ladder and the national artifacts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Stacked pool: refuse a household that carries an ACS puma_geoid or PUMA without a valid matching puma instead of routing it through a CPS source-key join (ACS keys share the CPS 2024 key space). - The opt-in remainder weighting never applies to a year whose List 4 lacks the whole-county guarantee (keeps its whole-state draw). - Tests for the parser's positive end-of-list stop, the CSV-versus- provenance refusal and the recorded CSV digest. - Rebuild command covers ASEC 2026; docs invariant, per-line section and changelog describe the no-guarantee rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The Connecticut CBSA defect noted in this PR's body is fixed in #1072. That PR maps each CT 2020 block to its 2022 planning region through its town (the BAF MCD layer plus Census's
|
Part of #696. This implements its block-first draw on all three US lines; the predictor-surface and lineage-spec items stay open there.
Summary
Max ruled on 27 September: a household's location is one 2020 census block, drawn with probability proportional to block population within the finest geography its source provides, and every other geography is looked up from that block. Calibration supplies fidelity afterwards. This PR adds that rule as one function,
us_runtime/block_location.py, and wires it into every US line behind--location-rule block_v1. The default,legacy, keeps each line's current rule and bytes.It replaces three rules:
legacy)block_v1build_us_puf_support_base.py, feeds Route A)build_us_multispine_pool.py)_legacy/build_us_acs_multispine_base.py→build_us_acs_local_release.py)The rule
Candidate blocks come from each record's source:
GTCO≠ 0: the blocks of that county.GTCO= 0: the blocks of its state, excluding counties that are both on Census's identified-county list for that ASEC year (List 4 of the technical documentation) and coded in that year's file. A year whose List 4 drops the whole-county guarantee (ASEC 2026) excludes nothing.Tract, county, place, SLDU/SLDL, CBSA, PUMA and every attached congressional-district plan are then looked up from the block, so a household's geographies cannot contradict each other.
Draws are keyed, not sequential:
stable_identity_uniforms("{household_id}:{clone}", seed, salt=rule id)feeds an exact inverse CDF over block population. The draw also supports K clones, each with weight/K. Every line refuses K > 1 for now, because Route A's and the pool's duplicate-copy checks do not yet recognize location clones (follow-up below).Full write-up:
docs/us-location-v1.md.Why both confirmations for GTCO = 0
Max's 16 August refinement on #696 says a record without a county code does not live in an identified county. Census's list and the files disagree in the same way in every year checked.
census_cps_2022/2023/2024.h5match the rawhhpub25.csv, and the table's ratios are computed on those files:A data-derived set would rule out Tarrant's uncoded 85%. The list alone would rule out Lubbock, whose households carry GTCO = 0. Requiring both excludes 271 counties in each of ASEC 2023–2025.
The ASEC 2026 documentation drops the "entire county is identified" sentence. Its file also has 49 Delaware households with GTCO = 0, although every Delaware county is listed and coded for its whole population. So for that year GTCO = 0 draws from the whole state. The official lists for 2023–2026 are packaged with each PDF's SHA-256, and the loader verifies the CSV against its provenance.
Evidence
pumaarray. It is additive to schema 1, so the legacy loader reads the file unchanged. The national rebuild (us_block_ladder_2020_puma.npz, sha9f2dc986…) has 5,769,942 blocks, 2,462 PUMAs, 436 districts, 3,143 counties and 331,449,281 people.7ba39b95…).39a2ab2a…) cell for cell (2,462, 4,043 and 4,620 cells). Within a PUMA, the new draw's district and county distribution is exactly the legacy one; the two are now consistent with each other.census_cps_2022–2025.h5were located with the packaged lists and the national ladder:Invariants, and how each is tested
Hypothesis property tests run over nested synthetic ladders (
test_us_block_location.py,test_us_cps_source_geography.py):us_block_location_gatepasses, and fails with the column's name when any single column is tampered with.Differential tests:
assemble_us_puma_ladderon the same synthetic sources;Mutation checks. Running (results added before this leaves draft).
Effect on certified builds
None:
legacyis the default on every line, and it is byte-identical.906c9c02…, and its stage lists, run_config and child argv are unchanged.spec_engine/seeds.py's kernel lists changed. The legacy-v1 seed-protocol digest is still91989ed5…, and a new engine-free test pins it.block_v1.The stacked-pool
block_v1branch is source-spine blind (test_us_spine_blindness): a row with an observed PUMA draws within it, and any other row resolves through its CPS source key.Review
An independent five-dimension review found these, all fixed:
A second round verifying these fixes is running.
Not in this PR
puf_capital_gains_tail.pyis hashed.--cd-plan-registry) is a follow-up session. The attach interface ships here.cbsa_code0, a pre-existing ladder defect; a session is open.axiom: n/a: microsimulation geography assignment, no policy rule changes.
🤖 Generated with Claude Code