Fix J=1 shape collapse bugs (#1143)#1145
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1145 +/- ##
==========================================
- Coverage 73.51% 73.41% -0.11%
==========================================
Files 21 21
Lines 5302 5303 +1
==========================================
- Hits 3898 3893 -5
- Misses 1404 1410 +6
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
Tested PR #1145, commit Passed: Failed: Also, The remaining |
|
@SeaCelo Thanks for looking into this. I think the code changes you suggest make sense, but I'm still getting the failure identified in Issue #1143: Returns: |
… and SS tax/pension calls (PSLmodels#1143)
|
@jdebacker @utsinboots Thanks both for checking this. Fixed now. I ran the full model (SS + TPI) for one income group against an identical two-group economy and they match. I also confirmed the steady state matches across reform and use_zeta. test_run_TPI_extra[J=1] passes and the full suite is green. Worth confirming on your end with a full J=1 run. the test alone uses simplified settings that hide this class of bug. |
Fixes #1143. Closes #1146.
OG-Core is almost always run with several income groups, and a handful of spots assumed there was always more than one. Each used
np.squeeze, which drops a size-1 axis — a no-op for J≥2, but for J=1 it collapses the(S, 1)ability column to a flat(S,). When that flat array is then multiplied against an(S, 1)array, numpy builds an(S, S)outer product instead of multiplying element by element, so the result comes out S× too large or the wrong shape. For J=1 this broke aggregate labor, the income-scaling factor, tax rates, and before-tax income — enough that the steady state couldn't clear (K explodes, r and consumption go negative).Sites fixed:
aggregates.get_L— SS labor aggregateSS.pyaverage_income_model— calibration factortxfunc.get_tax_rates— all parametric tax functions (linear, DEP, DEP_totalinc, GS, HSV), via one shape-aware coefficient helperhousehold.get_y— before-tax incomeSS.py— theeargument to the income-tax and pension callsWhy it took a couple of passes: the J=1 test uses a flat productivity profile and the simplest (linear) tax function — settings that happen to hide this bug (an inflated table of ones is still ones), and it never exercises the realistic tax functions. So the test passing wasn't enough; the realistic-tax and before-tax-income sites only surfaced in a full model run. The test also compared against a saved fixture generated under the old buggy code, so it kept failing even after the code was right. That fixture is regenerated.
Validation:
test_run_TPI_extra[J=1]passes; full suite green.Regression tests:
test_get_L_J1_regression—get_Lagainst a plain double-sum reference.test_get_tax_rates_J1_shape— every parametric tax function preserves the J=1 shape (fails without the fix).test_get_ystrengthened to use realistic(S, J)inputs and assert the shape.Regenerated
inner_loop_outputs_J1.pklandrun_TPI_outputs_J1.pkl, which encoded the old buggy output.cc: @jdebacker @rickecon @utsinboots