Skip to content

Divide bequest pools by actual group populations, not birth shares - #1187

Open
marcelolafleur wants to merge 2 commits into
PSLmodels:masterfrom
marcelolafleur:fix/bq-actual-population
Open

Divide bequest pools by actual group populations, not birth shares#1187
marcelolafleur wants to merge 2 commits into
PSLmodels:masterfrom
marcelolafleur:fix/bq-actual-population

Conversation

@marcelolafleur

@marcelolafleur marcelolafleur commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Fixes #1186.

With demographics that vary across lifetime income groups (#1165), each group's population share no longer equals its birth share lambdas[j] and survivorship differs by group. The use_zeta = False branch of household.get_bq still divided each group's bequest pool by lambdas[j], so bequests received did not sum to bequests left. In an OG-ZAF calibration with South African mortality gradients, households collectively received about 6.5% more bequests than existed, and the steady state failed the aggregate resource constraint by about 1% of GDP.

The fix: divide each group's pool by its actual population share: omega_SS[:, j].sum() in the steady state, per-period omega sums along the time path, which is what the use_zeta = True branch already does. When demographics are common across groups the two denominators coincide, so results are unchanged in every pre-#1165 use case: all existing get_bq tests pass without modification.

Tests: adds a conservation test with a non-separable omega (group population shares deliberately different from lambdas) checking that receipts aggregate back to the pool for SS and TPI, by-group and pooled. tests/test_household.py passes 52/52 locally.

cc: @rickecon @jdebacker

With demographics varying across lifetime income groups (PR PSLmodels#1165),
group population shares no longer equal lambdas: survivorship differs
by group. The use_zeta=False branch of household.get_bq still divided
each group's bequest pool by lambdas[j], so bequests received did not
sum to bequests left (about +6.5% over-distribution in an OG-ZAF
calibration with South African mortality gradients) and the steady
state failed the aggregate resource constraint by about 1% of GDP.

Divide by the group's actual population share instead — omega_SS[:, j]
for the steady state, per-period omega sums along the time path —
matching what the use_zeta=True branch already does. When demographics
are common across groups the two coincide, so existing results are
unchanged (all existing get_bq tests pass unmodified). Adds a
conservation test with non-separable omega covering SS and TPI, by-j
and pooled.

Fixes PSLmodels#1186.
@codecov-commenter

codecov-commenter commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 72.68%. Comparing base (b9b33ac) to head (621b97b).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1187      +/-   ##
==========================================
+ Coverage   72.66%   72.68%   +0.01%     
==========================================
  Files          22       22              
  Lines        5726     5730       +4     
==========================================
+ Hits         4161     4165       +4     
  Misses       1565     1565              
Flag Coverage Δ
unittests 72.68% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
ogcore/household.py 90.90% <100.00%> (+0.13%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@marcelolafleur
marcelolafleur marked this pull request as ready for review July 28, 2026 20:44
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.

Bequest receipts don't sum to bequests left when demographics vary by income group

2 participants