Repository navigation
Conversation
- Keep runtime-parameterized process axes (NaN placeholder nodes at build time). - IID draws read row 0 of a broadcast table, so unread IID states stay broadcast. - Skip targets reached through a participation check. - Regenerate fingerprint pins; re-anchor certificate pins and seals. - Disable contraction in bitwise-parity and axis-order tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Documentation build overview
38 files changed ·
|
mj023
marked this pull request as ready for review
November 2, 2026 19:14
…20261103 # Conflicts: # src/_lcm/regime_building/Q_and_F.py # tests/candidate_certificate/direct_flow.py # tests/candidate_certificate/sources.json # tests/ci/ci-workloads.json # tests/data/fingerprints_slice4_base.json
Re-seal tests/candidate_certificate/sources.json after the conflict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## feat/591-value-storage #636 +/- ##
=========================================================
Coverage ? 94.10%
=========================================================
Files ? 663
Lines ? 111924
Branches ? 0
=========================================================
Hits ? 105321
Misses ? 6603
Partials ? 0
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
hmgaudecker
added a commit
that referenced
this pull request
Nov 4, 2026
The process-edge wrapper hands `_get_compute_CE` a partial that binds every argument except `lottery_contraction_source`, so the inner build saw the default `None` and `GridSearch(lottery_contraction=True)` compiled the same enumerated kernel as `False`. Bind the source as well. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LAZ63AjbZFLweWuJyPUs6S
Benchmark comparison (main → HEAD)Comparing
|
The lognormal process draws income in levels while every other process draws log income, but the shared wealth transition exponentiated the state for all of them. The lognormal variant therefore added exp(exp(z)) to wealth, reaching seven orders of magnitude past its wealth grid, and its value test could only be bounded loosely against an analytic recurrence. The fixture now selects a level transition and constraint for the lognormal process, so it is the normal fixture with the exponential moved into the process: same value function, same panel with income exponentiated. A parity test pins that, and the regression test compares the lognormal values to the normal solution pickle. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LAZ63AjbZFLweWuJyPUs6S (cherry picked from commit f400cbd)
Only the lognormal panel changes in content; the other four are byte-different serializations of identical frames, regenerated together so the provenance record describes every file in the directory. Generated at float64 on CPU with jax 0.12.0.1. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LAZ63AjbZFLweWuJyPUs6S
This branch has not been deployed
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.
What problem do you want to solve?
GridSearch averages the next-period value over every joint lottery node at every
state–action candidate. A Markov or process draw whose weights read no state or action
other than the drawn state itself, and whose value no law reads, only selects a slice of
V′. Its expectation is therefore the same for every candidate. This PR sums such draws
into V′ once per kernel call. The continuation then reads one row at the current node
instead of mapping over the draw.
On ACA's benchmark grids, spousal income, the wage residual (Rouwenhorst) and health are
contracted. The warm solve drops from 11.67 s to 7.96 s (1.47×), with values equal to
2.65e-15.
Summary
Linear interpolation is linear in the node values, so the swap is exact in real
arithmetic.
_ComputeCE.__call__ (per state–action candidate) for each target next_values = next_regime_to_V_arr[target] + next_values = continuation.with_contracted_draws(values=next_values, ...) # once per call: Ṽ next_V(**coordinates, next_V_arr=next_values) # contracted draws: no node axis, # read at the current nodesrc/_lcm/ ├── regime_building/ +│ ├── lottery_contraction.py # eligibility, rewritten laws/plans, the contraction │ ├── Q_and_F.py # _contract_target_lotteries; field on _TargetContinuation │ └── processing.py # solve site passes LotteryContractionSource for GridSearch └── solution/ └── grid_search.py # GridSearch(lottery_contraction: bool = True)A draw
next_<state>toward a target is contracted only when all of these hold:participation-querying, and the target is not reached through a participation check,
which rebinds the reader later.
no original (fixed-component) layout.
than
<state>. Period, age and parameters are allowed.0..n-1, or astochastic process with static, finite nodes. Runtime-parameterized processes keep
their axis.
The table is indexed by the source grid, so cross-grid draws (ACA health, 3 → 2
categories at 65) are covered. When the weights don't read
<state>(IID draws), allrows coincide: the continuation reads row 0 and no current value. That keeps the
existing broadcast of unread IID states.
Numerics: each row uses
zero_safe_averageoverscaled_joint_weightcoefficients,like the per-node path. The mean is held between its smallest and largest live value,
because summing one draw on its own at near-maximal values could otherwise round past
the largest finite number.
Evidence
Oracle:
tests/regime_building/test_lottery_contraction.pychecks a literaljoint-node expectation, with contraction on and off, for these cases:
action, and a draw read by next wealth.
The planner tests cover runtime-node processes and the IID law reading no state.
test_continuation_expectation_oracle.py(including the near-float-max cases) passes.Full CPU suite, float64: Marvin, 48 workers, compared with the base commit
2ca4c2c05.Before (first version of this branch): 104 failed against 32 on the base, so 72
were caused by contraction. The causes:
After (head
64c8314ad, job 28686948): 32 failed, 29853 passed, 410 skipped,9 xfailed. The 32 failures are exactly the base's 32; none is new.
ACA benchmark grids (RTX 3050, float64, warm median of 3): off 11.67 s, on 7.96 s,
1.47×. 184 value arrays: max relative difference 2.65e-15, no finiteness mismatches.
Measured on the pre-rebase base; to re-measure on Keep solved values on the host or on disk (#591) #633.
Production-grid memory, compile-only, 2 preference types: one V′-sized table per
target, temporaries about 4× V′ (largest 37.6 MiB → 150 MiB).
Merge Danger
Door: two-way.
GridSearch(lottery_contraction=False)restores per-node enumeration.Blast Radius: numerical.
Stored-bytes regressions and bitwise parity checks see that. The broadcast and
fixed-component parity tests now switch contraction off.
GridSearchgained a field). The pins areregenerated, and the base reproduces the old ones.
Q_and_F.py,processing.pyandgrid_search.pyre-anchored, byte seals refreshed,verify.pypasses.temporaries are part of the compiler's memory report that budgeted width selection
admits against. On the test model the core's temporaries drop from 1.87 MB to
0.41 MB with contraction on, at the same widths. The table is V′-sized and does not
shrink with narrower widths.
Notes
lottery_contractionis the first option onGridSearch;execution switches such as
donate_bufferslive onExecutionConfig. It sits on thesolver because it changes how GridSearch computes the expectation, can be set per
regime and means nothing to other solvers, like
DCEGM's method options.action-tile loop body. XLA:CPU hoists it out of the loop; XLA:GPU does not, so on GPU
the table is rebuilt once per (cell tile, action tile): 12 times per core call at cell
width 64 on the test model. Values and memory are unaffected, and the ACA speedup
above already includes this repeated work. We do not hoist the contraction here,
because building it once before the tiles would need structural changes to the chunk
loop.
files move between shards in
ci-workloads.json. The tool does this by design; baseand branch both pass
--check.Todo
🤖 Generated with Claude Code