Skip to content

Commit 7ef8cac

Browse files
Merge pull request #41 from PolicyEngine/api-parity
Add some API impacts
2 parents 8cf7ce0 + 3cafefd commit 7ef8cac

File tree

11 files changed

+231
-98
lines changed

11 files changed

+231
-98
lines changed

.github/workflows/pr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
pip install furo
2222
2323
- name: Generate documentation
24-
run: make docs
24+
run: make documentation
2525

2626
- name: Check documentation build
2727
run: |

.github/workflows/push.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ jobs:
2121
pip install furo
2222
pip install sphinx-argparse
2323
24-
25-
2624
- name: Generate documentation
2725
run: make documentation
2826

docs/_toc.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@ root: index
33
parts:
44
- caption: Maintenance
55
chapters:
6-
- file: maintaining
6+
- file: maintaining
7+
- caption: Schema
8+
chapters:
9+
- file: schema

docs/schema.ipynb

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Schema\n",
8+
"\n",
9+
"This page contains examples of the schema of the returned simulation outputs for given types of simulation. Each subsection specifies the country, scope and whether a reform has been passed. The schema is given in YAML format.\n",
10+
"\n",
11+
"## UK, macro, reform-comparison"
12+
]
13+
},
14+
{
15+
"cell_type": "code",
16+
"execution_count": 1,
17+
"metadata": {
18+
"tags": [
19+
"hide-input"
20+
]
21+
},
22+
"outputs": [
23+
{
24+
"data": {
25+
"text/markdown": [
26+
"```yaml\n",
27+
"macro:\n",
28+
" baseline:\n",
29+
" gov:\n",
30+
" balance:\n",
31+
" total_gov_spending: <class 'numpy.float64'>\n",
32+
" total_state_tax: <class 'int'>\n",
33+
" total_tax_revenue: <class 'numpy.float64'>\n",
34+
" programs:\n",
35+
" child_benefit: <class 'numpy.float64'>\n",
36+
" council_tax: <class 'numpy.float64'>\n",
37+
" fuel_duty: <class 'numpy.float64'>\n",
38+
" income_tax: <class 'numpy.float64'>\n",
39+
" national_insurance: <class 'numpy.float64'>\n",
40+
" ni_employer: <class 'numpy.float64'>\n",
41+
" pension_credit: <class 'numpy.float64'>\n",
42+
" state_pension: <class 'numpy.float64'>\n",
43+
" tax_credits: <class 'numpy.float64'>\n",
44+
" universal_credit: <class 'numpy.float64'>\n",
45+
" vat: <class 'numpy.float64'>\n",
46+
" household:\n",
47+
" demographic_values:\n",
48+
" household_count_people: <class 'list'>\n",
49+
" household_weight: <class 'list'>\n",
50+
" person_weight: <class 'list'>\n",
51+
" comparison:\n",
52+
" revenue_impact:\n",
53+
" tax_revenues: <class 'numpy.float64'>\n",
54+
" reform:\n",
55+
" gov:\n",
56+
" balance:\n",
57+
" total_gov_spending: <class 'numpy.float64'>\n",
58+
" total_state_tax: <class 'int'>\n",
59+
" total_tax_revenue: <class 'numpy.float64'>\n",
60+
" programs:\n",
61+
" child_benefit: <class 'numpy.float64'>\n",
62+
" council_tax: <class 'numpy.float64'>\n",
63+
" fuel_duty: <class 'numpy.float64'>\n",
64+
" income_tax: <class 'numpy.float64'>\n",
65+
" national_insurance: <class 'numpy.float64'>\n",
66+
" ni_employer: <class 'numpy.float64'>\n",
67+
" pension_credit: <class 'numpy.float64'>\n",
68+
" state_pension: <class 'numpy.float64'>\n",
69+
" tax_credits: <class 'numpy.float64'>\n",
70+
" universal_credit: <class 'numpy.float64'>\n",
71+
" vat: <class 'numpy.float64'>\n",
72+
" household:\n",
73+
" demographic_values:\n",
74+
" household_count_people: <class 'list'>\n",
75+
" household_weight: <class 'list'>\n",
76+
" person_weight: <class 'list'>\n",
77+
"\n",
78+
"```"
79+
],
80+
"text/plain": [
81+
"<IPython.core.display.Markdown object>"
82+
]
83+
},
84+
"execution_count": 1,
85+
"metadata": {},
86+
"output_type": "execute_result"
87+
}
88+
],
89+
"source": [
90+
"from policyengine import Simulation\n",
91+
"from IPython.display import Markdown\n",
92+
"import yaml\n",
93+
"\n",
94+
"def replace_value_with_dtype(tree):\n",
95+
" for key in tree:\n",
96+
" if isinstance(tree[key], dict):\n",
97+
" replace_value_with_dtype(tree[key])\n",
98+
" else:\n",
99+
" tree[key] = str(type(tree[key]))\n",
100+
" return tree\n",
101+
"\n",
102+
"sim = Simulation(\n",
103+
" country=\"uk\",\n",
104+
" scope=\"macro\",\n",
105+
" time_period=2025,\n",
106+
" reform={\n",
107+
" \"gov.hmrc.income_tax.allowances.personal_allowance.amount\": {\n",
108+
" \"2025\": 0,\n",
109+
" }\n",
110+
" }\n",
111+
")\n",
112+
"sim.calculate(\"macro\")\n",
113+
"tree = replace_value_with_dtype(sim.outputs)\n",
114+
"\n",
115+
"Markdown('```yaml\\n' + yaml.dump(tree, indent=2) + '\\n```')"
116+
]
117+
}
118+
],
119+
"metadata": {
120+
"kernelspec": {
121+
"display_name": "base",
122+
"language": "python",
123+
"name": "python3"
124+
},
125+
"language_info": {
126+
"codemirror_mode": {
127+
"name": "ipython",
128+
"version": 3
129+
},
130+
"file_extension": ".py",
131+
"mimetype": "text/x-python",
132+
"name": "python",
133+
"nbconvert_exporter": "python",
134+
"pygments_lexer": "ipython3",
135+
"version": "3.10.14"
136+
}
137+
},
138+
"nbformat": 4,
139+
"nbformat_minor": 2
140+
}

policyengine/outputs/macro/comparison/revenue_impact.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ def revenue_impact(simulation: Simulation):
1010
Returns:
1111
float: The revenue impact of the simulation.
1212
"""
13-
tax_revenue_baseline = simulation.calculate("macro/baseline/tax_revenue")
14-
tax_revenue_reform = simulation.calculate("macro/reform/tax_revenue")
15-
return tax_revenue_reform - tax_revenue_baseline
13+
tax_revenue_baseline = simulation.calculate(
14+
"macro/baseline/gov/balance"
15+
)["total_tax_revenue"]
16+
tax_revenue_reform = simulation.calculate(
17+
"macro/reform/gov/balance"
18+
)["total_tax_revenue"]
19+
tax_revenue_impact = tax_revenue_reform - tax_revenue_baseline
20+
return {
21+
"tax_revenues": tax_revenue_impact,
22+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from policyengine import Simulation
2+
3+
4+
def balance(simulation: Simulation) -> dict:
5+
sim = simulation.baseline
6+
if simulation.country == "uk":
7+
total_tax = sim.calculate("gov_tax").sum()
8+
total_spending = sim.calculate("gov_spending").sum()
9+
total_state_tax = 0
10+
elif simulation.country == "us":
11+
total_tax = sim.calculate("household_tax").sum()
12+
total_spending = sim.calculate("household_benefits").sum()
13+
total_state_tax = simulation.calculate(
14+
"household_state_income_tax"
15+
).sum()
16+
return {
17+
"total_tax_revenue": total_tax,
18+
"total_gov_spending": total_spending,
19+
"total_state_tax": total_state_tax,
20+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from policyengine import Simulation
2+
from dataclasses import dataclass
3+
4+
5+
@dataclass
6+
class UKProgram:
7+
name: str
8+
is_positive: bool
9+
10+
11+
class UKPrograms:
12+
PROGRAMS = [
13+
UKProgram("income_tax", True),
14+
UKProgram("national_insurance", True),
15+
UKProgram("vat", True),
16+
UKProgram("council_tax", True),
17+
UKProgram("fuel_duty", True),
18+
UKProgram("tax_credits", False),
19+
UKProgram("universal_credit", False),
20+
UKProgram("child_benefit", False),
21+
UKProgram("state_pension", False),
22+
UKProgram("pension_credit", False),
23+
UKProgram("ni_employer", True),
24+
]
25+
26+
27+
def programs(simulation: Simulation) -> dict:
28+
if simulation.country == "uk":
29+
return {
30+
program.name: simulation.baseline.calculate(
31+
program.name, map_to="household"
32+
).sum()
33+
* (1 if program.is_positive else -1)
34+
for program in UKPrograms.PROGRAMS
35+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from policyengine import Simulation
2+
3+
4+
def demographic_values(simulation: Simulation) -> dict:
5+
sim = simulation.baseline
6+
household_count_people = (
7+
sim.calculate("household_count_people").astype(int).tolist()
8+
)
9+
person_weight = sim.calculate("person_weight").astype(float).tolist()
10+
household_weight = sim.calculate("household_weight").astype(float).tolist()
11+
return {
12+
"household_count_people": household_count_people,
13+
"person_weight": person_weight,
14+
"household_weight": household_weight,
15+
}

policyengine/outputs/macro/single/tax_revenue.py

Lines changed: 0 additions & 2 deletions
This file was deleted.

policyengine/simulation.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,15 @@ def calculate(self, output: str):
7373
"""
7474
if output.endswith("/"):
7575
output = output[:-1]
76+
77+
if output == "":
78+
output = list(self.outputs.keys())[0]
7679

7780
node = self.outputs
7881

82+
for child_key in output.split("/")[:-1]:
83+
node = node[child_key]
84+
7985
parent = node
8086
child_key = output.split("/")[-1]
8187
node = parent[child_key]

test.ipynb

Lines changed: 0 additions & 89 deletions
This file was deleted.

0 commit comments

Comments
 (0)