Dissolution routing: revert each individual to its own single regime (synthetic mode) - #401
Closed
hmgaudecker wants to merge 1 commit into
Closed
Dissolution routing: revert each individual to its own single regime (synthetic mode)#401hmgaudecker wants to merge 1 commit into
hmgaudecker wants to merge 1 commit into
Conversation
…me (synthetic mode) Row-split PLAN commit 1 (synthetic mode). `route_gated_edges` previously routed a divorced row to the FIRST declared leg's fallback regardless of which stakeholder the row actually represents. Adds `own_stakeholder`, a single value for the whole `simulate()` call (not a per-subject array), selecting the leg whose `source_stakeholder` matches the row's own role; `None` (default) preserves the exact prior "first declared leg" behavior, so every existing caller is byte-identical. This is EKL Appendix F's design: two independent, single-gender cohorts (all-women, all-men), each carrying a synthetic opposite-gender partner, each correctly reverting to its own single regime on divorce. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Benchmark comparison (main → HEAD)Comparing
|
Member
Author
|
Superseded by #409, which targets |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Dissolution routing: revert each individual to its own single regime (synthetic mode)
Draft — stacked on the collective-regimes extension. Review the row-split commit; the base carries the extension.
Motivation
The collective-regimes extension's forward simulation is a fixed-size pass, so on dissolution a household row could not become two independently-tracked single rows — the continuing membership followed the first declared edge leg regardless of which partner the row represents. Wrong for any two-sided dissolution simulation.
The immediate driver is Eckstein–Keane–Lifshitz (2019) (
ecksteinCareerFamilyDecisions2019). EKL's simulation (Appendix F) tracks individuals with synthetic partners: two independent single-gender cohorts, each drawing a synthetic spouse on marriage, no cross-population linkage. On dissolution each tracked individual must revert to its own single regime (single_ffor women,single_mfor men). The old "first leg" convention routed both cohorts to the same leg — silently wrong for one gender.What this PR does (synthetic mode)
Adds
own_stakeholder: str | None = Noneto the simulation router (route_gated_edges), threaded throughsimulate(). When set, a dissolved row routes to the leg whosesource_stakeholdermatches — its own single regime with its own projected state — instead of unconditionallylegs[0]:own_stakeholder=None(default) reproduces the exact prior "first declared leg" routing — byte-identical for every existing caller._select_own_leg(legs, own_stakeholder). No cross-row gather, no matcher, no new per-subject array — those belong to linked mode (below).Synthetic vs the general two-sided (linked) split
A true two-way split — one row becoming two linked tracked singles, both ex-partners living on with transfers/asset-division between them — is a larger, separate feature (linked mode): a per-subject
rolestate +partner_rowlink array, a model-declared matcher (a global cross-subject reduction the row-independentsimulatedeliberately avoids), and marriage-time pairing. Deferred and scoped inROWSPLIT-STATUS.md(incl. a gather-only, no-scatter simplification). Synthetic mode is the minimum that makes EKL's Appendix-F simulation faithful. Linked mode is what these pool papers additionally require (both ex-partners tracked):foersterUntyingKnotHow2024— Untying the KnotvoenaYoursMineOurs2015— Yours, Mine, and Ours: Do Divorce Laws Affect…reynosoImpactDivorceLaws2024— Impact of Divorce Laws on the Marriage MarketborellaAreMarriageRelatedTaxes2022— Borella, De Nardi & YangdenardiWageRiskGovernment2024— Wage Risk and Government and Spousal Insurance(Widowhood models —
hongLifeInsuranceHousehold2012,denardiWhyCouplesSingles2025— are couple→single with one surviving row, no two-way split;chiapporiMarriageMarketLabor2018models no dissolution.)Tests & verification
tests/regime_building/test_row_split_synthetic.py(3, green): own-role routing,own_stakeholder=Nonebyte-identical regression pin, two independent cohorts differing only in landing regime. Broadtests/solution tests/simulation= 570/5/2 (default path byte-identical).ty+ ruff clean.🤖 Generated with Claude Code