Skip to content

Refactor piecewise polynomial (implement GEP-8)#1132

Merged
hmgaudecker merged 36 commits intomainfrom
refactor-piecewise-polynomial
Mar 19, 2026
Merged

Refactor piecewise polynomial (implement GEP-8)#1132
hmgaudecker merged 36 commits intomainfrom
refactor-piecewise-polynomial

Conversation

@hmgaudecker
Copy link
Copy Markdown
Collaborator

Refactor piecewise polynomial YAML and code for GEP-08, twin to TTSIM #76

Convert all piecewise polynomial YAML parameters from numbered dict format
to ordered lists with explicit interval strings:

  • solidaritätszuschlag, einkommensteuertarif, vorsorge, behinderung,
    wohngeld, grundrente, bürgergeld/arbeitslosengeld_2 freibeträge,
    lohnsteuer vorsorge
  • Rename keys: rate_linear->slope, rate_quadratic->quadratic,
    intercept_at_lower_threshold->intercept
  • Update Python code to use new API (parameter_list instead of
    parameter_dict, new key names)
  • Fix rates shape indexing: [coeff, interval] -> [interval, coeff]
    in lohnsteuer.py and solidaritätszuschlag.py
  • Add extend_extend_intervals_to_real_line to fix stale adjacent intervals
    after upsert_tree merges in param_functions
  • Re-export extend_extend_intervals_to_real_line from gettsim.tt

Co-Authored-By: Claude Opus 4.5 noreply@anthropic.com

hmgaudecker and others added 15 commits January 16, 2026 06:40
…#76](ttsim-dev/ttsim#76)

Convert all piecewise polynomial YAML parameters from numbered dict format
to ordered lists with explicit interval strings:
- solidaritätszuschlag, einkommensteuertarif, vorsorge, behinderung,
  wohngeld, grundrente, bürgergeld/arbeitslosengeld_2 freibeträge,
  lohnsteuer vorsorge
- Rename keys: rate_linear->slope, rate_quadratic->quadratic,
  intercept_at_lower_threshold->intercept
- Update Python code to use new API (parameter_list instead of
  parameter_dict, new key names)
- Fix rates shape indexing: [coeff, interval] -> [interval, coeff]
  in lohnsteuer.py and solidaritätszuschlag.py
- Add extend_extend_intervals_to_real_line to fix stale adjacent intervals
  after upsert_tree merges in param_functions
- Re-export extend_extend_intervals_to_real_line from gettsim.tt

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@MImmesberger
Copy link
Copy Markdown
Collaborator

@hmgaudecker When discussion GEP 8, we forgot about reference and note keys as well as the update_previous mechanic. I propose we add a intervals which stores the list of intervals and their coefficients. At the level of the intervals key, we can put reference, note and update_previous.

Regarding the behavior of update_previous specs:

  • No gaps between intervals before and after updating
  • Overlapping intervals in new and old spec are fine; new spec takes precedence and the old intervals adjust accordingly.

Any comments?

@hmgaudecker
Copy link
Copy Markdown
Collaborator Author

Any comments?

Yes, I'll need more context...

Overlapping intervals in new and old spec are fine; new spec takes precedence and the old intervals adjust accordingly.

Sounds scary. I think we should be very strict here. No need to use the update_previous mechanic; it's just a couple of extra lines after all.

@MImmesberger
Copy link
Copy Markdown
Collaborator

Sounds scary. I think we should be very strict here. No need to use the update_previous mechanic; it's just a couple of extra lines after all.

Yeah, needed to implement it (and fail to anticipate test results) to see how error-prone this is.

The only place where we use update_previous for piecewise functions is for the income tax and Soli. Copy+Paste of the parameters that don't change isn't too bad there.

Yes, I'll need more context...

So the only difference compared the GEP version will be that we do

2026-01-01:
    reference: ...
    intervals:
        - interval: "[0, 100)"
           slope: 0.5
        - ...

instead of

2026-01-01:
    - interval: "[0, 100)"
       slope: 0.5
    - ...

@hmgaudecker
Copy link
Copy Markdown
Collaborator Author

That looks good, but I still don't quite get what you mean by:

Overlapping intervals in new and old spec are fine; new spec takes precedence and the old intervals adjust accordingly.

Are overlapping intervals

2025-01-01:
    - interval: "[0, 100)"
       slope: 0.5
    - interval: "[100, 200)"
       slope: 0.4
2026-01-01:
    - updates_previous: true
    - interval: "[50, 150)"
       slope: 0.4

or

2025-01-01:
    - updates_previous: true
    - interval: "[0, 100)"
       slope: 0.5
    - interval: "[100, 200)"
       slope: 0.4
2026-01-01:
    - updates_previous: true
    - interval: "[0, 100)"
       slope: 0.4

?

The first would be terrible, I don't see why we would not support the second.

@MImmesberger
Copy link
Copy Markdown
Collaborator

I was talking about the first one and I agree we should not do it. We don't really need the second one as of now, but wouldn't hurt to cover that case.

@hmgaudecker
Copy link
Copy Markdown
Collaborator Author

We could use it in Bürgergeld, but I am not sure whether this case would be covered:

      - interval: '[100, 1000)'
        slope: 0.2

->

      - interval: '[100, 520)'
        slope: 0.2
      - interval: '[520, 1000)'
        slope: 0.3

@MImmesberger
Copy link
Copy Markdown
Collaborator

My hunch is that we should not allow for that. Splitting up intervals doesn't occur often and a strict "no changes in boundaries" rule is easier to keep track of (I noticed a week ago that I start to forget about all the features we implemented last summer 😄). But feel free to overrule.

@hmgaudecker
Copy link
Copy Markdown
Collaborator Author

No, Just thought it might have worked out is the box!

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 7, 2026

Codecov Report

❌ Patch coverage is 78.57143% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...rc/gettsim/germany/arbeitslosengeld_2/einkommen.py 0.00% 1 Missing ⚠️
src/gettsim/tests_germany/test_jittability.py 0.00% 1 Missing ⚠️
src/gettsim/tests_germany/test_policy_cases.py 50.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@read-the-docs-community
Copy link
Copy Markdown

read-the-docs-community bot commented Mar 7, 2026

Documentation build overview

📚 gettsim | 🛠️ Build #31873487 | 📁 Comparing 2c849bf against latest (e0d468e)


🔍 Preview build

Show files changed (4 files in total): 📝 4 modified | ➕ 0 added | ➖ 0 deleted
File Status
geps/gep-03.html 📝 modified
geps/gep-08.html 📝 modified
how_to_guides/modifications_of_policy_environments.html 📝 modified
tutorials/visualizing_the_system.html 📝 modified

@MImmesberger MImmesberger marked this pull request as ready for review March 7, 2026 15:30
@hmgaudecker hmgaudecker force-pushed the refactor-piecewise-polynomial branch from 9efd51a to 058a909 Compare March 11, 2026 16:58
@hmgaudecker hmgaudecker force-pushed the refactor-piecewise-polynomial branch from 502c1b6 to 0bbe9af Compare March 14, 2026 06:40
Copy link
Copy Markdown
Collaborator

@MImmesberger MImmesberger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can merge (after merging gettsim-personas and ttsim)!

@hmgaudecker hmgaudecker merged commit 539c421 into main Mar 19, 2026
14 checks passed
@hmgaudecker hmgaudecker deleted the refactor-piecewise-polynomial branch March 19, 2026 06:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants