Skip to content

Commit dbe0b9f

Browse files
authored
Merge pull request #1062 from jdebacker/J1
Merging
2 parents e0d0972 + 30450ff commit dbe0b9f

File tree

12 files changed

+103
-38
lines changed

12 files changed

+103
-38
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ 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.15.4] - 2025-01-27 12:00:00
9+
10+
### Added
11+
12+
- Ability to simulate the model with a single type of household (`J=1`). See PR [#1062](https://github.com/PSLmodels/OG-Core/pull/1062)
13+
814
## [0.15.3] - 2025-01-24 12:00:00
915

1016
### Added
@@ -505,6 +511,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
505511
- 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.
506512

507513

514+
[0.15.4]: https://github.com/PSLmodels/OG-Core/compare/v0.15.3...v0.15.4
508515
[0.15.3]: https://github.com/PSLmodels/OG-Core/compare/v0.15.2...v0.15.3
509516
[0.15.2]: https://github.com/PSLmodels/OG-Core/compare/v0.15.1...v0.15.2
510517
[0.15.1]: https://github.com/PSLmodels/OG-Core/compare/v0.15.0...v0.15.1

ogcore/SS.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ def inner_loop(outer_loop_vars, p, client):
418418
None,
419419
False,
420420
"SS",
421-
np.squeeze(p.e[-1, :, :]),
421+
np.squeeze(p.e[-1, :, :]).reshape((p.S, p.J)),
422422
etr_params_3D,
423423
p,
424424
)
@@ -433,7 +433,7 @@ def inner_loop(outer_loop_vars, p, client):
433433
bq,
434434
rm,
435435
net_tax,
436-
np.squeeze(p.e[-1, :, :]),
436+
np.squeeze(p.e[-1, :, :]).reshape((p.S, p.J)),
437437
p.tau_c[-1, :],
438438
p,
439439
)
@@ -557,7 +557,7 @@ def inner_loop(outer_loop_vars, p, client):
557557
None,
558558
False,
559559
"SS",
560-
np.squeeze(p.e[-1, :, :]),
560+
np.squeeze(p.e[-1, :, :]).reshape((p.S, p.J)),
561561
etr_params_3D,
562562
p,
563563
)
@@ -572,7 +572,7 @@ def inner_loop(outer_loop_vars, p, client):
572572
new_bq,
573573
new_rm,
574574
taxss,
575-
np.squeeze(p.e[-1, :, :]),
575+
np.squeeze(p.e[-1, :, :]).reshape((p.S, p.J)),
576576
p.tau_c[-1, :],
577577
p,
578578
)
@@ -602,7 +602,7 @@ def inner_loop(outer_loop_vars, p, client):
602602
ubi,
603603
theta,
604604
etr_params_3D,
605-
np.squeeze(p.e[-1, :, :]),
605+
np.squeeze(p.e[-1, :, :]).reshape((p.S, p.J)),
606606
p,
607607
None,
608608
"SS",
@@ -925,7 +925,7 @@ def SS_solver(
925925
nssmat,
926926
factor,
927927
True,
928-
np.squeeze(p.e[-1, :, :]),
928+
np.squeeze(p.e[-1, :, :]).reshape((p.S, p.J)),
929929
etr_params_3D,
930930
mtry_params_3D,
931931
capital_noncompliance_rate_2D,
@@ -939,7 +939,7 @@ def SS_solver(
939939
nssmat,
940940
factor,
941941
False,
942-
np.squeeze(p.e[-1, :, :]),
942+
np.squeeze(p.e[-1, :, :]).reshape((p.S, p.J)),
943943
etr_params_3D,
944944
mtrx_params_3D,
945945
labor_noncompliance_rate_2D,
@@ -952,7 +952,7 @@ def SS_solver(
952952
bssmat_s,
953953
nssmat,
954954
factor,
955-
np.squeeze(p.e[-1, :, :]),
955+
np.squeeze(p.e[-1, :, :]).reshape((p.S, p.J)),
956956
etr_params_3D,
957957
labor_noncompliance_rate_2D,
958958
capital_noncompliance_rate_2D,
@@ -974,7 +974,7 @@ def SS_solver(
974974
None,
975975
False,
976976
"SS",
977-
np.squeeze(p.e[-1, :, :]),
977+
np.squeeze(p.e[-1, :, :]).reshape((p.S, p.J)),
978978
etr_params_3D,
979979
p,
980980
)
@@ -1020,7 +1020,7 @@ def SS_solver(
10201020
bqssmat,
10211021
rmssmat,
10221022
taxss,
1023-
np.squeeze(p.e[-1, :, :]),
1023+
np.squeeze(p.e[-1, :, :]).reshape((p.S, p.J)),
10241024
p.tau_c[-1, :],
10251025
p,
10261026
)
@@ -1077,7 +1077,7 @@ def SS_solver(
10771077
ubissmat,
10781078
theta,
10791079
etr_params_3D,
1080-
np.squeeze(p.e[-1, :, :]),
1080+
np.squeeze(p.e[-1, :, :]).reshape((p.S, p.J)),
10811081
p,
10821082
None,
10831083
"SS",

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.15.3"
23+
__version__ = "0.15.4"

ogcore/pensions.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ def replacement_rate_vals(nssmat, wss, factor_ss, j, p):
3030
"""
3131
if j is not None:
3232
e = np.squeeze(p.e[-1, :, j]) # Only computes using SS earnings
33+
dim2 = 1
3334
else:
34-
e = np.squeeze(p.e[-1, :, :]) # Only computes using SS earnings
35+
e = np.squeeze(p.e[-1, :, :]).reshape(
36+
(p.S, p.J)
37+
) # Only computes using SS earnings
38+
dim2 = p.J
3539
# adjust number of calendar years AIME computed from int model periods
3640
equiv_periods = int(round((p.S / 80.0) * p.avg_earn_num_years)) - 1
37-
if e.ndim == 2:
38-
dim2 = e.shape[1]
39-
else:
40-
dim2 = 1
4141
earnings = (e * (wss * nssmat * factor_ss)).reshape(p.S, dim2)
4242
# get highest earning years for number of years AIME computed from
4343
highest_earn = (

ogcore/tax.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ def net_taxes(
302302
)
303303
T_BQ = bequest_tax_liab(r, b, bq, t, j, method, p)
304304
T_W = wealth_tax_liab(r, b, t, j, method, p)
305-
305+
# print("Net taxes shapes = ", T_I.shape, pension.shape, T_BQ.shape, T_W.shape)
306306
net_tax = T_I - pension + T_BQ + T_W - tr - ubi
307307

308308
return net_tax
@@ -373,6 +373,7 @@ def income_tax_liab(r, w, b, n, factor, t, j, method, e, etr_params, p):
373373
tax_filer = p.income_tax_filer[-1, :]
374374
income = r * b + w * e * n
375375
labor_income = w * e * n
376+
376377
T_I = (
377378
ETR_income(
378379
r,

ogcore/txfunc.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,10 @@ def get_tax_rates(
263263
txrates = tau_income + shift_income + shift
264264
elif tax_func_type == "linear":
265265
rate = np.squeeze(params[..., 0])
266-
txrates = rate * np.ones_like(income)
266+
try:
267+
txrates = rate * np.ones_like(income)
268+
except ValueError:
269+
txrates = rate.reshape(income.shape) * np.ones_like(income)
267270
elif tax_func_type == "mono":
268271
if for_estimation:
269272
mono_interp = params[0]
@@ -367,7 +370,7 @@ def get_tax_rates(
367370
]
368371
for t in range(income.shape[0])
369372
]
370-
txrates = np.squeeze(np.array(txrates))
373+
txrates = np.squeeze(np.array(txrates)).reshape(X.shape)
371374

372375
return txrates
373376

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.15.3",
8+
version="0.15.4",
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",

tests/test_SS.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,21 @@ def test_solve_for_j():
587587
"gamma_g": [0.0, 0.0, 0.0, 0.0],
588588
}
589589
filename8 = "inner_loop_outputs_reform_MneI.pkl"
590+
param_updates9 = {
591+
"J": 1,
592+
"lambdas": np.array([1.0]),
593+
"e": np.ones((80, 1)),
594+
"beta_annual": [0.96],
595+
"chi_b": [80],
596+
"labor_income_tax_noncompliance_rate": [[0.0]],
597+
"capital_income_tax_noncompliance_rate": [[0.0]],
598+
"income_tax_filer": [[1]],
599+
"wealth_tax_filer": [[1]],
600+
"eta": np.ones((80, 1)) * (1 / 80),
601+
"eta_RM": np.ones((80, 1)) * (1 / 80),
602+
"replacement_rate_adjust": [[1.0]],
603+
}
604+
filename9 = "inner_loop_outputs_J1.pkl"
590605

591606

592607
@pytest.mark.parametrize(
@@ -599,6 +614,7 @@ def test_solve_for_j():
599614
(False, 0.04260341179572245, param_updates5, filename5),
600615
(False, 0.04759112768438152, param_updates7, filename7),
601616
(False, 0.04759112768438152, param_updates8, filename8),
617+
(True, 0.04, param_updates9, filename9),
602618
],
603619
ids=[
604620
"Baseline, Small Open",
@@ -608,6 +624,7 @@ def test_solve_for_j():
608624
"Reform, baseline spending",
609625
"Reform, M>1",
610626
"Reform, I!=>M",
627+
"J=1",
611628
],
612629
)
613630
def test_inner_loop(baseline, r_p, param_updates, filename, dask_client):
@@ -662,6 +679,7 @@ def test_inner_loop(baseline, r_p, param_updates, filename, dask_client):
662679
)
663680
test_tuple = SS.inner_loop(outer_loop_vars, p, dask_client)
664681

682+
# The output format for the inner loop
665683
try:
666684
(
667685
euler_errors,

tests/test_TPI.py

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ def dask_client():
177177
client = Client(cluster)
178178
yield client
179179
# teardown
180-
client.close()
181-
cluster.close()
180+
# client.close()
181+
# cluster.close()
182182

183183

184184
filename1 = "intial_SS_values_baseline.pkl"
@@ -870,6 +870,21 @@ def test_run_TPI(baseline, param_updates, filename, tmpdir, dask_client):
870870
filename8 = os.path.join(
871871
CUR_PATH, "test_io_data", "run_TPI_outputs_baseline_Kg_nonzero_2.pkl"
872872
)
873+
param_updates10 = {
874+
"J": 1,
875+
"lambdas": np.array([1.0]),
876+
"e": np.ones((40, 1)),
877+
"beta_annual": [0.96],
878+
"chi_b": [80],
879+
"labor_income_tax_noncompliance_rate": [[0.0]],
880+
"capital_income_tax_noncompliance_rate": [[0.0]],
881+
"income_tax_filer": [[1]],
882+
"wealth_tax_filer": [[1]],
883+
"eta": np.ones((40, 1)) * (1 / 40),
884+
"eta_RM": np.ones((40, 1)) * (1 / 40),
885+
"replacement_rate_adjust": [[1.0]],
886+
}
887+
filename10 = os.path.join(CUR_PATH, "test_io_data", "run_TPI_outputs_J1.pkl")
873888
# read in mono tax funcs (not age specific)
874889
if sys.version_info[1] < 11:
875890
dict_params = utils.safe_read_pickle(
@@ -899,6 +914,7 @@ def test_run_TPI(baseline, param_updates, filename, tmpdir, dask_client):
899914
CUR_PATH, "test_io_data", "run_TPI_outputs_mono_2.pkl"
900915
)
901916

917+
902918
if sys.version_info[1] < 11:
903919
test_list = [
904920
(True, param_updates2, filename2),
@@ -922,22 +938,24 @@ def test_run_TPI(baseline, param_updates, filename, tmpdir, dask_client):
922938
]
923939
else:
924940
test_list = [
925-
# (True, param_updates2, filename2),
926-
# (True, param_updates5, filename5),
927-
# (True, param_updates6, filename6),
928-
# (True, param_updates7, filename7),
929-
# (True, {}, filename1),
930-
# (False, param_updates4, filename4),
941+
(True, param_updates2, filename2),
942+
(True, param_updates5, filename5),
943+
(True, param_updates6, filename6),
944+
(True, param_updates7, filename7),
945+
(True, {}, filename1),
946+
(False, param_updates4, filename4),
931947
(True, param_updates8, filename8),
948+
(True, param_updates10, filename10),
932949
]
933950
id_list = [
934-
# "Baseline, balanced budget",
935-
# "Baseline, small open",
936-
# "Baseline, small open for some periods",
937-
# "Baseline, delta_tau = 0",
938-
# "Baseline",
939-
# "Reform, baseline spending",
951+
"Baseline, balanced budget",
952+
"Baseline, small open",
953+
"Baseline, small open for some periods",
954+
"Baseline, delta_tau = 0",
955+
"Baseline",
956+
"Reform, baseline spending",
940957
"Baseline, Kg>0",
958+
"J=1",
941959
]
942960

943961

3.1 KB
Binary file not shown.

0 commit comments

Comments
 (0)