Skip to content

Commit 70aa8ad

Browse files
authored
Merge pull request #83 from jdebacker/example_scripts
Merging
2 parents ad65aba + 6e28f61 commit 70aa8ad

File tree

3 files changed

+429
-0
lines changed

3 files changed

+429
-0
lines changed

examples/run_og_zaf_education.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# Need to fix references to Calculator, reform json, and substitute new tax
2+
# function call
3+
import multiprocessing
4+
from distributed import Client
5+
import os
6+
import json
7+
import time
8+
import copy
9+
import numpy as np
10+
import matplotlib.pyplot as plt
11+
from ogzaf.calibrate import Calibration
12+
from ogcore.parameters import Specifications
13+
from ogcore import output_tables as ot
14+
from ogcore import output_plots as op
15+
import ogcore
16+
from ogcore.execute import runner
17+
from ogcore.utils import safe_read_pickle
18+
19+
20+
# Use a custom matplotlib style file for plots
21+
plt.style.use("ogcore.OGcorePlots")
22+
23+
24+
def main():
25+
# Define parameters to use for multiprocessing
26+
num_workers = min(multiprocessing.cpu_count(), 7)
27+
client = Client(n_workers=num_workers, threads_per_worker=1)
28+
print("Number of workers = ", num_workers)
29+
30+
# Directories to save data
31+
CUR_DIR = os.path.dirname(os.path.realpath(__file__))
32+
save_dir = os.path.join(CUR_DIR, "OG-ZAF-Education")
33+
base_dir = os.path.join(save_dir, "OUTPUT_BASELINE")
34+
reform_dir = os.path.join(save_dir, "OUTPUT_EDUC")
35+
reform_dir2 = os.path.join(save_dir, "OUTPUT_EDUC_SPEND")
36+
37+
"""
38+
---------------------------------------------------------------------------
39+
Run baseline policy
40+
---------------------------------------------------------------------------
41+
"""
42+
# Set up baseline parameterization
43+
p = Specifications(
44+
baseline=True,
45+
num_workers=num_workers,
46+
baseline_dir=base_dir,
47+
output_base=base_dir,
48+
)
49+
# Update parameters for baseline from default json file
50+
p.update_specifications(
51+
json.load(
52+
open(
53+
os.path.join(
54+
CUR_DIR, "..", "ogzaf", "ogzaf_default_parameters.json"
55+
)
56+
)
57+
)
58+
)
59+
# move closure rule out to 50 years since educaation phases in over 20 years
60+
p.tG1 = 50
61+
62+
# Run model
63+
start_time = time.time()
64+
runner(p, time_path=True, client=client)
65+
print("run time = ", time.time() - start_time)
66+
67+
"""
68+
---------------------------------------------------------------------------
69+
Run counterfactual simulation
70+
---------------------------------------------------------------------------
71+
"""
72+
73+
# create new Specifications object for reform simulation
74+
p2 = copy.deepcopy(p)
75+
p2.baseline = False
76+
p2.output_base = reform_dir
77+
78+
# adjust labor productivity to account for education investment
79+
# Public spending may be able to obtain universal enrollment in Africa: https://www.inderscienceonline.com/doi/abs/10.1504/IJEED.2015.075794
80+
# no time for paper, but let's assume this increases productivity of those bottom 70% by 20% for all ages 20+
81+
# Let's assume this phases in linearly over 20 years
82+
num_years = 20 # 20 years to phase in
83+
total_benefit = 0.2 # total effect on productivity when fully phased in
84+
benefits = np.linspace(0, total_benefit, num_years)
85+
for t, benefit in enumerate(benefits):
86+
p2.e[t, :, :3] = p.e[t, :, :3] * (
87+
1 + benefit
88+
) # just apply to bottom 70%
89+
p2.e[num_years:, :, :3] = p.e[num_years:, :, :3] * (1 + total_benefit)
90+
91+
# Run sim with just the benefits of education
92+
start_time = time.time()
93+
runner(p2, time_path=True, client=client)
94+
print("run time = ", time.time() - start_time)
95+
96+
# Now increase spending and solve model again
97+
p3 = copy.deepcopy(p2)
98+
p3.baseline = False
99+
p3.output_base = reform_dir2
100+
# increase gov't spending to account for costs of education
101+
# Spending currently about 6.6% of GDP (source: https://data.worldbank.org/indicator/SE.XPD.TOTL.GD.ZS?locations=ZA)
102+
# Let's assume this increases to 10% of GDP
103+
p3.alpha_G = (
104+
p3.alpha_G + 0.034
105+
) # counterfactual 10% of GDP - current 6.6% of GDP
106+
start_time = time.time()
107+
runner(p3, time_path=True, client=client)
108+
print("run time = ", time.time() - start_time)
109+
client.close()
110+
111+
"""
112+
---------------------------------------------------------------------------
113+
Save some results of simulations
114+
---------------------------------------------------------------------------
115+
"""
116+
base_tpi = safe_read_pickle(os.path.join(base_dir, "TPI", "TPI_vars.pkl"))
117+
base_params = safe_read_pickle(os.path.join(base_dir, "model_params.pkl"))
118+
reform_tpi = safe_read_pickle(
119+
os.path.join(reform_dir, "TPI", "TPI_vars.pkl")
120+
)
121+
reform_params = safe_read_pickle(
122+
os.path.join(reform_dir, "model_params.pkl")
123+
)
124+
ans = ot.macro_table(
125+
base_tpi,
126+
base_params,
127+
reform_tpi=reform_tpi,
128+
reform_params=reform_params,
129+
var_list=["Y", "C", "K", "L", "r", "w"],
130+
output_type="pct_diff",
131+
num_years=10,
132+
start_year=base_params.start_year,
133+
)
134+
135+
# create plots of output
136+
op.plot_all(
137+
base_dir, reform_dir, os.path.join(save_dir, "OG-ZAF_example_plots")
138+
)
139+
140+
print("Percentage changes in aggregates:", ans)
141+
# save percentage change output to csv file
142+
ans.to_csv(os.path.join(save_dir, "ogzaf_example_output.csv"))
143+
144+
145+
if __name__ == "__main__":
146+
# execute only if run as a script
147+
main()
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Need to fix references to Calculator, reform json, and substitute new tax
2+
# function call
3+
import multiprocessing
4+
from distributed import Client
5+
import importlib.resources
6+
import os
7+
import json
8+
import time
9+
import copy
10+
import numpy as np
11+
12+
# from taxcalc import Calculator
13+
from ogzaf.calibrate import Calibration
14+
from ogcore.parameters import Specifications
15+
from ogcore import output_tables as ot
16+
from ogcore import output_plots as op
17+
from ogcore.execute import runner
18+
from ogcore.utils import safe_read_pickle
19+
20+
21+
def main():
22+
# Define parameters to use for multiprocessing
23+
client = Client()
24+
num_workers = min(multiprocessing.cpu_count(), 7)
25+
print("Number of workers = ", num_workers)
26+
27+
# Directories to save data
28+
CUR_DIR = os.path.dirname(os.path.realpath(__file__))
29+
base_dir = os.path.join(CUR_DIR, "OG-ZAF-CIT_Example", "OUTPUT_BASELINE")
30+
reform_dir = os.path.join(CUR_DIR, "OG-ZAF-CIT_Example", "OUTPUT_REFORM")
31+
32+
"""
33+
---------------------------------------------------------------------------
34+
Run baseline policy
35+
---------------------------------------------------------------------------
36+
"""
37+
# Set up baseline parameterization
38+
p = Specifications(
39+
baseline=True,
40+
num_workers=num_workers,
41+
baseline_dir=base_dir,
42+
output_base=base_dir,
43+
)
44+
# Update parameters for baseline from default json file
45+
with importlib.resources.open_text(
46+
"ogzaf", "ogzaf_default_parameters.json"
47+
) as file:
48+
defaults = json.load(file)
49+
p.update_specifications(defaults)
50+
# Update parameters from calibrate.py Calibration class for multiple industries
51+
p.M = 4
52+
p.I = 5
53+
c = Calibration(p)
54+
updated_params = c.get_dict()
55+
p.update_specifications(updated_params)
56+
updated_params_tax = {
57+
"cit_rate": [[0.27, 0.27, 0.27, 0.27]],
58+
# order of industries is primary, energy, tertiary, secondary ex energy
59+
"Z": [[0.5, 0.4, 1.7, 1.0]],
60+
"epsilon": [1.0, 1.0, 1.0, 1.0],
61+
"gamma": [0.67, 0.50, 0.45, 0.53],
62+
"gamma_g": [0.0, 0.0, 0.0, 0.0],
63+
"alpha_c": c.alpha_c,
64+
"io_matrix": c.io_matrix,
65+
"tG1": 23,
66+
"debt_ratio_ss": 1.8,
67+
}
68+
p.update_specifications(updated_params_tax)
69+
70+
# Run model
71+
start_time = time.time()
72+
runner(p, time_path=True, client=client)
73+
print("run time = ", time.time() - start_time)
74+
75+
"""
76+
---------------------------------------------------------------------------
77+
Run reform policy
78+
---------------------------------------------------------------------------
79+
"""
80+
81+
# create new Specifications object for reform simulation
82+
p2 = copy.deepcopy(p)
83+
p2.baseline = False
84+
p2.output_base = reform_dir
85+
86+
# additional parameters to change
87+
updated_params_ref = {
88+
"cit_rate": [[0.25, 0.25, 0.25, 0.25]],
89+
"baseline_spending": True,
90+
}
91+
p2.update_specifications(updated_params_ref)
92+
93+
# Run model
94+
start_time = time.time()
95+
runner(p2, time_path=True, client=client)
96+
print("run time = ", time.time() - start_time)
97+
client.close()
98+
99+
"""
100+
---------------------------------------------------------------------------
101+
Save some results of simulations
102+
---------------------------------------------------------------------------
103+
"""
104+
base_tpi = safe_read_pickle(os.path.join(base_dir, "TPI", "TPI_vars.pkl"))
105+
base_params = safe_read_pickle(os.path.join(base_dir, "model_params.pkl"))
106+
reform_tpi = safe_read_pickle(
107+
os.path.join(reform_dir, "TPI", "TPI_vars.pkl")
108+
)
109+
reform_params = safe_read_pickle(
110+
os.path.join(reform_dir, "model_params.pkl")
111+
)
112+
ans = ot.macro_table(
113+
base_tpi,
114+
base_params,
115+
reform_tpi=reform_tpi,
116+
reform_params=reform_params,
117+
var_list=["Y", "C", "K", "L", "r", "w"],
118+
output_type="pct_diff",
119+
num_years=10,
120+
start_year=base_params.start_year,
121+
)
122+
123+
# create plots of output
124+
op.plot_all(
125+
base_dir,
126+
reform_dir,
127+
os.path.join(CUR_DIR, "OG-ZAF_CIT_multi_industry_plots"),
128+
)
129+
130+
print("Percentage changes in aggregates:", ans)
131+
# save percentage change output to csv file
132+
ans.to_csv("ogzaf_CIT_multi_industry_output.csv")
133+
134+
135+
if __name__ == "__main__":
136+
# execute only if run as a script
137+
main()

0 commit comments

Comments
 (0)