Skip to content

Commit

Permalink
Merge pull request PSLmodels#861 from jdebacker/tax_lists
Browse files Browse the repository at this point in the history
Merging
  • Loading branch information
rickecon authored Mar 31, 2023
2 parents 31a0d66 + c2262e8 commit c8121de
Show file tree
Hide file tree
Showing 14 changed files with 313 additions and 143 deletions.
70 changes: 45 additions & 25 deletions ogcore/SS.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ def euler_equation_solver(guesses, *args):
theta,
p.e[:, j],
p.rho,
p.etr_params[-1, :, :],
p.mtry_params[-1, :, :],
p.etr_params[-1],
p.mtry_params[-1],
None,
j,
p,
Expand All @@ -101,8 +101,8 @@ def euler_equation_solver(guesses, *args):
theta,
p.chi_n,
p.e[:, j],
p.etr_params[-1, :, :],
p.mtrx_params[-1, :, :],
p.etr_params[-1],
p.mtrx_params[-1],
None,
j,
p,
Expand Down Expand Up @@ -139,7 +139,7 @@ def euler_equation_solver(guesses, *args):
False,
"SS",
p.e[:, j],
p.etr_params[-1, :, :],
p.etr_params[-1],
p,
)
cons = household.get_cons(
Expand Down Expand Up @@ -270,10 +270,14 @@ def inner_loop(outer_loop_vars, p, client):

theta = tax.replacement_rate_vals(nssmat, w, factor, None, p)

etr_params_3D = np.tile(
np.reshape(p.etr_params[-1, :, :], (p.S, 1, p.etr_params.shape[2])),
(1, p.J, 1),
)
num_params = len(p.etr_params[-1][0])
etr_params_3D = [
[
[p.etr_params[-1][s][i] for i in range(num_params)]
for j in range(p.J)
]
for s in range(p.S)
]

net_tax = tax.net_taxes(
r_p,
Expand Down Expand Up @@ -398,10 +402,15 @@ def inner_loop(outer_loop_vars, p, client):
new_p_i = np.dot(p.io_matrix, new_p_m)
new_p_tilde = aggr.get_ptilde(new_p_i, p.tau_c[-1, :], p.alpha_c)

etr_params_3D = np.tile(
np.reshape(p.etr_params[-1, :, :], (p.S, 1, p.etr_params.shape[2])),
(1, p.J, 1),
)
num_params = len(p.etr_params[-1][0])
etr_params_3D = [
[
[p.etr_params[-1][s][i] for i in range(num_params)]
for j in range(p.J)
]
for s in range(p.S)
]

taxss = tax.net_taxes(
new_r_p,
new_w,
Expand Down Expand Up @@ -710,18 +719,29 @@ def SS_solver(
theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, None, p)

# Compute effective and marginal tax rates for all agents
etr_params_3D = np.tile(
np.reshape(p.etr_params[-1, :, :], (p.S, 1, p.etr_params.shape[2])),
(1, p.J, 1),
)
mtrx_params_3D = np.tile(
np.reshape(p.mtrx_params[-1, :, :], (p.S, 1, p.mtrx_params.shape[2])),
(1, p.J, 1),
)
mtry_params_3D = np.tile(
np.reshape(p.mtry_params[-1, :, :], (p.S, 1, p.mtry_params.shape[2])),
(1, p.J, 1),
)
num_params = len(p.etr_params[-1][0])
etr_params_3D = [
[
[p.etr_params[-1][s][i] for i in range(num_params)]
for j in range(p.J)
]
for s in range(p.S)
]
mtrx_params_3D = [
[
[p.mtrx_params[-1][s][i] for i in range(num_params)]
for j in range(p.J)
]
for s in range(p.S)
]
mtry_params_3D = [
[
[p.mtry_params[-1][s][i] for i in range(num_params)]
for j in range(p.J)
]
for s in range(p.S)
]

labor_noncompliance_rate_2D = np.tile(
np.reshape(p.labor_income_tax_noncompliance_rate[-1, :], (1, p.J)),
(p.S, 1),
Expand Down
144 changes: 88 additions & 56 deletions ogcore/TPI.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ def firstdoughnutring(
theta[j],
p.e[-1, j],
p.rho[-1],
p.etr_params[0, -1, :],
p.mtry_params[0, -1, :],
p.etr_params[0][-1],
p.mtry_params[0][-1],
None,
j,
p,
Expand All @@ -178,8 +178,8 @@ def firstdoughnutring(
theta[j],
p.chi_n[-1],
p.e[-1, j],
p.etr_params[0, -1, :],
p.mtrx_params[0, -1, :],
p.etr_params[0][-1],
p.mtrx_params[0][-1],
None,
j,
p,
Expand Down Expand Up @@ -231,12 +231,12 @@ def twist_doughnut(
j (int): index of ability type
s (int): years of life remaining
t (int): model period
etr_params (Numpy array): ETR function parameters,
size = sxsxnum_params
mtrx_params (Numpy array): labor income MTR function parameters,
size = sxsxnum_params
mtry_params (Numpy array): capital income MTR function
parameters, size = sxsxnum_params
etr_params (list): ETR function parameters,
list of lists with size = sxsxnum_params
mtrx_params (list): labor income MTR function parameters,
list of lists with size = sxsxnum_params
mtry_params (list): capital income MTR function
parameters, lists of lists with size = sxsxnum_params
initial_b (Numpy array): savings of agents alive at T=0,
size = SxJ
p (OG-Core Specifications object): model parameters
Expand Down Expand Up @@ -408,22 +408,29 @@ def inner_loop(guesses, outer_loop_vars, initial_values, ubi, j, ind, p):
tr_to_use = np.diag(tr[: p.S, :, j], p.S - (s + 2))
ubi_to_use = np.diag(ubi[: p.S, :, j], p.S - (s + 2))

length_diag = np.diag(p.etr_params[: p.S, :, 0], p.S - (s + 2)).shape[
0
num_params = len(p.etr_params[0][0])
temp_etr = [
[p.etr_params[t][p.S - s - 2 + t][i] for i in range(num_params)]
for t in range(s + 2)
]
etr_params_to_use = np.zeros((length_diag, p.etr_params.shape[2]))
mtrx_params_to_use = np.zeros((length_diag, p.mtrx_params.shape[2]))
mtry_params_to_use = np.zeros((length_diag, p.mtry_params.shape[2]))
for i in range(p.etr_params.shape[2]):
etr_params_to_use[:, i] = np.diag(
p.etr_params[: p.S, :, i], p.S - (s + 2)
)
mtrx_params_to_use[:, i] = np.diag(
p.mtrx_params[: p.S, :, i], p.S - (s + 2)
)
mtry_params_to_use[:, i] = np.diag(
p.mtry_params[: p.S, :, i], p.S - (s + 2)
)
etr_params_to_use = [
[temp_etr[i][j] for j in range(num_params)] for i in range(s + 2)
]
temp_mtrx = [
[p.mtrx_params[t][p.S - s - 2 + t][i] for i in range(num_params)]
for t in range(s + 2)
]
mtrx_params_to_use = [
[temp_mtrx[i][j] for j in range(num_params)] for i in range(s + 2)
]
temp_mtry = [
[p.mtry_params[t][p.S - s - 2 + t][i] for i in range(num_params)]
for t in range(s + 2)
]
mtry_params_to_use = [
[temp_mtry[i][j] for j in range(num_params)] for i in range(s + 2)
]

solutions = opt.root(
twist_doughnut,
list(b_guesses_to_use) + list(n_guesses_to_use),
Expand Down Expand Up @@ -463,19 +470,19 @@ def inner_loop(guesses, outer_loop_vars, initial_values, ubi, j, ind, p):
ubi_to_use = np.diag(ubi[t : t + p.S, :, j])

# initialize array of diagonal elements
length_diag = np.diag(p.etr_params[t : t + p.S, :, 0]).shape[0]
etr_params_to_use = np.zeros((length_diag, p.etr_params.shape[2]))
mtrx_params_to_use = np.zeros((length_diag, p.mtrx_params.shape[2]))
mtry_params_to_use = np.zeros((length_diag, p.mtry_params.shape[2]))

for i in range(p.etr_params.shape[2]):
etr_params_to_use[:, i] = np.diag(p.etr_params[t : t + p.S, :, i])
mtrx_params_to_use[:, i] = np.diag(
p.mtrx_params[t : t + p.S, :, i]
)
mtry_params_to_use[:, i] = np.diag(
p.mtry_params[t : t + p.S, :, i]
)
num_params = len(p.etr_params[t][0])
etr_params_to_use = [
[p.etr_params[t + s][s][i] for i in range(num_params)]
for s in range(p.S)
]
mtrx_params_to_use = [
[p.mtrx_params[t + s][s][i] for i in range(num_params)]
for s in range(p.S)
]
mtry_params_to_use = [
[p.mtry_params[t + s][s][i] for i in range(num_params)]
for s in range(p.S)
]

solutions = opt.root(
twist_doughnut,
Expand Down Expand Up @@ -753,12 +760,18 @@ def run_TPI(p, client=None):
bmat_splus1 = np.zeros((p.T, p.S, p.J))
bmat_splus1[:, :, :] = b_mat[: p.T, :, :]

etr_params_4D = np.tile(
p.etr_params[: p.T, :, :].reshape(
p.T, p.S, 1, p.etr_params.shape[2]
),
(1, 1, p.J, 1),
)
num_params = len(p.etr_params[0][0])
etr_params_4D = [
[
[
[p.etr_params[t][s][i] for i in range(num_params)]
for j in range(p.J)
]
for s in range(p.S)
]
for t in range(p.T)
]

bqmat = household.get_bq(BQ, None, p, "TPI")
trmat = household.get_tr(TR, None, p, "TPI")
tax_mat = tax.net_taxes(
Expand Down Expand Up @@ -1087,18 +1100,37 @@ def run_TPI(p, client=None):
print("\tDistance:", TPIdist)

# Compute effective and marginal tax rates for all agents
mtrx_params_4D = np.tile(
p.mtrx_params[: p.T, :, :].reshape(
p.T, p.S, 1, p.mtrx_params.shape[2]
),
(1, 1, p.J, 1),
)
mtry_params_4D = np.tile(
p.mtry_params[: p.T, :, :].reshape(
p.T, p.S, 1, p.mtry_params.shape[2]
),
(1, 1, p.J, 1),
)
num_params = len(p.mtrx_params[0][0])
etr_params_4D = [
[
[
[p.etr_params[t][s][i] for i in range(num_params)]
for j in range(p.J)
]
for s in range(p.S)
]
for t in range(p.T)
]
mtrx_params_4D = [
[
[
[p.mtrx_params[t][s][i] for i in range(num_params)]
for j in range(p.J)
]
for s in range(p.S)
]
for t in range(p.T)
]
mtry_params_4D = [
[
[
[p.mtry_params[t][s][i] for i in range(num_params)]
for j in range(p.J)
]
for s in range(p.S)
]
for t in range(p.T)
]
labor_noncompliance_rate_3D = np.tile(
np.reshape(
p.labor_income_tax_noncompliance_rate[: p.T, :], (p.T, 1, p.J)
Expand Down
2 changes: 1 addition & 1 deletion ogcore/aggregates.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ def revenue(
ubi (array_like): universal basic income household distributions
theta (Numpy array): social security replacement rate for each
lifetime income group
etr_params (Numpy array): parameters of the effective tax rate
etr_params (list): list of parameters of the effective tax rate
functions
p (OG-Core Specifications object): model parameters
method (str): adjusts calculation dimensions based on 'SS' or
Expand Down
6 changes: 5 additions & 1 deletion ogcore/default_parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"labels": {},
"additional_members": {
"section_1": {"type": "str"},
"section_2": {"type": "str"}
"section_2": {"type": "str"},
"array_first": {"type": "bool"}
}
},
"frisch": {
Expand Down Expand Up @@ -3584,6 +3585,7 @@
"notes": "",
"type": "float",
"number_dims": 3,
"array_first": false,
"value": [
{
"value": [
Expand All @@ -3605,6 +3607,7 @@
"notes": "",
"type": "float",
"number_dims": 3,
"array_first": false,
"value": [
{
"value": [
Expand All @@ -3626,6 +3629,7 @@
"notes": "",
"type": "float",
"number_dims": 3,
"array_first": false,
"value": [
{
"value": [
Expand Down
8 changes: 4 additions & 4 deletions ogcore/household.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,9 +361,9 @@ def FOC_savings(
lifetime income group
e (Numpy array): effective labor units
rho (Numpy array): mortality rates
etr_params (Numpy array): parameters of the effective tax rate
etr_params (list): parameters of the effective tax rate
functions
mtry_params (Numpy array): parameters of the marginal tax rate
mtry_params (list): parameters of the marginal tax rate
on capital income functions
t (int): model period
j (int): index of ability type
Expand Down Expand Up @@ -530,9 +530,9 @@ def FOC_labor(
chi_n (Numpy array): utility weight on the disutility of labor
supply
e (Numpy array): effective labor units
etr_params (Numpy array): parameters of the effective tax rate
etr_params (list): parameters of the effective tax rate
functions
mtrx_params (Numpy array): parameters of the marginal tax rate
mtrx_params (list): parameters of the marginal tax rate
on labor income functions
t (int): model period
j (int): index of ability type
Expand Down
9 changes: 2 additions & 7 deletions ogcore/parameter_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,7 @@ def plot_2D_taxfunc(
if len(tax_func_type) < len(tax_param_list):
tax_func_type = [tax_func_type[0]] * len(tax_param_list)
for i, v in enumerate(tax_func_type):
assert v in ["DEP", "DEP_totalinc", "GS", "linear"]
assert v in ["DEP", "DEP_totalinc", "GS", "linear", "mono"]
assert rate_type in ["etr", "mtrx", "mtry"]
assert len(tax_param_list) == len(labels)

Expand Down Expand Up @@ -1118,13 +1118,8 @@ def plot_2D_taxfunc(
# get tax rates for each point in the income support and plot
fig, ax = plt.subplots()
for i, tax_params in enumerate(tax_param_list):
if tax_func_type[i] == "mono":
tax_params = tax_params[rate_key][s][t][0]
else:
tax_param_array = np.array(tax_params[rate_key])
tax_params = tax_param_array[s, t, :]
tax_params = tax_params[rate_key][s][t]
rates = txfunc.get_tax_rates(
# tax_params[rate_key][s, t, :],
tax_params,
X,
Y,
Expand Down
Loading

0 comments on commit c8121de

Please sign in to comment.