Skip to content

Commit ab0321f

Browse files
committed
GEP 10: unit fixes for arbeitslosengeld_2/wohngeld + bump ttsim to 4dc065aa
- restore eg→bg transfer cast in anspruchshöhe_m; berechtigte_wohnfläche cast-free via the schedule param-function output unit + max/min shim - wohngeld basisbetrag/anspruchshöhe/betrag chain to .PER_WTHH; drop redundant casts - wohngeld EUR-only heating/climate lookups: raw output_unit -> _PER_HH, drop casts
1 parent 90237e8 commit ab0321f

122 files changed

Lines changed: 1135 additions & 1076 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGES.md

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,8 @@ All releases are available on [Anaconda.org](https://anaconda.org/conda-forge/ge
1515

1616
## Unreleased
1717

18-
- {gh}`1192` Annotate the taxes and transfers system with units and dimensions (GEP 10).
19-
Every `@policy_function`, `@policy_input`, `@param_function` and
20-
`@group_creation_function` declares a unit, as does every parameter in the YAML files.
21-
The euro is registered as the base currency and the Deutsche Mark relative to it, so
22-
that policy dates before 2002 compute in the currency of their day.
23-
({ghuser}`MImmesberger`)
24-
- {gh}`1192` Rename columns whose name did not match the quantity they carry. Most gain
25-
the suffix of the period they are measured over: `basistarif`, `splittingtarif`,
18+
- {gh}`1212` GEP 10 Rollout and some related column renamings: Most gain the suffix of
19+
the period they are measured over: `basistarif`, `splittingtarif`,
2620
`tarif_klassen_5_und_6` (and their `_mit_kinderfreibetrag` variants),
2721
`einkommensgrenze_ohne_geschwisterbonus` (and its two age variants),
2822
`vorsorge_arbeitslosenversicherungsbeiträge`,
@@ -33,8 +27,7 @@ All releases are available on [Anaconda.org](https://anaconda.org/conda-forge/ge
3327
`satz` all gain `_m`. Two lose a suffix they should never have had, being shares
3428
rather than flows: `anteil_steuerfälliger_einnahmen_y` and
3529
`mehrbedarf_alleinerziehend_m`. `gesamteinkommen_y` becomes `gesamteinkommen_y_sn`,
36-
naming the level it is aggregated to. There are no aliases; the old names are gone.
37-
({ghuser}`MImmesberger`)
30+
naming the level it is aggregated to. ({ghuser}`MImmesberger`)
3831
- {gh}`1206` Update Rentenwert 2025, 2026. ({ghuser}`cmdr-majus`)
3932
- {gh}`1156` Collection of all Grundsicherung im Alter / Wohngeld PRs ({gh}`1163`,
4033
{gh}`1167`, {gh}`1164`, {gh}`1159`, {gh}`1154`, {gh}`1155`, {gh}`1178`).

docs/geps/params-schema.json

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
2-
"$comment": "If you change this file, always change it in both locations: 1. ttsim/src/ttsim/params-schema.json 2. gettsim/docs/geps/params-schema.json",
2+
"$comment": "Keep in sync with ttsim/src/ttsim/params-schema.json, except unitToken: this GETTSIM copy pins the grouping levels to Germany's, ttsim leaves them open.",
33
"$schema": "http://json-schema.org/draft-07/schema#",
44
"definitions": {
55
"unitToken": {
6-
"$comment": "A fully-spelled compositional unit (GEP 10): a base optionally divided by an area, a period, and a grouping level, joined by `_PER_` (e.g. DIMENSIONLESS, CURRENCY_PER_MONTH_PER_BG, SILVER_PENNY_PER_FAM, PERSON_COUNT_PER_HH). Bases and grouping levels are open (per-package currencies, per-build levels), so this is a coarse pattern; `parse_compositional_unit` validates the grammar at load time.",
6+
"$comment": "Bases stay open (currencies register per package); the grouping level, if present, must be one of Germany's.",
77
"type": "string",
8-
"pattern": "^[A-Z][A-Z0-9_]*$"
8+
"pattern": "^[A-Z][A-Z0-9]*(?:_(?!PER_)[A-Z0-9]+)*(?:_PER_(?:SQUARE_METER|HOURS))?(?:_PER_(?:YEAR|QUARTER|MONTH|WEEK|DAY))?(?:_PER_(?:HH|EHE|FG|BG|EG|WTHH|SN))?$"
99
},
1010
"unitDeclaration": {
1111
"oneOf": [
@@ -157,7 +157,6 @@
157157
]
158158
},
159159
"else": {
160-
"$comment": "Scalar/dict parameter: `unit:` may sit at the top level (shared by every date) or one level lower, inside each date-specific key, so a parameter re-denominated over time can spell its unit symmetrically per date. The schema therefore does not require `unit:` here; the build-time mandatory-units check (`fail_if_environment_units_are_missing`) is the guarantee that every active leaf resolves to a unit (GEP 10).",
161160
"allOf": [
162161
{ "not": { "required": ["input_unit"] } },
163162
{ "not": { "required": ["output_unit"] } }
@@ -166,7 +165,6 @@
166165
}
167166
},
168167
{
169-
"$comment": "A scalar parameter takes its period from a time suffix on its name and declares a single fully-spelled `unit:` token, not a per-leaf mapping (which only a dict or require_converter parameter may use).",
170168
"if": {
171169
"properties": { "type": { "const": "scalar" } },
172170
"required": ["type"]

docs/how_to_guides/modifications_of_policy_environments.ipynb

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -222,17 +222,16 @@
222222
"- `leaf_name`: The leaf name of the parameter in GETTSIM's policy environment.\n",
223223
"- `start_date`: The date from which the parameter is valid (if applicable).\n",
224224
"- `end_date`: The date until which the parameter is valid (if applicable).\n",
225-
"- `unit`: The unit of the parameter (GEP 10). Parameters that map an input to an output\n",
226-
" — the lookup tables and piecewise polynomials — leave this unset and declare\n",
227-
" `input_unit` and `output_unit` instead.\n",
225+
"- `unit`: The unit of the parameter (GEP 10).\n",
228226
"- `name`: The name of the parameter.\n",
229227
"- `description`: A more elaborate description of the parameter.\n",
230228
"- `value`: The value of the parameter.\n",
231229
"- `note`: Some notes (if applicable).\n",
232230
"- `reference`: A legal reference.\n",
233231
"\n",
234-
"When modifying parameters, you will mostly care about the `value` attribute. The unit is\n",
235-
"required, so state the same one the parameter you replace declares.\n",
232+
"When modifying parameters, you will mostly care about the `value` attribute. Every\n",
233+
"parameter must declare a `unit` (GEP 10); keep the one the original declares.\n",
234+
"Parameters state a concrete currency, e.g. `TTSIMUnit.EUR.PER_YEAR`.\n",
236235
"\n",
237236
"### Scalar Parameters\n",
238237
"\n",
@@ -315,9 +314,9 @@
315314
"metadata": {},
316315
"outputs": [],
317316
"source": [
318-
"from gettsim.tt import ScalarParam, Unit\n",
317+
"from gettsim.tt import ScalarParam, TTSIMUnit\n",
319318
"\n",
320-
"higher_arbeitnehmerpauschbetrag = ScalarParam(value=1600, unit=Unit.EUR.PER_YEAR)"
319+
"higher_arbeitnehmerpauschbetrag = ScalarParam(value=1600, unit=TTSIMUnit.EUR.PER_YEAR)"
321320
]
322321
},
323322
{
@@ -419,7 +418,7 @@
419418
"metadata": {},
420419
"outputs": [],
421420
"source": [
422-
"from gettsim.tt import DictParam, Unit\n",
421+
"from gettsim.tt import DictParam, TTSIMUnit\n",
423422
"\n",
424423
"# Step 1: Create a copy of the status quo policy environment.\n",
425424
"higher_kinderfreibetrag_pe = copy_environment(status_quo_environment)\n",
@@ -430,7 +429,7 @@
430429
" \"betreuung_erziehung_ausbildung\": 1464,\n",
431430
" \"sächliches_existenzminimum\": 4000,\n",
432431
" },\n",
433-
" unit=Unit.EUR.PER_YEAR,\n",
432+
" unit=TTSIMUnit.EUR.PER_YEAR,\n",
434433
")\n",
435434
"\n",
436435
"# Step 3: Insert the new parameter into the copied policy environment\n",
@@ -557,7 +556,7 @@
557556
"source": [
558557
"from gettsim.tt import (\n",
559558
" ConsecutiveIntLookupTableParam,\n",
560-
" Unit,\n",
559+
" TTSIMUnit,\n",
561560
" get_consecutive_int_lookup_table_param_value,\n",
562561
")\n",
563562
"\n",
@@ -581,8 +580,8 @@
581580
" },\n",
582581
" xnp=np,\n",
583582
" ),\n",
584-
" input_unit=Unit.CALENDAR_YEAR,\n",
585-
" output_unit=Unit.YEARS,\n",
583+
" input_unit=TTSIMUnit.CALENDAR_YEAR,\n",
584+
" output_unit=TTSIMUnit.YEARS,\n",
586585
")\n",
587586
"\n",
588587
"# Step 3: Insert the new parameter into the copied policy environment\n",
@@ -687,7 +686,7 @@
687686
"metadata": {},
688687
"outputs": [],
689688
"source": [
690-
"from gettsim.tt import PiecewisePolynomialParam, Unit, get_piecewise_parameters\n",
689+
"from gettsim.tt import PiecewisePolynomialParam, TTSIMUnit, get_piecewise_parameters\n",
691690
"\n",
692691
"increased_behindertenpauschbetrag = PiecewisePolynomialParam(\n",
693692
" value=get_piecewise_parameters(\n",
@@ -705,8 +704,8 @@
705704
" leaf_name=\"parameter_behindertenpauschbetrag\",\n",
706705
" xnp=np,\n",
707706
" ),\n",
708-
" input_unit=Unit.DIMENSIONLESS,\n",
709-
" output_unit=Unit.EUR.PER_YEAR,\n",
707+
" input_unit=TTSIMUnit.DIMENSIONLESS,\n",
708+
" output_unit=TTSIMUnit.EUR.PER_YEAR,\n",
710709
")\n",
711710
"\n",
712711
"increased_behindertenpauschbetrag_pe = copy_environment(status_quo_environment)\n",
@@ -779,7 +778,7 @@
779778
"metadata": {},
780779
"outputs": [],
781780
"source": [
782-
"from gettsim.tt import RawParam, Unit\n",
781+
"from gettsim.tt import RawParam, TTSIMUnit\n",
783782
"\n",
784783
"# Step 1: Create a copy of the status quo policy environment.\n",
785784
"increased_tax_exemption_pe = copy_environment(status_quo_environment)\n",
@@ -800,8 +799,8 @@
800799
" {\"interval\": \"[277825, inf)\", \"slope\": 0.45, \"quadratic\": 0},\n",
801800
" ],\n",
802801
" },\n",
803-
" input_unit=Unit.EUR.PER_YEAR,\n",
804-
" output_unit=Unit.EUR.PER_YEAR,\n",
802+
" input_unit=TTSIMUnit.EUR.PER_YEAR,\n",
803+
" output_unit=TTSIMUnit.EUR.PER_YEAR,\n",
805804
")\n",
806805
"\n",
807806
"# Step 3: Insert the new parameter into the copied policy environment\n",
@@ -836,7 +835,7 @@
836835
"dictionary.\n",
837836
"\n",
838837
"```python\n",
839-
"@param_function(unit=Unit.CURRENCY.PER_YEAR)\n",
838+
"@param_function(unit=TTSIMUnit.CURRENCY.PER_YEAR)\n",
840839
"def kinderfreibetrag_pro_kind_y(parameter_kinderfreibetrag: dict[str, float]) -> float:\n",
841840
" return sum(parameter_kinderfreibetrag.values())\n",
842841
"```"
@@ -868,7 +867,7 @@
868867
"The original function looks like this:\n",
869868
"\n",
870869
"```python\n",
871-
"@param_function(unit=Unit.CURRENCY.PER_YEAR)\n",
870+
"@param_function(unit=TTSIMUnit.CURRENCY.PER_YEAR)\n",
872871
"def kinderfreibetrag_pro_kind_y(\n",
873872
" parameter_kinderfreibetrag: dict[str, float],\n",
874873
") -> float:\n",
@@ -885,10 +884,10 @@
885884
"metadata": {},
886885
"outputs": [],
887886
"source": [
888-
"from gettsim.tt import Unit, param_function\n",
887+
"from gettsim.tt import TTSIMUnit, param_function\n",
889888
"\n",
890889
"\n",
891-
"@param_function(unit=Unit.CURRENCY.PER_YEAR)\n",
890+
"@param_function(unit=TTSIMUnit.CURRENCY.PER_YEAR)\n",
892891
"def kinderfreibetrag_pro_kind_y(\n",
893892
" parameter_kinderfreibetrag: dict[str, float],\n",
894893
" kinderzuschlag__parameter_existenzminimum: dict[str, dict[str, float]],\n",
@@ -966,6 +965,10 @@
966965
"`PolicyFunction`s are usually written to operate on rows of the input data. They can\n",
967966
"take any parameter or other `ColumnObject` as inputs.\n",
968967
"\n",
968+
"Like parameters, every `ColumnObject` declares a `unit` (GEP 10), so a function you\n",
969+
"add or replace must declare one too. Functions are typically currency-agnostic —\n",
970+
"they use `TTSIMUnit.CURRENCY.PER_YEAR`, not a concrete currency like `TTSIMUnit.EUR.PER_YEAR`.\n",
971+
"\n",
969972
"**Note**: Some `PolicyFunction`s operate on columns of input data. Their decorator will\n",
970973
"contain the term `vectorization_strategy=\"not_required\"`.\n",
971974
"\n",
@@ -975,7 +978,7 @@
975978
"This is the original function:\n",
976979
"\n",
977980
"```python\n",
978-
"@policy_function(unit=Unit.CURRENCY.PER_YEAR)\n",
981+
"@policy_function(unit=TTSIMUnit.CURRENCY.PER_YEAR)\n",
979982
"def kinderfreibetrag_y(\n",
980983
" anzahl_kinderfreibeträge: int,\n",
981984
" kinderfreibetrag_pro_kind_y: float,\n",
@@ -1005,18 +1008,18 @@
10051008
")\n",
10061009
"\n",
10071010
"# Step 2: Create a new parameter `min_anzahl_kinder_für_kinderfreibetrag`\n",
1008-
"from gettsim.tt import ScalarParam, Unit\n",
1011+
"from gettsim.tt import ScalarParam, TTSIMUnit\n",
10091012
"\n",
10101013
"min_anzahl_kinder_für_kinderfreibetrag = ScalarParam(\n",
1011-
" value=2, unit=Unit.PERSON_COUNT.PER_FG\n",
1014+
" value=2, unit=TTSIMUnit.PERSON_COUNT\n",
10121015
")\n",
10131016
"\n",
10141017
"# Step 3: Create a new `PolicyFunction` that modifies the tax deduction for children\n",
10151018
"# based on the new parameter\n",
10161019
"from gettsim.tt import policy_function\n",
10171020
"\n",
10181021
"\n",
1019-
"@policy_function(unit=Unit.CURRENCY.PER_YEAR)\n",
1022+
"@policy_function(unit=TTSIMUnit.CURRENCY.PER_YEAR)\n",
10201023
"def kinderfreibetrag_y(\n",
10211024
" anzahl_kinderfreibeträge: int,\n",
10221025
" kinderfreibetrag_pro_kind_y: float,\n",

docs/tutorials/simple_example.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@
394394
"cell_type": "markdown",
395395
"metadata": {},
396396
"source": [
397-
"We get the current `value` of the `ScalarParam` out. We then inject a new `ScalarParam` object into the same place of `policy_environment`, carrying over the unit of the parameter we replace — every parameter must declare one (GEP 10), and changing a value must not change its unit."
397+
"We get the current `value` of the `ScalarParam` out. We then inject a new `ScalarParam` object into the same place of `policy_environment`, carrying over the unit of the parameter we replace — every parameter must declare one (GEP 10)."
398398
]
399399
},
400400
{

0 commit comments

Comments
 (0)