feat(as_of): set_input_sparse + transition_formula for sparse forward simulation#1368
Merged
feat(as_of): set_input_sparse + transition_formula for sparse forward simulation#1368
Conversation
eraviart
approved these changes
Mar 4, 2026
Member
eraviart
left a comment
There was a problem hiding this comment.
transition_formula is a big change, but I don't see how to avoid it
479caec to
e171424
Compare
…orward simulation
## set_input_sparse (Holder API)
New public method `Holder.set_input_sparse(period, idx, vals)` backed by
`_set_as_of_sparse`. Lets callers provide the diff directly (idx, vals)
without building a full N-array, saving 2×O(N) per SET iteration when only
k << N individuals change.
## transition_formula (Variable API)
Alternative to `formula` for `as_of` variables. Instead of returning a full
N-array (which triggers O(N) diff in the holder), the formula returns
`(selector, vals)` describing only who changes and their new values:
def transition_formula(person, period, parameters):
eligible = person("anciennete", period) >= 3
nouveau = person("salaire", period.last_month)[eligible] * 1.02
return eligible, nouveau # bool mask + k values (or scalar)
Supports dated variants (transition_formula_2024_01_01) with the same
dispatch mechanism as formula_*. Mutually exclusive with formula.
Requires as_of to be set.
## Implementation
- variables/config.py: TRANSITION_FORMULA_NAME_PREFIX constant
- variables/variable.py: detect/validate/dispatch transition_formula*
- simulations/simulation.py: _calculate_transition + _run_transition_formula
- holders/holder.py: _as_of_transition_computed tracking set
- tests/core/test_asof_variable.py: 6 new set_input_sparse tests
- tests/core/test_transition_formula.py: 12 new tests
- benchmarks/test_bench_asof.py: set_input_sparse in forward sim bench
+ new TestSetInputSparseVsDense comparison class
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ache - Replace _as_of_snapshot (single tuple) with _as_of_snapshots (OrderedDict) keeping up to _as_of_max_snapshots entries (default 3) - Add _cache_snapshot() helper with LRU eviction (popitem last=False) - Retroactive SET evicts all snapshots at >= instant instead of just one - Add Variable.snapshot_count attribute to configure per-variable - Add MemoryConfig.asof_max_snapshots for simulation-level default - Resolution order: Variable.snapshot_count > MemoryConfig > 3 - Add 7 tests covering defaults, priority chain, eviction, and correctness Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n_formula initial_formula: - Optional counterpart to transition_formula, called once when no base snapshot exists to seed the as_of variable's initial state - Supports date dispatch (initial_formula_YYYY_MM_DD) like transition_formula - Requires as_of; validated at instantiation time - If no initial_formula and no set_input, raises ValueError with clear message - Add INITIAL_FORMULA_NAME_PREFIX constant, set_initial_formulas(), parse_initial_formula_name(), get_initial_formula(), has_initial_formula Tracer / cycle detection fix: - Replace _check_for_cycle with _check_for_strict_cycle in _calculate_transition - _check_for_strict_cycle raises CycleError only for same variable@same period - Removes false SpiralError for legitimate temporal reads (e.g. period.last_month) - Termination for transition_formula is guaranteed by _as_of_transition_computed Tests (+8): - initial_formula establishes base, seeds transition sequence, date dispatch - initial_formula without as_of raises at instantiation - no initial_formula + no set_input raises ValueError - temporal recursion (P reads P-1) no longer falsely triggers SpiralError - true same-period cycle is caught and state preserved Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add formula_type: str | None = None field to TraceNode dataclass - Add record_formula_type(kind) to FullTracer; no-op on SimpleTracer - _calculate_transition annotates the current node with "initial" or "transition" before running the respective formula - Add formula_type property to TraceNode Protocol in types.py - Add 3 tests: initial → "initial", transition → "transition", regular formula → None Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add show_formula_type: bool = False to lines(), print_log(), _get_node_log(), and _print_line() - When True, appends [initial] or [transition] tag to the line for as_of nodes; regular formula nodes (formula_type=None) are unaffected - Add test verifying tags appear/disappear based on the flag Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add CHANGELOG entry covering transition_formula, initial_formula, multi-snapshot LRU cache, formula_type tracer field, show_formula_type option, and spiral-detection fix for as_of variables. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove unused imports (Holder, period) from test_transition_formula.py - Rename ambiguous variable l → line in assertion - Add # noqa: T201 to intentional print in benchmark - Rename loop variable p → _p to signal it is unused - Remove unused months_periods variable in forward-simulation benchmark - Fix stale _as_of_snapshot reference → _as_of_snapshots.clear() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Made-with: Cursor
e171424 to
473ca77
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Holder.set_input_sparse(period, idx, vals)— API directe pour passer le diff(idx, vals)sans tableau dense intermédiaire. Économise 2×O(N) par SET dans les boucles de simulation forward.transition_formula— alternative àformulapour les variablesas_of. La formule retourne(masque_bool, valeurs)au lieu d'un tableau complet de taille N, permettant un stockage sparse O(k) sans diff interne.Même dispatch par date que
formula_YYYY_MM_DD. Mutuellement exclusif avecformula. Requiertas_of.Fichiers modifiés
variables/config.pyTRANSITION_FORMULA_NAME_PREFIXvariables/variable.pytransition_formula*simulations/simulation.py_calculate_transition+_run_transition_formulaholders/holder.py_set_as_of_sparse,set_input_sparse, tracking_as_of_transition_computedtests/core/test_asof_variable.pyset_input_sparsetests/core/test_transition_formula.pybenchmarks/test_bench_asof.pyset_input_sparsedans le bench forward +TestSetInputSparseVsDenseTest plan
pytest tests/core/test_asof_variable.py— 24 tests (dont 6 nouveaux) ✅pytest tests/core/test_transition_formula.py— 12 tests ✅pytest tests/ -q --ignore=tests/web_api— 355 passed, 0 régression ✅🤖 Generated with Claude Code