Skip to content

Collect Medicaid eligibility from the ACA source batches instead of a second full-population pass#339

Draft
daphnehanse11 wants to merge 1 commit into
medicaid-chip-take-upfrom
claude/admiring-khorana-983a15
Draft

Collect Medicaid eligibility from the ACA source batches instead of a second full-population pass#339
daphnehanse11 wants to merge 1 commit into
medicaid-chip-take-upfrom
claude/admiring-khorana-983a15

Conversation

@daphnehanse11

Copy link
Copy Markdown
Collaborator

Implements the deferred efficiency finding from the #334 review: the medicaid_take_up stage re-ran a full-population batched Microsimulation sweep (~68 batches at the default 5k-household batch size) immediately after the ACA source loop tore down identical per-batch simulations, solely to read person-level is_medicaid_eligible. Eliminating the second pass saves roughly 15–45 minutes of wall clock and the repeated multi-GB simulation churn per release build.

Note

Stacked on #334 (medicaid-chip-take-up) — the function being refactored only exists there. Retarget to main once #334 merges.

What changed

  • Medicaid eligibility now rides the ACA source batches. _aca_source_tax_unit_table_batched (and its wrappers up through _with_aca_marketplace_source_outputs) accept an on_batch_simulation(batch_frame, batch_simulation) callback invoked while each batch simulation is alive. The release flow passes a new _BatchedPersonEligibilityCollector, which calculates is_medicaid_eligible per batch and scatters it into a full-population person array by person_id position. _with_medicaid_take_up_outputs accepts the precomputed array and keeps the dedicated batched pass only as a fallback; the simulation is not None fast paths are preserved.
  • Safety of the seam. The ACA writeback touches only takes_up_aca_if_eligible and selected_marketplace_plan_benchmark_ratio. Verified against installed policyengine-us that neither appears in is_medicaid_eligible's transitive dependency closure (468 variables, including adds/subtracts), so computing eligibility on the pre-writeback batch simulations is behavior-preserving. The collector tracks coverage and raises on partial coverage rather than shipping silent all-False rows; a never-invoked collector yields None, which triggers the fallback pass.
  • Batching skeleton deduplicated. The GC-suspension / full-batch-reuse / forced-collection loop that was copied four times is now a shared _for_each_household_batch(frame, batch_size=…, describe=…, fn=…) helper.

Blast radius

Beyond the ACA and Medicaid loops, the two reform-validation batch loops were also rewritten onto the shared helper: _BatchedReformValidationSimulation._calculate_total (validation-measure scoring) and _reform_household_income_tax (JCT reform target materialization). Their per-batch bodies are unchanged — same dataset construction, reform application, cache invalidation, and household-position writeback — but they now share the skeleton, so a bug in the helper would touch all four passes.

Tests

  • New: ACA batched loop feeds the collector in full person-table order; collector rejects partial coverage; _with_medicaid_take_up_outputs uses a precomputed array without triggering the batched pass (asserted via diagnostics eligible weight).
  • Updated: three monkeypatched signatures that gained keyword-only params.
  • Full packages/populace-build suite passes (519 tests); ruff check/format clean.

🤖 Generated with Claude Code

… second full-population pass

The medicaid_take_up stage re-ran the entire batched Microsimulation
sweep (~68 batches at the default batch size) immediately after the ACA
source loop tore down identical per-batch simulations, solely to read
person-level is_medicaid_eligible. The ACA writeback only touches
takes_up_aca_if_eligible and selected_marketplace_plan_benchmark_ratio,
neither of which appears in is_medicaid_eligible's transitive dependency
closure (verified against policyengine-us), so the eligibility array is
now scattered out of the ACA batch simulations via an
on_batch_simulation callback and handed to _with_medicaid_take_up_outputs,
which keeps the dedicated batched pass only as a fallback.

Also extracts the batching skeleton (GC suspension, full-batch reuse,
forced collection between batches) that was copied four times into a
shared _for_each_household_batch helper used by the ACA loop, the
Medicaid eligibility fallback, and both reform-validation loops.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@daphnehanse11 daphnehanse11 force-pushed the claude/admiring-khorana-983a15 branch from f12aad8 to a545c2d Compare July 8, 2026 18:02
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