Skip to content

Promote the Iskhakov et al. (2017) model to an example with docs#374

Open
hmgaudecker wants to merge 17 commits into
feat/canonical-paramsfrom
example/iskhakov-et-al-2017
Open

Promote the Iskhakov et al. (2017) model to an example with docs#374
hmgaudecker wants to merge 17 commits into
feat/canonical-paramsfrom
example/iskhakov-et-al-2017

Conversation

@hmgaudecker

Copy link
Copy Markdown
Member

Promotes the deterministic retirement model behind the analytical-solution tests to a proper example (lcm_examples.iskhakov_et_al_2017), with an example page and an explanation notebook plotting the paper's signature saw-tooth consumption function — each tooth is one optimal retirement age: as people retire later, their lifetime wealth increases, changing the optimal consumption path. The notebook's closing section is reserved for the brute-force vs DC-EGM comparison once the solver lands; this PR is the first piece of that stack and is independent of #373.

tests/test_models/deterministic/base.py becomes a re-export shim, so the test suite keeps its import location.

🤖 Generated with Claude Code

The deterministic retirement model that the analytical-solution tests replicate
moves from tests/test_models/deterministic/base.py to
src/lcm_examples/iskhakov_et_al_2017.py; base.py becomes a re-export shim so
the test suite keeps its import location.

Docs: an example page (docs/examples/iskhakov_et_al_2017.md, with the QE
citation in references.bib) and an explanation notebook
(docs/explanations/iskhakov_et_al_2017.ipynb) that plots the saw-tooth
consumption function — each tooth is one optimal retirement age: as people
retire later, their lifetime wealth increases, changing the optimal consumption
path — plus a horizon comparison showing the teeth accumulate with remaining
work-life. A closing section is reserved for the brute-force vs DC-EGM
comparison once the solver lands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@review-notebook-app

Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@read-the-docs-community

read-the-docs-community Bot commented Jun 10, 2026

Copy link
Copy Markdown

hmgaudecker and others added 4 commits June 10, 2026 10:25
The forward simulation evaluates every regime's policy for all subjects and
masks out-of-regime entries afterwards; those placeholder entries can be -inf
when a subject's state is infeasible under the other regime's problem. The
NaN/Inf warning fired on these placeholders — a false positive that surfaced
on every multi-regime simulation at log_level="warning".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ase.

The horizon comparison now starts at one decision period, which has no kink at
all: income earned by working arrives in the following period's budget, so
with no period left to enjoy it, working is pure disutility and everyone
retires — the first kink appears with two decision periods, where the
work-vs-retire values cross.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
At the packaged default resolution the sharp drop at a retirement threshold
shows up as a two-step drop with a spurious intermediate plateau: linear
interpolation smears the next-period value function's kink across a wealth-grid
cell and the consumption grid quantizes the policy. The main figures now use
finer grids (where the drop is a single jump, matching the analytical
solution), and a zoomed default-vs-fine comparison documents the artifact —
and motivates DC-EGM, which places kinks exactly without a consumption grid.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
At each threshold (initial wealth of about 32.4, 50.4, 68.3, 86.4) the agent
retires one period earlier — the marginal value of leisure exceeds the marginal
utility of the consumption the extra wage would buy — so lifetime wealth is one
period's income smaller and consumption drops; beyond 86.5 the agent never
works. Thresholds and the periods-worked progression (4 -> 3 -> 2 -> 1 -> 0)
verified on the fine-grid solution.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hmgaudecker hmgaudecker changed the title Promote the Iskhakov et al. (2017) model to an example with docs and a saw-tooth notebook Promote the Iskhakov et al. (2017) model to an example with docs Jun 10, 2026

@hmgaudecker hmgaudecker left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Autoreview.

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown

Benchmark comparison (main → HEAD)

Comparing 64cf042c (main) → fb501cc0 (HEAD)

Benchmark Statistic before after Ratio Alert
aca-baseline execution time 15.286 s 14.997 s 0.98
peak GPU mem 581 MB 581 MB 1.00
compilation time 311.45 s 349.54 s 1.12
peak CPU mem 7.83 GB 7.63 GB 0.97
aca-baseline-debug execution time 72.232 s 80.270 s 1.11
peak GPU mem 581 MB 581 MB 1.00
compilation time 404.14 s 457.07 s 1.13
peak CPU mem 7.63 GB 7.93 GB 1.04
Mahler-Yum execution time 4.868 s 4.508 s 0.93
peak GPU mem 520 MB 520 MB 1.00
compilation time 11.92 s 11.33 s 0.95
peak CPU mem 1.60 GB 1.58 GB 0.99
Precautionary Savings - Solve execution time 27.6 ms 24.1 ms 0.87
peak GPU mem 8 MB 8 MB 1.00
compilation time 1.52 s 1.52 s 1.00
peak CPU mem 1.15 GB 1.16 GB 1.01
Precautionary Savings - Simulate execution time 98.4 ms 63.5 ms 0.65
peak GPU mem 162 MB 157 MB 0.97
compilation time 3.83 s 3.52 s 0.92
peak CPU mem 1.35 GB 1.33 GB 0.99
Precautionary Savings - Solve & Simulate execution time 124.7 ms 89.6 ms 0.72
peak GPU mem 566 MB 566 MB 1.00
compilation time 5.07 s 4.77 s 0.94
peak CPU mem 1.32 GB 1.30 GB 0.99
Precautionary Savings - Solve & Simulate (irreg) execution time 229.2 ms 199.8 ms 0.87
peak GPU mem 2.18 GB 2.18 GB 1.00
compilation time 5.24 s 5.03 s 0.96
peak CPU mem 1.37 GB 1.36 GB 0.99

@hmgaudecker hmgaudecker changed the base branch from main to feat/canonical-broadcast-grammar June 10, 2026 15:43
hmgaudecker and others added 3 commits June 11, 2026 06:14
The explanation notebook constructs the same fine-grid model up to four
times across its sections; each fresh model object recompiles every kernel.
Caching the builder makes repeat uses execution-only, keeping the docs
build inside the Read the Docs time limit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Base automatically changed from feat/canonical-broadcast-grammar to feat/phase-variant-states June 11, 2026 18:48
hmgaudecker and others added 5 commits June 11, 2026 22:00
The forward simulation evaluates every regime's policy for all subjects;
the per-regime `validate_V` check now sees only the subjects simulated in
the regime, matching the NaN/Inf warning's masking, so placeholder values
of out-of-regime subjects can never raise.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@hmgaudecker hmgaudecker changed the base branch from feat/phase-variant-states to feat/canonical-params June 12, 2026 04:07
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