Skip to content

Allow more deeply nested mappings in params while retaining tight typing.#237

Merged
hmgaudecker merged 61 commits intomainfrom
nested-mapping-params
Feb 17, 2026
Merged

Allow more deeply nested mappings in params while retaining tight typing.#237
hmgaudecker merged 61 commits intomainfrom
nested-mapping-params

Conversation

@hmgaudecker
Copy link
Member

@hmgaudecker hmgaudecker commented Feb 11, 2026

Summary

Small update in order to work sensibly with GETTSIM functions.

  • Add MappingLeaf, a JAX-pytree-compatible wrapper that prevents flatten_regime_namespace from recursing into its contents, allowing nested parameter dicts to be passed through the params pipeline as opaque leaves. Same for SequenceLeaf.
  • Add an as_leaf function, wich is how these will typically be generated, make it available via lcm.params.as_leaf
  • Teach _make_immutable / _make_mutable to handle MappingLeaf (converting inner data while preserving the wrapper)
  • [somewhat unrelated, just because this bug crept up in the model ] Add reproducer test for BUG: State variable only used in transitions causes ValueError in vmap_1d at last regime period #236 (state used only in transitions with terminal regime)

Test plan

  • test_mapping_leaf.py — construction, repr, equality, JAX pytree round-trips, immutable/mutable conversions, flatten_regime_namespace leaf behavior

  • test_model.py::test_state_only_in_transitions_with_terminal_regime — reproducer for BUG: State variable only used in transitions causes ValueError in vmap_1d at last regime period #236.

    Somewhat unrelated, just because the bug crept up in the model where we are already using this branch.

    This passes out of the box; must have been fixed along the way somewhere.

hmgaudecker and others added 30 commits February 10, 2026 06:29
Instead of wrapping each function to accept an internal_regime_params dict and
extracting parameters at call time, use dags.signature.rename_arguments() to
qualify parameter names with function prefixes (e.g., risk_aversion becomes
utility__risk_aversion). This makes the parameter flow explicit and removes
the internal_regime_params indirection from all function signatures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…at_regime_params.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ParamsTemplate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…s Callable in result.py.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…mstances than REGIME_SEPARATOR. Some small improvements.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…eatment of dynamic IrregSpacedGrids, in particular ShockGrids.
Three bugs in _partial_fixed_params_into_regimes:
1. internal_functions.regime_transition_probs was not updated alongside
   the top-level attribute, causing simulation to use un-partialled
   functions for regime transitions.
2. regime_transition_probs was partialled with ALL regime fixed params,
   but it only accepts a subset — breaking inspect.signature used by
   dags.concatenate_functions in to_dataframe.
3. to_dataframe additional_targets built DAGs from raw functions that
   still expected fixed params no longer present in runtime params.

Fixes: update internal_functions, filter kwargs per function signature,
store resolved_fixed_params on InternalRegime for target computation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add the NestedMappingParams type.
Copy link
Member

@timmens timmens left a comment

Choose a reason for hiding this comment

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

Very nice! I can see how this is useful/necessary for GETTSIM etc.

Only two minor remarks. The user would need to import NestedMappingParams and use that in her params definition, correct? In this case:

  1. Should we potentially find a name that fits better with what this object actually does, i.e., tells PyLCM to treat this Mapping as a leaf (not sure about the wording yet, but NestedMappingParams confused me)?
  2. Should this object live in either the top-level namespace or in lcm.params?

@hmgaudecker hmgaudecker changed the title Add the NestedMappingParams type. Add the MappingLeaf type. Feb 16, 2026
@hmgaudecker
Copy link
Member Author

@timmens @MImmesberger -- do you like lcm.params.MappingLeaf ?

@timmens
Copy link
Member

timmens commented Feb 16, 2026

I think that is much better. I have one question (that might be stupid because I don't understand the application that well), but is there a reason why we don't simply want:

lcm.params.Leaf

In the sense that I have never read "MappingLeaf" before, but I have read "Leaf" frequently. And anyone who worked with JAX before will ---hopefully--- directly understand what is meant by "Leaf".

Or is solving the "more general" problem simply not necessary here, and we can restrict ourselves completely to the Mapping type?

Another thought that occurred to me, don't we actually want to export something like a as-function?

gettsim_params = {"a": [0, 1], "b": jnp.arange(4), "c": -1231}

lcm_params = {"d": {"e": 2, "f": 3}, "gettsim_params": lcm.params.as_leaf(gettsim_params)}

where lcm.params.as_leaf takes care of the processing and returns an lcm.params.Leaf object?

@hmgaudecker
Copy link
Member Author

is there a reason why we don't simply want lcm.params.Leaf

Yes, we want to have a mapping that is a leaf, useful for typing to distinguish this from other leaves. Since it was cheap and symmetric, I added SequenceLeaf, that hopefully makes it clear!

as_leaf() is a great idea, implemented!

@hmgaudecker
Copy link
Member Author

@MImmesberger, can you switch to .as_leaf? That should be the idiomatic way of using it, I am thinking about the classes more in terms of typing.

Base automatically changed from partial-fixed_params to main February 17, 2026 09:13
@hmgaudecker hmgaudecker changed the title Add the MappingLeaf type. Allow more deeply nested mappings in params while retaining tight typing. Feb 17, 2026
@hmgaudecker
Copy link
Member Author

@timmens -- I thought you had approved already, but either I misremember or it got lost because of subsequent changes. Anything left?

Copy link
Member

@timmens timmens left a comment

Choose a reason for hiding this comment

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

No, looks good to me!

@hmgaudecker hmgaudecker merged commit 391e63a into main Feb 17, 2026
7 of 8 checks passed
@hmgaudecker hmgaudecker deleted the nested-mapping-params branch February 17, 2026 10:10
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.

BUG: State variable only used in transitions causes ValueError in vmap_1d at last regime period

3 participants