Skip to content

Commit

Permalink
Merge pull request #987 from jdebacker/basespend_adj
Browse files Browse the repository at this point in the history
Merging
rickecon authored Oct 3, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents 4b32ef3 + 4137152 commit 4ea91c9
Showing 14 changed files with 934 additions and 627 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.13.1] - 2024-10-02 12:00:00

### Added

- Three new parameters to adjust government spending amounts in the case of `baseline_spending=True`:
- `alpha_bs_G`: the proportional adjustment to the level of baseline spending on government consumption (time varying, default value is 1.0 for each model period)
- `alpha_bs_T`: the proportional adjustment to the level of baseline spending on non-pension transfers (time varying, default value is 1.0 for each model period)
- `alpha_bs_I`: the proportional adjustment to the level of baseline spending on infrastructure investment (time varying, default value is 1.0 for each model period)

## [0.13.0] - 2024-09-26 12:00:00

### Added
@@ -333,6 +342,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Version [0.7.0] on August 30, 2021 was the first time that the OG-USA repository was detached from all of the core model logic, which was named OG-Core. Before this version, OG-USA was part of what is now the [`OG-Core`](https://github.com/PSLmodels/OG-Core) repository. In the next version of OG-USA, we adjusted the version numbering to begin with 0.1.0. This initial version of 0.7.0, was sequential from what OG-USA used to be when the OG-Core project was called OG-USA.
- 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.

[0.13.1]: https://github.com/PSLmodels/OG-Core/compare/v0.13.0...v0.13.1
[0.13.0]: https://github.com/PSLmodels/OG-Core/compare/v0.12.0...v0.13.0
[0.12.0]: https://github.com/PSLmodels/OG-Core/compare/v0.11.17...v0.12.0
[0.11.17]: https://github.com/PSLmodels/OG-Core/compare/v0.11.16...v0.11.17
[0.11.16]: https://github.com/PSLmodels/OG-Core/compare/v0.11.15...v0.11.16
1,192 changes: 621 additions & 571 deletions docs/book/content/intro/parameters.md

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions docs/book/content/theory/government.md
Original file line number Diff line number Diff line change
@@ -564,6 +564,17 @@ Total pension spending is the sum of the pension payments to each household in t

Put description of growth-adjusted specification here.

#### Spending in the `reform` simulation

While aggregate spending on $G$, $TR$, and $I_g$ in the baseline simulation are set as fractions of GDP, in the `reform` simulation, these spending amounts can be set in two different ways. The method is controlled by the `baseline_spending` parameter. If `baseline_spending=False`, the behavior of these spending is analgous to that in the baseline simulation; they are set as fractions of GDP, in this case **GDP in the reform simulation**. Thus, with the default assumption of `baseline_spending` it's assumed that spending levels in these three categories are function of GDP in the reform. In this case, users will see that, even with the parameters $\alpha_G$, $\alpha_T$, and $\alpha_I$ are unchanged, the *level* of spending will change in the reform *if* GDP in the reform is different.

With the assumption of `baseline_spending=True`, the level of spending in the reform is held to the level of spending in the baseline. If the user wishes to adjust the level of spending, relative to the baseline level, in the reform, then the parameters `alpha_bs_G`, `alpha_bs_T`, and `alpha_bs_I` can be used to proportionally increase or decrease the levels of spending on $G$, $TR$, and $I_g$ in the reform simulation, relative to the levels in the baseline simulation. Note that the `alpha_bs_*` parameters are time varying, so the proportional change in spending can be different across time. E.g., for government consumption expenditures, we'd have the reform amount of $G$ determined as:

```{math}
G^{reform}_t = \alpha^{BS}_{G,t}G^{baseline}_{t}
```

Note that the budget closure rule (described in Section ref{`SecUnbalGBCcloseRule`}) still takes effect in the case of `baseline_spending=True`. What this means is that the relation described above holds until the period in which the closure rules takes effect. Once the closure rule begins, the path of $G$ (and/or $TR$, depending on the closure rule used) will adjust as determined by the rule to close the government budget in the long run.

(SecUnbalGBCrev)=
## Government Tax Revenue
105 changes: 87 additions & 18 deletions ogcore/SS.py
Original file line number Diff line number Diff line change
@@ -225,7 +225,9 @@ def inner_loop(outer_loop_vars, p, client):
scattered_p = client.scatter(p, broadcast=True) if client else p

# unpack variables to pass to function
bssmat, nssmat, r_p, r, w, p_m, Y, BQ, TR, factor = outer_loop_vars
bssmat, nssmat, r_p, r, w, p_m, Y, BQ, TR, Ig_baseline, factor = (
outer_loop_vars
)

p_m = np.array(p_m) # TODO: why is this a list otherwise?
p_i = np.dot(p.io_matrix, p_m)
@@ -333,7 +335,7 @@ def inner_loop(outer_loop_vars, p, client):
D, D_d, D_f, new_borrowing, _, new_borrowing_f = fiscal.get_D_ss(
r_gov, Y, p
)
I_g = fiscal.get_I_g(Y, p.alpha_I[-1])
I_g = fiscal.get_I_g(Y, Ig_baseline, p, "SS")
K_g = fiscal.get_K_g(0, I_g, p, "SS")

# Find wage rate consistent with open economy interest rate
@@ -372,7 +374,7 @@ def inner_loop(outer_loop_vars, p, client):
Y_vec[-1] = firm.get_Y(K_vec[-1], K_g, L_vec[-1], p, "SS", -1)
# Find GDP
Y = (p_m * Y_vec).sum()
I_g = fiscal.get_I_g(Y, p.alpha_I[-1])
I_g = fiscal.get_I_g(Y, Ig_baseline, p, "SS")
K_g = fiscal.get_K_g(0, I_g, p, "SS")
if p.zeta_K[-1] == 1.0:
new_r = p.world_int_rate[-1]
@@ -553,7 +555,20 @@ def inner_loop(outer_loop_vars, p, client):


def SS_solver(
bmat, nmat, r_p, r, w, p_m, Y, BQ, TR, factor, p, client, fsolve_flag=False
bmat,
nmat,
r_p,
r,
w,
p_m,
Y,
BQ,
TR,
Ig_baseline,
factor,
p,
client,
fsolve_flag=False,
):
"""
Solves for the steady state distribution of capital, labor, as well
@@ -586,18 +601,30 @@ def SS_solver(
if fsolve_flag: # case where already solved via SS_fsolve
maxiter_ss = 1
if p.baseline_spending:
TR_ss = TR
TR_baseline = p.alpha_bs_T[-1] * TR
if not p.budget_balance and not p.baseline_spending:
Y = TR / p.alpha_T[-1]
while (dist > p.mindist_SS) and (iteration < maxiter_ss):
# Solve for the steady state levels of b and n, given w, r,
# Y, BQ, TR, and factor
if p.baseline_spending:
TR = TR_ss
TR = p.alpha_bs_T[-1] * TR_baseline
if not p.budget_balance and not p.baseline_spending:
Y = TR / p.alpha_T[-1]

outer_loop_vars = (bmat, nmat, r_p, r, w, p_m, Y, BQ, TR, factor)
outer_loop_vars = (
bmat,
nmat,
r_p,
r,
w,
p_m,
Y,
BQ,
TR,
Ig_baseline,
factor,
)

(
euler_errors,
@@ -654,7 +681,7 @@ def SS_solver(
).max()
else:
if p.baseline_spending:
TR = TR_ss
TR = p.alpha_bs_T[-1] * TR_baseline
else:
TR = utils.convex_combo(new_TR, TR, nu_ss)
dist = np.array(
@@ -695,7 +722,7 @@ def SS_solver(
RM_ss = new_RM
TR_ss = new_TR
Yss = new_Y
I_g_ss = fiscal.get_I_g(Yss, p.alpha_I[-1])
I_g_ss = fiscal.get_I_g(Yss, Ig_baseline, p, "SS")
K_g_ss = fiscal.get_K_g(0, I_g_ss, p, "SS")
Lss = aggr.get_L(nssmat, p, "SS")
Bss = aggr.get_B(bssmat_splus1, p, "SS", False)
@@ -718,7 +745,7 @@ def SS_solver(
Bss, K_demand_open_ss.sum(), D_d_ss, p.zeta_K[-1]
)
# Yss = firm.get_Y(Kss, K_g_ss, Lss, p, 'SS')
I_g_ss = fiscal.get_I_g(Yss, p.alpha_I[-1])
I_g_ss = fiscal.get_I_g(Yss, Ig_baseline, p, "SS")
K_g_ss = fiscal.get_K_g(0, I_g_ss, p, "SS")
MPKg_vec = np.zeros(p.M)
for m in range(p.M):
@@ -1057,7 +1084,7 @@ def SS_fsolve(guesses, *args):
implied outer loop variables
"""
(bssmat, nssmat, TR_ss, factor_ss, p, client) = args
(bssmat, nssmat, TR_ss, Ig_baseline, factor_ss, p, client) = args

# Rename the inputs
r_p = guesses[0]
@@ -1078,7 +1105,19 @@ def SS_fsolve(guesses, *args):
if not p.budget_balance and not p.baseline_spending:
Y = TR / p.alpha_T[-1]

outer_loop_vars = (bssmat, nssmat, r_p, r, w, p_m, Y, BQ, TR, factor)
outer_loop_vars = (
bssmat,
nssmat,
r_p,
r,
w,
p_m,
Y,
BQ,
TR,
Ig_baseline,
factor,
)

# Solve for the steady state levels of b and n, given w, r, TR and
# factor
@@ -1236,7 +1275,15 @@ def run_SS(p, client=None):
Yguess = TRguess / p.alpha_T[-1]
factorguess = p.initial_guess_factor_SS
BQguess = aggr.get_BQ(rguess, b_guess, None, p, "SS", False)
ss_params_baseline = (b_guess, n_guess, None, None, p, client)
ss_params_baseline = (
b_guess,
n_guess,
None,
None,
None,
p,
client,
)
if p.use_zeta:
BQguess = 0.12231465279007188
guesses = (
@@ -1285,6 +1332,7 @@ def run_SS(p, client=None):
Yss,
BQss,
TR_ss,
None,
factor_ss,
p,
client,
@@ -1364,21 +1412,30 @@ def run_SS(p, client=None):
if p.use_zeta:
BQguess = 0.12231465279007188
if p.baseline_spending:
TR_ss = TRguess
ss_params_reform = (b_guess, n_guess, TR_ss, factor, p, client)
TR_baseline = TRguess
Ig_baseline = ss_solutions["I_g_ss"]
ss_params_reform = (
b_guess,
n_guess,
TR_baseline,
Ig_baseline,
factor,
p,
client,
)
if p.use_zeta:
guesses = (
[r_p_guess, rguess, wguess]
+ list(p_m_guess)
+ [Yguess, BQguess, TR_ss]
+ [Yguess, BQguess, TR_baseline]
)
else:
guesses = (
[r_p_guess, rguess, wguess]
+ list(p_m_guess)
+ [Yguess]
+ list(BQguess)
+ [TR_ss]
+ [TR_baseline]
)
sol = opt.root(
SS_fsolve,
@@ -1393,8 +1450,17 @@ def run_SS(p, client=None):
p_m_ss = sol.x[3 : 3 + p.M]
Yss = sol.x[3 + p.M]
BQss = sol.x[3 + p.M + 1 : -1]
TR_ss = sol.x[-1]
else:
ss_params_reform = (b_guess, n_guess, None, factor, p, client)
ss_params_reform = (
b_guess,
n_guess,
None,
None,
factor,
p,
client,
)
if p.use_zeta:
guesses = (
[r_p_guess, rguess, wguess]
@@ -1435,6 +1501,8 @@ def run_SS(p, client=None):
# Return SS values of variables
fsolve_flag = True
# Return SS values of variables
if not p.baseline_spending:
Ig_baseline = None
output = SS_solver(
b_guess,
n_guess,
@@ -1445,6 +1513,7 @@ def run_SS(p, client=None):
Yss,
BQss,
TR_ss,
Ig_baseline,
factor,
p,
client,
28 changes: 17 additions & 11 deletions ogcore/TPI.py
Original file line number Diff line number Diff line change
@@ -623,16 +623,6 @@ def run_TPI(p, client=None):
Y = np.zeros_like(K)
Y[: p.T] = firm.get_Y(K[: p.T], K_g[: p.T], L[: p.T], p, "TPI")
Y[p.T :] = ss_vars["Yss"]
I_g = np.ones_like(Y) * ss_vars["I_g_ss"]
if p.baseline_spending:
I_g[: p.T] = Ig_baseline[: p.T]
else:
I_g = fiscal.get_I_g(Y[: p.T], p.alpha_I[: p.T])
if p.baseline:
K_g0 = p.initial_Kg_ratio * Y[0]
else:
K_g0 = Kg0_baseline
K_g = fiscal.get_K_g(K_g0, I_g, p, "TPI")
# path for industry specific aggregates
K_vec_init = np.ones((p.T + p.S, p.M)) * ss_vars["K_vec_ss"].reshape(
1, p.M
@@ -697,20 +687,36 @@ def run_TPI(p, client=None):
D = np.zeros(p.T + p.S)
D_d = np.zeros(p.T + p.S)
D_f = np.zeros(p.T + p.S)
I_g = fiscal.get_I_g(Y[: p.T], None, p, "TPI")
else:
if p.baseline_spending:
# Will set to TRbaseline here, but will be updated in TPI loop
# with call to fiscal.get_TR
TR = np.concatenate(
(TRbaseline[: p.T], np.ones(p.S) * ss_vars["TR_ss"])
)
# Will set to Ig_baseline here, but will be updated in TPI loop
# with call to fiscal.get_I_g
I_g = np.concatenate(
(Ig_baseline[: p.T], np.ones(p.S) * ss_vars["I_g_ss"])
)
# Will set to Gbaseline here, but will be updated in TPI loop
# with call to fiscal.D_G_path, which also does closure rule
G = np.concatenate(
(Gbaseline[: p.T], np.ones(p.S) * ss_vars["Gss"])
)
else:
TR = p.alpha_T * Y
G = np.ones(p.T + p.S) * ss_vars["Gss"]
I_g = np.ones(p.T + p.S) * ss_vars["I_g_ss"]
D = np.ones(p.T + p.S) * ss_vars["Dss"]
D_d = D * ss_vars["D_d_ss"] / ss_vars["Dss"]
D_f = D * ss_vars["D_f_ss"] / ss_vars["Dss"]
if p.baseline:
K_g0 = p.initial_Kg_ratio * Y[0]
else:
K_g0 = Kg0_baseline
K_g = fiscal.get_K_g(K_g0, I_g, p, "TPI")
total_tax_revenue = np.ones(p.T + p.S) * ss_vars["total_tax_revenue"]

# Compute other interest rates
@@ -993,7 +999,7 @@ def run_TPI(p, client=None):
B[: p.T], K_demand_open_vec.sum(-1), D_d[: p.T], p.zeta_K[: p.T]
)
if not p.baseline_spending:
I_g = fiscal.get_I_g(Y[: p.T], p.alpha_I[: p.T])
I_g = fiscal.get_I_g(Y[: p.T], None, p, "TPI")
if p.baseline:
K_g0 = p.initial_Kg_ratio * Y[0]
K_g = fiscal.get_K_g(K_g0, I_g, p, "TPI")
2 changes: 1 addition & 1 deletion ogcore/__init__.py
Original file line number Diff line number Diff line change
@@ -20,4 +20,4 @@
from ogcore.txfunc import *
from ogcore.utils import *

__version__ = "0.13.0"
__version__ = "0.13.1"
72 changes: 69 additions & 3 deletions ogcore/default_parameters.json
Original file line number Diff line number Diff line change
@@ -729,8 +729,8 @@
}
},
"alpha_I": {
"title": "Exogenous fraction of GDP that goes towards government investment in infrastructure (public capital)",
"description": "Exogenous fraction of GDP that goes towards government investment in infrastructure (public capital)",
"title": "Exogenous fraction of GDP that goes towards government investment in infrastructure (public capital)when balanced budget is false",
"description": "Exogenous fraction of GDP that goes towards government investment in infrastructure (public capital) when balanced budget is false.",
"section_1": "Fiscal Policy Parameters",
"section_2": "Spending",
"notes": "",
@@ -739,7 +739,7 @@
"value": [
{
"value": [
0.00
0.0
]
}
],
@@ -750,6 +750,72 @@
}
}
},
"alpha_bs_T": {
"title": "Proportional adjustment to government transfers relative to baseline amount when budget balance is true",
"description": "Proportional adjustment to government transfers relative to baseline amount when budget balance is true. Set value for base year, click '+' to add value for next year. All future years not specified are set to last value entered.",
"section_1": "Fiscal Policy Parameters",
"section_2": "Spending",
"notes": "",
"type": "float",
"number_dims": 1,
"value": [
{
"value": [
1.0
]
}
],
"validators": {
"range": {
"min": 0.0,
"max": 99999e99
}
}
},
"alpha_bs_G": {
"title": "Proportional adjustment to government consumption expenditures relative to baseline amount when budget balance is true",
"description": "Proportional adjustment to government consumption expenditures relative to baseline amount when budget balance is true. Set value for base year, click '+' to add value for next year. All future years not specified are set to last value entered.",
"section_1": "Fiscal Policy Parameters",
"section_2": "Spending",
"notes": "",
"type": "float",
"number_dims": 1,
"value": [
{
"value": [
1.0
]
}
],
"validators": {
"range": {
"min": 0.0,
"max": 99999e99
}
}
},
"alpha_bs_I": {
"title": "Proportional adjustment to infrastructure (public capital) spending relative to baseline amount when balanced budget is true",
"description": "Proportional adjustment to infrastructure (public capital) spending relative to baseline amount when balanced budget is true.",
"section_1": "Fiscal Policy Parameters",
"section_2": "Spending",
"notes": "",
"type": "float",
"number_dims": 1,
"value": [
{
"value": [
1.0
]
}
],
"validators": {
"range": {
"min": 0.0,
"max": 99999e99
}
}
},
"rho_G": {
"title": "Speed of convergence to a stable government budget deficit for periods [tG1, tG2-1]",
"description": "Speed of convergence to a stable government budget deficit for periods [tG1, tG2-1].",
22 changes: 17 additions & 5 deletions ogcore/fiscal.py
Original file line number Diff line number Diff line change
@@ -78,7 +78,7 @@ def D_G_path(r_gov, dg_fixed_values, p):
D[0] = D0_baseline

if p.baseline_spending:
G = Gbaseline[: p.T]
G = p.alpha_bs_G[: p.T] * Gbaseline[: p.T]
else:
G = p.alpha_G[: p.T] * Y[: p.T]

@@ -340,7 +340,7 @@ def get_TR(
total_tax_revenue - agg_pension_outlays - G - UBI_outlays - I_g
)
elif p.baseline_spending:
new_TR = TR
new_TR = p.alpha_bs_T[-1] * TR
else:
if method == "SS":
new_TR = p.alpha_T[-1] * Y
@@ -375,7 +375,7 @@ def get_r_gov(r, p, method):
return r_gov


def get_I_g(Y, alpha_I):
def get_I_g(Y, Ig_baseline, p, method="SS"):
r"""
Find investment in public capital
@@ -384,12 +384,24 @@ def get_I_g(Y, alpha_I):
Args:
Y (array_like): aggregate output
alpha_I (array_like): percentage of output invested in public capital
Ig_baseline (array_like): public infrastructure investment in
the baseliine simulation
p (OG-Core Specifications object): model parameters
method (str): either 'SS' for steady-state or 'TPI' for transition path
Returns
I_g (array_like): investment in public capital
"""
I_g = alpha_I * Y
if p.baseline_spending:
if method == "SS":
I_g = p.alpha_bs_I[-1] * Ig_baseline
else:
I_g = p.alpha_bs_I[: p.T] * Ig_baseline
else:
if method == "SS":
I_g = p.alpha_I[-1] * Y
else:
I_g = p.alpha_I[: p.T] * Y

return I_g

3 changes: 3 additions & 0 deletions ogcore/parameters.py
Original file line number Diff line number Diff line change
@@ -159,6 +159,9 @@ def compute_default_params(self):
"alpha_G",
"alpha_T",
"alpha_I",
"alpha_bs_G",
"alpha_bs_T",
"alpha_bs_I",
"world_int_rate_annual",
"adjustment_factor_for_cit_receipts",
"tau_bq",
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -11,5 +11,5 @@ build-backend = "setuptools.build_meta"

[tool.black]
line-length = 79
target-version = ["py310", "py311"]
target-version = ["py311", "py312"]
include = '\.pyi?$'
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@

setuptools.setup(
name="ogcore",
version="0.13.0",
version="0.13.1",
author="Jason DeBacker and Richard W. Evans",
license="CC0 1.0 Universal (CC0 1.0) Public Domain Dedication",
description="A general equilibrium overlapping generations model for fiscal policy analysis",
80 changes: 68 additions & 12 deletions tests/test_SS.py
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ def dask_client():
guesses1 = np.array(
[0.06, 1.1, 0.2, 0.016, 0.02, 0.02, 0.01, 0.01, 0.02, 0.003, -0.07, 0.051]
)
args1 = (bssmat, nssmat, None, None, p1, None)
args1 = (bssmat, nssmat, None, None, None, p1, None)
expected1 = np.array(
[
-0.03640424626041604,
@@ -61,7 +61,7 @@ def dask_client():
guesses2 = np.array(
[0.06, 1.1, 0.2, 0.016, 0.02, 0.02, 0.01, 0.01, 0.02, 0.003, -0.07]
)
args2 = (bssmat, nssmat, None, 0.51, p2, None)
args2 = (bssmat, nssmat, None, None, 0.51, p2, None)
expected2 = np.array(
[
-0.0389819118896058,
@@ -87,7 +87,7 @@ def dask_client():
guesses3 = np.array(
[0.06, 1.1, 0.2, 0.016, 0.02, 0.02, 0.01, 0.01, 0.02, 0.003, -0.07]
)
args3 = (bssmat, nssmat, 0.13, 0.51, p3, None)
args3 = (bssmat, nssmat, 0.13, 0.0, 0.51, p3, None)
expected3 = np.array(
[
-0.042611174492217574,
@@ -110,7 +110,7 @@ def dask_client():
guesses4 = np.array(
[0.06, 1.1, 0.2, 0.016, 0.02, 0.02, 0.01, 0.01, 0.02, 0.003, -0.07, 0.051]
)
args4 = (bssmat, nssmat, None, None, p4, None)
args4 = (bssmat, nssmat, None, None, None, p4, None)
expected4 = np.array(
[
-0.04501723939772713,
@@ -135,7 +135,7 @@ def dask_client():
guesses5 = np.array(
[0.06, 1.1, 0.2, 0.016, 0.02, 0.02, 0.01, 0.01, 0.02, 0.003, -0.07, 0.051]
)
args5 = (bssmat, nssmat, None, 0.51, p5, None)
args5 = (bssmat, nssmat, None, None, 0.51, p5, None)
expected5 = np.array(
[
-0.02690768327226259,
@@ -162,7 +162,7 @@ def dask_client():
guesses6 = np.array(
[0.06, 1.1, 0.2, 0.016, 0.02, 0.02, 0.01, 0.01, 0.02, 0.003, -0.07, 0.051]
)
args6 = (bssmat, nssmat, None, None, p6, None)
args6 = (bssmat, nssmat, None, None, None, p6, None)
expected6 = np.array(
[
-0.051097905293268894,
@@ -196,7 +196,7 @@ def dask_client():
guesses7 = np.array(
[0.06, 1.1, 0.2, 0.016, 0.02, 0.02, 0.01, 0.01, 0.02, 0.003, -0.07, 0.051]
)
args7 = (bssmat, nssmat, None, None, p7, None)
args7 = (bssmat, nssmat, None, None, None, p7, None)
expected7 = np.array(
[
-0.06985935377445636,
@@ -247,7 +247,7 @@ def test_SS_fsolve(tmpdir, guesses, args, expected):
ensure that output returned matches what it has been before.
"""
# args =
(bssmat, nssmat, TR_ss, factor_ss, p, client) = args
(bssmat, nssmat, TR_ss, Ig_baseline, factor_ss, p, client) = args
p.baseline_dir = tmpdir
p.output_base = tmpdir

@@ -297,7 +297,7 @@ def test_SS_fsolve(tmpdir, guesses, args, expected):
filename4 = "SS_solver_outputs_baseline_small_open.pkl"


# Note that chaning the order in which these tests are run will cause
# Note that changing the order in which these tests are run will cause
# failures for the baseline spending=True tests which depend on the
# output of the baseline run just prior
@pytest.mark.parametrize(
@@ -336,6 +336,12 @@ def test_SS_solver(baseline, param_updates, filename, dask_client):
Yguess = 0.6376591201150815
p_m_guess = np.ones(p.M)

# for new Ig_baseline arg
if p.baseline_spending:
Ig_baseline = 0.0 # tests only have zero infrastructure
else:
Ig_baseline = None

test_dict = SS.SS_solver(
b_guess,
n_guess,
@@ -346,6 +352,7 @@ def test_SS_solver(baseline, param_updates, filename, dask_client):
Yguess,
BQguess,
TRguess,
Ig_baseline,
factorguess,
p,
dask_client,
@@ -406,6 +413,10 @@ def test_SS_solver_extra(baseline, param_updates, filename, dask_client):
else:
rguess = 0.06483431412921253
r_p_guess = rguess
if p.baseline_spending:
Ig_baseline = 0.0
else:
Ig_baseline = None
wguess = firm.get_w_from_r(rguess, p, "SS")
TRguess = 0.05738932081035772
factorguess = 139355.1547340256
@@ -423,6 +434,7 @@ def test_SS_solver_extra(baseline, param_updates, filename, dask_client):
Yguess,
BQguess,
TRguess,
Ig_baseline,
factorguess,
p,
dask_client,
@@ -518,9 +530,37 @@ def test_inner_loop(baseline, r_p, param_updates, filename, dask_client):
factor = 100000
BQ = np.ones(p.J) * 0.00019646295986015257
if p.budget_balance:
outer_loop_vars = (bssmat, nssmat, r_p, r, w, p_m, Y, BQ, TR, factor)
outer_loop_vars = (
bssmat,
nssmat,
r_p,
r,
w,
p_m,
Y,
BQ,
TR,
None,
factor,
)
else:
outer_loop_vars = (bssmat, nssmat, r_p, r, w, p_m, Y, BQ, TR, factor)
if p.baseline_spending:
Ig_baseline = 0.0
else:
Ig_baseline = None
outer_loop_vars = (
bssmat,
nssmat,
r_p,
r,
w,
p_m,
Y,
BQ,
TR,
Ig_baseline,
factor,
)
test_tuple = SS.inner_loop(outer_loop_vars, p, dask_client)

try:
@@ -623,7 +663,23 @@ def test_inner_loop_extra(baseline, param_updates, filename, dask_client):
BQ = np.ones(p.J) * 0.00019646295986015257
p_m = np.array([1.0])
r_p = 0.04260341179572245
outer_loop_vars = (bssmat, nssmat, r_p, r, w, p_m, Y, BQ, TR, factor)
if p.baseline_spending:
Ig_baseline = 0.0
else:
Ig_baseline = None
outer_loop_vars = (
bssmat,
nssmat,
r_p,
r,
w,
p_m,
Y,
BQ,
TR,
Ig_baseline,
factor,
)
test_tuple = SS.inner_loop(outer_loop_vars, p, dask_client)
expected_tuple = utils.safe_read_pickle(
os.path.join(CUR_PATH, "test_io_data", filename)
31 changes: 27 additions & 4 deletions tests/test_fiscal.py
Original file line number Diff line number Diff line change
@@ -276,14 +276,37 @@ def test_get_r_gov(r, p, method, r_gov_expected):
assert np.allclose(r_gov, r_gov_expected)


def test_get_I_g():
@pytest.mark.parametrize(
"baseline_spending,Ig_baseline,method",
[
(True, 3.5, "SS"),
(False, [3.5, 4.2], "TPI"),
(False, None, "SS"),
(False, None, "TPI"),
],
ids=["baseline spend, SS", "baseline spend, TPI", "SS", "TPI"],
)
def test_get_I_g(baseline_spending, Ig_baseline, method):
"""
Test function to determine investment in public capital
"""
p = Specifications()
p.baseline_spending = baseline_spending
Y = np.array([0.2, 4.0])
alpha_I = np.array([0.1, 0.5])
expected = np.array([0.02, 2.0])
test_val = fiscal.get_I_g(Y, alpha_I)
p.alpha_I = np.array([0.1, 0.5])
p.alpha_bs_I = np.array([0.1, 1.0])
if method == "SS":
test_val = fiscal.get_I_g(Y[-1], Ig_baseline, p, method)
if baseline_spending:
expected = np.array([3.5])
else:
expected = np.array([2.0])
else:
test_val = fiscal.get_I_g(Y, Ig_baseline, p, method)
if baseline_spending:
expected = np.array([0.35, 4.2])
else:
expected = np.array([0.02, 2.0])

assert np.allclose(test_val, expected)

Binary file modified tests/test_io_data/run_TPI_outputs_baseline_Kg_nonzero_2.pkl
Binary file not shown.

0 comments on commit 4ea91c9

Please sign in to comment.