Skip to content

Commit b40d179

Browse files
committed
sync upstream
2 parents b8ed1d0 + 9aafbbd commit b40d179

10 files changed

Lines changed: 136 additions & 66 deletions

File tree

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,24 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.14.13] - 2025-11-21 12:00:00
89

10+
### Bug Fix
11+
12+
- Fix calculation of consumption tax revenue with differentiated goods ((PR #1074)[https://github.com/PSLmodels/OG-Core/pull/1074])
13+
14+
## [0.14.12] - 2025-11-07 12:00:00
15+
16+
### Bug Fix
17+
18+
- Use data for pre-time path population distribution (rather than inferring it) ([PR #1071](https://github.com/PSLmodels/OG-Core/pull/1071))
19+
20+
## [0.14.11] - 2025-11-07 12:00:00
21+
22+
### Added
23+
24+
- Adds Ethiopia demographic data mapping ((PR #1063)[https://github.com/PSLmodels/OG-Core/pull/1063])
25+
-
926
## [0.14.10] - 2025-09-11 12:00:00
1027

1128
### Added
@@ -453,6 +470,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
453470
- Any earlier versions of OG-USA can be found in the [`OG-Core`](https://github.com/PSLmodels/OG-Core) repository [release history](https://github.com/PSLmodels/OG-Core/releases) from [v.0.6.4](https://github.com/PSLmodels/OG-Core/releases/tag/v0.6.4) (Jul. 20, 2021) or earlier.
454471

455472

473+
[0.14.13]: https://github.com/PSLmodels/OG-Core/compare/v0.14.12...v0.14.13
474+
[0.14.12]: https://github.com/PSLmodels/OG-Core/compare/v0.14.11...v0.14.12
475+
[0.14.11]: https://github.com/PSLmodels/OG-Core/compare/v0.14.10...v0.14.11
456476
[0.14.10]: https://github.com/PSLmodels/OG-Core/compare/v0.14.9...v0.14.10
457477
[0.14.9]: https://github.com/PSLmodels/OG-Core/compare/v0.14.8...v0.14.9
458478
[0.14.8]: https://github.com/PSLmodels/OG-Core/compare/v0.14.7...v0.14.8

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
| | |
44
| --- | --- |
5-
| Org | [![PSL cataloged](https://img.shields.io/badge/PSL-cataloged-a0a0a0.svg)](https://www.PSLmodels.org) [![OS License: CCO-1.0](https://img.shields.io/badge/OS%20License-CCO%201.0-yellow)](https://github.com/PSLmodels/OG-Core/blob/master/LICENSE) [![Jupyter Book Badge](https://jupyterbook.org/badge.svg)](https://pslmodels.github.io/OG-Core/) |
5+
| Org | [![PSL cataloged](https://img.shields.io/badge/PSL-cataloged-a0a0a0.svg)](https://www.PSLmodels.org) [![OS License: CCO-1.0](https://img.shields.io/badge/OS%20License-CCO%201.0-yellow)](https://github.com/PSLmodels/OG-Core/blob/master/LICENSE) [![Jupyter Book Badge](https://raw.githubusercontent.com/jupyter-book/jupyter-book/next/docs/media/images/badge.svg)](https://pslmodels.github.io/OG-Core/) |
66
| Package | [![Python 3.12](https://img.shields.io/badge/python-3.12-blue.svg)](https://www.python.org/downloads/release/python-3129/) [![Python 3.13](https://img.shields.io/badge/python-3.13-blue.svg)](https://www.python.org/downloads/release/python-3137/) [![PyPI Latest Release](https://img.shields.io/pypi/v/ogcore.svg)](https://pypi.org/project/ogcore/) [![PyPI Downloads](https://img.shields.io/pypi/dm/ogcore.svg?label=PyPI%20downloads)](https://pypi.org/project/ogcore/) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) |
77
| Testing | ![example event parameter](https://github.com/PSLmodels/OG-Core/actions/workflows/build_and_test.yml/badge.svg?branch=master) ![example event parameter](https://github.com/PSLmodels/OG-Core/actions/workflows/deploy_docs.yml/badge.svg?branch=master) ![example event parameter](https://github.com/PSLmodels/OG-Core/actions/workflows/check_black.yml/badge.svg?branch=master) [![Codecov](https://codecov.io/gh/PSLmodels/OG-Core/branch/master/graph/badge.svg)](https://codecov.io/gh/PSLmodels/OG-Core) |
88

@@ -12,8 +12,8 @@ OG-Core is an overlapping-generations (OG) model core theory, logic, and solutio
1212
**Country calibrations of OG-Core**
1313
| | | |
1414
| :-----------: | :---------: | :---------: |
15-
| United States, [OG-USA](https://github.com/PSLmodels/OG-USA) | United Kingdom, [OG-UK](https://github.com/PSLmodels/OG-USA) | |
16-
| Phillipines, [OG-PHL](https://github.com/EAPD-DRB/OG-PHL) | South Africa, [OG-ZAF](https://github.com/EAPD-DRB/OG-ZAF) | Indonesia, [OG-IDN](https://github.com/EAPD-DRB/OG-IDN) |
15+
| United States, [OG-USA](https://github.com/PSLmodels/OG-USA) | United Kingdom, [OG-UK](https://github.com/PSLmodels/OG-USA) | Phillipines, [OG-PHL](https://github.com/EAPD-DRB/OG-PHL) |
16+
| South Africa, [OG-ZAF](https://github.com/EAPD-DRB/OG-ZAF) | Indonesia, [OG-IDN](https://github.com/EAPD-DRB/OG-IDN) | Ethiopia, [OG-ETH](https://github.com/EAPD-DRB/OG-ETH) |
1717
| India, [OG-IND](https://github.com/OpenSourceEcon/OG-IND) | Malaysia, [OG-MYS](https://github.com/OpenSourceEcon/OG-MYS) | |
1818

1919

docs/book/content/intro/intro.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
| | |
55
| --- | --- |
6-
| Org | [![PSL cataloged](https://img.shields.io/badge/PSL-cataloged-a0a0a0.svg)](https://www.PSLmodels.org) [![OS License: CCO-1.0](https://img.shields.io/badge/OS%20License-CCO%201.0-yellow)](https://github.com/PSLmodels/OG-Core/blob/master/LICENSE) [![Jupyter Book Badge](https://jupyterbook.org/badge.svg)](https://pslmodels.github.io/OG-Core/) |
6+
| Org | [![PSL cataloged](https://img.shields.io/badge/PSL-cataloged-a0a0a0.svg)](https://www.PSLmodels.org) [![OS License: CCO-1.0](https://img.shields.io/badge/OS%20License-CCO%201.0-yellow)](https://github.com/PSLmodels/OG-Core/blob/master/LICENSE) [![Jupyter Book Badge](https://raw.githubusercontent.com/jupyter-book/jupyter-book/next/docs/media/images/badge.svg)](https://pslmodels.github.io/OG-Core/) |
77
| Package | [![Python 3.12](https://img.shields.io/badge/python-3.12-blue.svg)](https://www.python.org/downloads/release/python-3129/) [![Python 3.13](https://img.shields.io/badge/python-3.13-blue.svg)](https://www.python.org/downloads/release/python-3137/) [![PyPI Latest Release](https://img.shields.io/pypi/v/ogcore.svg)](https://pypi.org/project/ogcore/) [![PyPI Downloads](https://img.shields.io/pypi/dm/ogcore.svg?label=PyPI%20downloads)](https://pypi.org/project/ogcore/) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) |
88
| Testing | ![example event parameter](https://github.com/PSLmodels/OG-Core/actions/workflows/build_and_test.yml/badge.svg?branch=master) ![example event parameter](https://github.com/PSLmodels/OG-Core/actions/workflows/deploy_docs.yml/badge.svg?branch=master) ![example event parameter](https://github.com/PSLmodels/OG-Core/actions/workflows/check_black.yml/badge.svg?branch=master) [![Codecov](https://codecov.io/gh/PSLmodels/OG-Core/branch/master/graph/badge.svg)](https://codecov.io/gh/PSLmodels/OG-Core) |
99

@@ -12,8 +12,8 @@
1212
**Country calibrations of OG-Core**
1313
| | | |
1414
| :-----------: | :---------: | :---------: |
15-
| United States, [OG-USA](https://github.com/PSLmodels/OG-USA) | United Kingdom, [OG-UK](https://github.com/PSLmodels/OG-USA) | |
16-
| Phillipines, [OG-PHL](https://github.com/EAPD-DRB/OG-PHL) | South Africa, [OG-ZAF](https://github.com/EAPD-DRB/OG-ZAF) | Indonesia, [OG-IDN](https://github.com/EAPD-DRB/OG-IDN) |
15+
| United States, [OG-USA](https://github.com/PSLmodels/OG-USA) | United Kingdom, [OG-UK](https://github.com/PSLmodels/OG-USA) | Phillipines, [OG-PHL](https://github.com/EAPD-DRB/OG-PHL) |
16+
| South Africa, [OG-ZAF](https://github.com/EAPD-DRB/OG-ZAF) | Indonesia, [OG-IDN](https://github.com/EAPD-DRB/OG-IDN) | Ethiopia, [OG-ETH](https://github.com/EAPD-DRB/OG-ETH) |
1717
| India, [OG-IND](https://github.com/OpenSourceEcon/OG-IND) | Malaysia, [OG-MYS](https://github.com/OpenSourceEcon/OG-MYS) | |
1818

1919
The model output focuses changes in macroeconomic aggregates (GDP, investment, consumption), wages, interest rates, and the stream of tax revenues over time. Although `OG-Core` can be run independently based on default parameter values (currently representing something similar to the United States), it is meant to be a dependency of a country-specific calibration. This documentation contains the following major sections, which are regularly updated.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Model variables
2+
=================
3+
4+
This section summarizes variables output from the model in a format
5+
that is easy to search and print.
6+
The model variables are grouped together in common categories and are
7+
available in both the dictionaries of steady-state and transition-path
8+
output, unless noted otherwise in these docs.
9+

environment.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ dependencies:
1919
- sphinxcontrib-bibtex>=2.0.0
2020
- sphinx-math-dollar
2121
- pydata-sphinx-theme
22-
- jupyter-book>=0.11.3
22+
- jupyter-book<2.0.0
2323
- jupyter
2424
- pytest>=6.0
2525
- pytest-cov

ogcore/SS.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -307,15 +307,6 @@ def inner_loop(outer_loop_vars, p, client):
307307
futures.append(f)
308308

309309
try:
310-
# Wait for futures with timeout, then gather results
311-
from distributed import wait
312-
313-
done, not_done = wait(futures, timeout=600)
314-
if not_done:
315-
# Some futures didn't complete in time
316-
raise TimeoutError(
317-
f"{len(not_done)} futures did not complete within 600 seconds"
318-
)
319310
results = client.gather(futures)
320311
except Exception as e:
321312
# Cancel remaining futures and fall back to serial computation
@@ -990,7 +981,15 @@ def SS_solver(
990981
np.squeeze(p.e[-1, :, :]),
991982
p,
992983
)
993-
sales_tax_ss = tax.cons_tax_liab(cssmat, p_i_ss, p, "SS")
984+
c_i = household.get_ci(
985+
cssmat,
986+
p_i_ss,
987+
p_tilde_ss,
988+
p.tau_c[-1, :],
989+
p.alpha_c,
990+
"SS",
991+
)
992+
sales_tax_ss = tax.cons_tax_liab(c_i, p_i_ss, p, "SS")
994993
yss_before_tax_mat = household.get_y(
995994
r_p_ss, wss, bssmat_s, nssmat, p, "SS"
996995
)

ogcore/TPI.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,15 @@ def run_TPI(p, client=None):
914914
p.e,
915915
p,
916916
)
917-
sales_tax_mat = tax.cons_tax_liab(c_mat, p_i, p, "TPI")
917+
c_i = household.get_ci(
918+
c_mat[: p.T, :, :],
919+
p_i[: p.T, :],
920+
p_tilde[: p.T],
921+
p.tau_c[: p.T, :],
922+
p.alpha_c,
923+
"TPI",
924+
)
925+
sales_tax_mat = tax.cons_tax_liab(c_i, p_i, p, "TPI")
918926
C = aggr.get_C(c_mat, p, "TPI")
919927

920928
c_i = household.get_ci(

ogcore/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@
2020
from ogcore.txfunc import *
2121
from ogcore.utils import *
2222

23-
__version__ = "0.14.10"
23+
__version__ = "0.14.13"

ogcore/demographics.py

Lines changed: 80 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ def get_un_data(
118118
"764": "THA",
119119
"076": "BRA",
120120
"410": "KOR",
121+
"231": "ETH",
121122
}
122123
un_variable_dict = {
123124
"68": "fertility_rates",
@@ -989,61 +990,94 @@ def get_pop_objs(
989990
# assert np.allclose(pop_counter_2D, pop_dist)
990991
assert np.allclose(pop_counter_2D, pop_2D)
991992

992-
""""
993-
CHANGE - in OG-Core, we are implicitLy assuming pre-TP rates of mortality,
994-
fertility, and immigration are the same as the period 0 rates.
993+
# """"
994+
# CHANGE - in OG-Core, we are implicitly assuming pre-TP rates of mortality,
995+
# fertility, and immigration are the same as the period 0 rates.
996+
997+
# So let's just infer the pre-pop_dist from those.
998+
# """
999+
# pop1 = pop_2D[0, :]
1000+
# fert0 = fert_rates[0, :]
1001+
# mort0 = mort_rates[0, :]
1002+
# infmort0 = infmort_rates[0]
1003+
# imm0 = imm_rates_orig[0, :]
1004+
# pre_pop_guess = pop1.copy()
1005+
1006+
# # I can't solve this analytically, so set up a system of equation
1007+
# # to solve
1008+
# def pre_pop_solve(pre_pop_guess, pop1, fert0, mort0, infmort0, imm0):
1009+
# pre_pop = pre_pop_guess
1010+
# errors = np.zeros(E + S)
1011+
# errors[0] = pop1[0] - (
1012+
# (1 - infmort0) * (fert0 * pre_pop).sum() + imm0[0] * pre_pop[0]
1013+
# )
1014+
# errors[1:] = pop1[1:] - (
1015+
# pre_pop[:-1] * (1 - mort0[:-1]) + pre_pop[1:] * imm0[1:]
1016+
# )
1017+
# # print("Max error = ", np.abs(errors).max())
1018+
# return errors
1019+
1020+
# opt_res = opt.root(
1021+
# pre_pop_solve,
1022+
# pre_pop_guess,
1023+
# args=(pop1, fert0, mort0, infmort0, imm0),
1024+
# method="lm",
1025+
# )
1026+
# pre_pop = opt_res.x
1027+
# print(
1028+
# "Success? ",
1029+
# opt_res.success,
1030+
# ", Max diff = ",
1031+
# np.abs(opt_res.fun).max(),
1032+
# )
1033+
# pre_pop_EpS = pop_rebin(pre_pop, E + S)
1034+
1035+
# # Check result
1036+
# initial_pop_counter = np.zeros(E + S)
1037+
# newborns = (fert_rates[0, :] * pre_pop[:]).sum()
1038+
# initial_pop_counter[0] = (
1039+
# 1 - infmort_rates[0]
1040+
# ) * newborns + imm_rates_orig[0, 0] * pre_pop[0]
1041+
# initial_pop_counter[1:] = (
1042+
# pre_pop[:-1] * (1 - mort_rates[0, :-1])
1043+
# + pre_pop[1:] * imm_rates_orig[0, 1:]
1044+
# )
1045+
# # Test that using pre pop get to pop in period 1
1046+
# print("Max diff = ", np.abs(pop_2D[0, :] - initial_pop_counter).max())
1047+
# # assert np.allclose(initial_pop_counter, pop_2D[0, :])
9951048

996-
So let's just infer the pre-pop_dist from those.
9971049
"""
998-
pop1 = pop_2D[0, :]
999-
fert0 = fert_rates[0, :]
1000-
mort0 = mort_rates[0, :]
1001-
infmort0 = infmort_rates[0]
1002-
imm0 = imm_rates_orig[0, :]
1003-
pre_pop_guess = pop1.copy()
1004-
1005-
# I can't solve this analytically, so set up a system of equation
1006-
# to solve
1007-
def pre_pop_solve(pre_pop_guess, pop1, fert0, mort0, infmort0, imm0):
1008-
pre_pop = pre_pop_guess
1009-
errors = np.zeros(E + S)
1010-
errors[0] = pop1[0] - (
1011-
(1 - infmort0) * (fert0 * pre_pop).sum() + imm0[0] * pre_pop[0]
1012-
)
1013-
errors[1:] = pop1[1:] - (
1014-
pre_pop[:-1] * (1 - mort0[:-1]) + pre_pop[1:] * imm0[1:]
1015-
)
1016-
# print("Max error = ", np.abs(errors).max())
1017-
return errors
1018-
1019-
opt_res = opt.root(
1020-
pre_pop_solve,
1021-
pre_pop_guess,
1022-
args=(pop1, fert0, mort0, infmort0, imm0),
1023-
method="lm",
1024-
)
1025-
pre_pop = opt_res.x
1026-
print(
1027-
"Success? ",
1028-
opt_res.success,
1029-
", Max diff = ",
1030-
np.abs(opt_res.fun).max(),
1031-
)
1032-
pre_pop_EpS = pop_rebin(pre_pop, E + S)
1050+
NEW CODE - use the actual UN historical data instead of solving backwards
1051+
"""
1052+
# Get percentage distribution for S periods for pre-TP period
1053+
# Use the actual UN historical data instead of solving backwards
1054+
# pre_pop_EpS = pop_rebin(pre_pop, E + S) -- this assignment is
1055+
# above on line 924, but keep for clarity
10331056

10341057
# Check result
1058+
# Verify that the UN pre-period data is reasonably consistent
1059+
# with the period 0 population using the demographic transition equations
10351060
initial_pop_counter = np.zeros(E + S)
1036-
newborns = (fert_rates[0, :] * pre_pop[:]).sum()
1061+
newborns = (fert_rates[0, :] * pre_pop_EpS[:]).sum()
10371062
initial_pop_counter[0] = (
10381063
1 - infmort_rates[0]
1039-
) * newborns + imm_rates_orig[0, 0] * pre_pop[0]
1064+
) * newborns + imm_rates_orig[0, 0] * pre_pop_EpS[0]
10401065
initial_pop_counter[1:] = (
1041-
pre_pop[:-1] * (1 - mort_rates[0, :-1])
1042-
+ pre_pop[1:] * imm_rates_orig[0, 1:]
1066+
pre_pop_EpS[:-1] * (1 - mort_rates[0, :-1])
1067+
+ pre_pop_EpS[1:] * imm_rates_orig[0, 1:]
10431068
)
1044-
# Test that using pre pop get to pop in period 1
1045-
print("Max diff = ", np.abs(pop_2D[0, :] - initial_pop_counter).max())
1046-
# assert np.allclose(initial_pop_counter, pop_2D[0, :])
1069+
1070+
max_diff = np.abs(pop_2D[0, :] - initial_pop_counter).max()
1071+
print("Pre-period population verification: Max diff = ", max_diff)
1072+
1073+
if max_diff > 100_000:
1074+
print(
1075+
"WARNING: Large difference between UN pre-period population "
1076+
+ "and period 0 population ({:.2f}). ".format(max_diff)
1077+
+ "This may indicate inconsistencies in the data or "
1078+
+ "immigration rate calculations, but using UN historical "
1079+
+ "data as it is more reliable than backward-solved estimates."
1080+
)
10471081

10481082
# Create the transition matrix for the population distribution
10491083
# from T0 going forward (i.e., past when we have data on forecasts)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setuptools.setup(
77
name="ogcore",
8-
version="0.14.10",
8+
version="0.14.13",
99
author="Jason DeBacker and Richard W. Evans",
1010
license="CC0 1.0 Universal (CC0 1.0) Public Domain Dedication",
1111
description="A general equilibrium overlapping generations model for fiscal policy analysis",

0 commit comments

Comments
 (0)