Add numerical guards for CES with heterogeneous epsilon#1096
Add numerical guards for CES with heterogeneous epsilon#1096jdebacker merged 4 commits intoPSLmodels:masterfrom
Conversation
…epsilon When epsilon differs from 1.0 across sectors, the CES production function raises K, L, and K_g to (epsilon-1)/epsilon, which is negative for epsilon < 1. If any input is zero or near-zero (common during initial solver iterations), this produces inf or NaN, causing the SS and TPI solvers to fail. Changes: - Add _FLOOR (1e-12) constant and apply np.maximum() guards before all CES power operations in get_Y, get_MPx, get_KLratio_KLonly, and solve_L - Fix bug in get_MPx: np.any(x) == 0 should be np.any(x == 0) - Guard denominator in get_KLratio_KLonly CES branch against negative values These guards only affect the general CES code paths (epsilon != 1); the Cobb-Douglas special case (epsilon == 1) is unchanged. Tested with OG-UK 8-sector model using heterogeneous epsilon values (0.40-1.30) — SS solver now converges successfully. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two changes:
1. Make single-sector (M=1) the default run mode. The 8-sector industry
calibration is now opt-in via `multi_sector=True` parameter on
solve_steady_state() and run_transition_path(), or via the
`multi-sector` CLI flag:
uv run python examples/run_oguk.py ss pooled # M=1
uv run python examples/run_oguk.py ss pooled multi-sector # M=8
2. Enable calibrated heterogeneous CES elasticities (epsilon) in the
8-sector mode. Previously forced to 1.0 (Cobb-Douglas) for all
sectors due to solver NaN issues — now uses literature values from
Chirinko (2008) and Knoblach et al. (2020):
Energy=0.50, Construction=0.70, Trade & Transport=1.00,
Info & Finance=1.20, Real Estate=0.40, Business Services=1.30,
Public & Other=0.90, Manufacturing=0.80
Supporting changes:
- Recalibrate TFP (Z) using CES Solow residuals instead of
Cobb-Douglas residuals when epsilon != 1
- Use hybr root-finder (Powell hybrid) instead of LM for
multi-sector SS — LM gets stuck at ~1e-5 residuals
- Relax mindist_SS and RC_SS to 1e-4 for multi-sector
Requires OG-Core PR PSLmodels/OG-Core#1096 (numerical guards for
CES production functions).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@vahid-ahmadi Can you merge in upstream changes? And then run I think tests should pass and this will be set to merge then. Thanks! |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The np.maximum(denom, _FLOOR) guard was clamping legitimately negative denominators to a small positive value, producing wrong KLratio results when epsilon < 1. Use sign-preserving guard instead. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Fixed the failing tests ( Root cause: Fix: Replaced with a sign-preserving guard: denom = np.where(
denom >= 0,
np.maximum(denom, _FLOOR),
np.minimum(denom, -_FLOOR),
)This still prevents division by zero but preserves negative denominators. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1096 +/- ##
==========================================
- Coverage 73.17% 73.09% -0.09%
==========================================
Files 21 21
Lines 5190 5211 +21
==========================================
+ Hits 3798 3809 +11
- Misses 1392 1402 +10
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
Thanks for the PR @vahid-ahmadi. Merging. |
Summary
_FLOOR = 1e-12guards infirm.pyto prevent0^(negative)→ inf/NaN when CES epsilon ≠ 1get_MPx:np.any(x) == 0should benp.any(x == 0)(the original always evaluates to False)get_Y,get_MPx,get_KLratio_KLonly, andsolve_L— only in the general CES code paths; Cobb-Douglas (ε=1) is unchangedMotivation
When
epsilonvaries across sectors (e.g., Energy=0.50, Real Estate=0.40, Info & Finance=1.20), the CES production function raises K, L, K_g to(epsilon-1)/epsilon. For epsilon < 1, this exponent is negative, so any zero or near-zero input during initial solver iterations produces inf/NaN and crashes the solver.This was blocking OG-UK from using calibrated sector-specific CES elasticities from Chirinko (2008) and Knoblach et al. (2020). With this fix, OG-UK's 8-sector model with heterogeneous epsilon (0.40–1.30) converges successfully in both SS and TPI.
Test plan
🤖 Generated with Claude Code