Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
208f78f
Add opt-in PF-asymptote decay machinery for AggShock cFunc slices
llorracc Jul 5, 2026
fed6f36
Add power-law decay extrapolation form to LinearInterp
llorracc Jul 5, 2026
6c4af31
Use the power-law decay form in the AggShock PF-decay machinery
llorracc Jul 5, 2026
4909c5c
Add pf_decay: theory quantities for the power-law decay exponent and …
llorracc Jul 9, 2026
d8afd27
Add explicit-exponent decay_extrap_Q to LinearInterp's power-law tail
llorracc Jul 9, 2026
30606d8
Thread theory-informed tail policy through the AggShock decay machinery
llorracc Jul 9, 2026
b04e70d
Add powerlaw_tail_diagnostic: Theorem gamma-T as a post-solve grid test
llorracc Jul 9, 2026
d8c0d27
Land the THEOREM-REF updater tool; audit + complete the tag set
llorracc Jul 9, 2026
e81ff28
Harden pf_decay root-finders near the r = g knife-edge (review fixes)
llorracc Jul 9, 2026
64e83bf
Add certified grid-extent criterion (aXtraMax_from_tail_tol + rel_gap…
llorracc Jul 10, 2026
5a16751
Harden the extent criterion per the adversarial review
llorracc Jul 10, 2026
4e46ee7
Add qstar_probe (operator eigen-probe) and mNrm_stable_points to pf_d…
llorracc Jul 10, 2026
45ff3ab
Add aXtraMax_from_wealth_mass: the grid top as a measured wealth quan…
llorracc Jul 11, 2026
e126dd6
Add DecayTailInterp: composable decay tails over any 1D interpolant
llorracc Jul 11, 2026
8e93c68
Make level continuity at the top knot an invariant of the decay machi…
llorracc Jul 11, 2026
d6af964
Add the C1 two-term decay attachment and make it the explicit-Q default
llorracc Jul 11, 2026
cec425f
Fill the CHANGELOG PR links: this branch is PR #1782
llorracc Jul 11, 2026
b6285f0
`decay_extrap_form='moderation_tail'`: guard-free C1 tail in Method-o…
llorracc Jul 12, 2026
a5c7068
CHANGELOG: the moderation_tail family + enriched guard diagnosis
llorracc Jul 12, 2026
df50847
THEOREM-REF pins: retarget to the theory's permanent home (comment-only)
llorracc Jul 13, 2026
629aee8
Add KappaBarTailInterp: the constraint-end (Theorem CE) tail wrapper
llorracc Jul 15, 2026
c3498c1
pf_decay: ce_psi_regime + ConstraintEndRegimeWarning + aXtraMin_from_…
llorracc Jul 15, 2026
168e569
IndShockConsumerType: opt-in theory-pinned tails, both ends, both roles
llorracc Jul 15, 2026
1a58528
Port the extrapolator-fidelity battery: tests/ConsumptionSaving/test_…
llorracc Jul 15, 2026
d31ed9c
CHANGELOG: the both-tails option surface, KappaBarTailInterp, pf_deca…
llorracc Jul 15, 2026
819ce1a
tests: platform-gate the byte-zero pins; honest factor-gate margins
llorracc Jul 15, 2026
b42afe7
IndShockConsumerType: respect a user decay_extrap_Q set after an auto…
llorracc Jul 15, 2026
a4ccde2
docs: NK calc_jacobian caveat, lifecycle t=0-Q caveat, st-prop-C2 + e…
llorracc Jul 15, 2026
68dc87f
style: ruff-format the new test file (pinned ruff 0.11.8)
llorracc Jul 15, 2026
1e3ae92
CHANGELOG: fill the both-tails PR links - this work rides PR #1782 (o…
llorracc Jul 15, 2026
98fb5e2
Add the notebook + binding-constraint-gate workstream prompt (rides P…
llorracc Jul 15, 2026
ab02922
feat(pf_decay): validity threshold + constraint-gate tests/docs + ext…
llorracc Jul 15, 2026
7b59d25
notebook: relocate to examples/ConsIndShockModel/ and revise per review
llorracc Jul 15, 2026
1c305b8
feat(pf_decay): ergodic-grid diagnostics -- ex-ante patience screen +…
llorracc Jul 15, 2026
1d57b9e
Add the measured-Q diagnostics rider to LinearInterp (q_diagnostics -…
llorracc Jul 24, 2026
fa50fbb
Merge branch 'main' into PR #1782
alanlujan91 Aug 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

506 changes: 503 additions & 3 deletions HARK/ConsumptionSaving/ConsAggShockModel.py

Large diffs are not rendered by default.

446 changes: 438 additions & 8 deletions HARK/ConsumptionSaving/ConsIndShockModel.py

Large diffs are not rendered by default.

2,457 changes: 2,457 additions & 0 deletions HARK/ConsumptionSaving/pf_decay.py

Large diffs are not rendered by default.

1,317 changes: 1,314 additions & 3 deletions HARK/interpolation.py

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions docs/CHANGELOG.md

Large diffs are not rendered by default.

904 changes: 904 additions & 0 deletions examples/ConsIndShockModel/PowerlawExtrapolation.ipynb

Large diffs are not rendered by default.

559 changes: 559 additions & 0 deletions tests/ConsumptionSaving/test_AggShock_pf_decay.py

Large diffs are not rendered by default.

1,145 changes: 1,145 additions & 0 deletions tests/ConsumptionSaving/test_pf_decay.py

Large diffs are not rendered by default.

1,336 changes: 1,336 additions & 0 deletions tests/ConsumptionSaving/test_powerlaw_extrap.py

Large diffs are not rendered by default.

1,421 changes: 1,421 additions & 0 deletions tests/test_interpolation.py

Large diffs are not rendered by default.

92 changes: 92 additions & 0 deletions tests/test_theorem_refs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
"""CI wrapper for tools/update_theorem_refs.py (theorem-ref tag hygiene).

The power-law-decay PR carries theorem-ref tags — pinned citations into the
private HAFiscal-Latest theorem repo (theory/powerlaw-decay/) — in its comments
and docstrings. ``tools/update_theorem_refs.py --check`` verifies tag SYNTAX
always, and tag RESOLUTION (file + section heading + optional label exist at
the pinned commit) whenever a theorem-repo checkout is available.

Pre-registered expectations (declared before first run; never weakened):
* WITHOUT the theorem repo (the public econ-ark CI case) the checker must
DEGRADE GRACEFULLY: syntax-check only, print a NOTICE, exit 0.
* It must find at least ``MIN_EXPECTED_TAGS`` tags (the PR landed 22; a
collapse to fewer than 20 means tags were mass-deleted or the scanner
broke) and 0 malformed.
* WITH a local theorem-repo checkout (private-side dev boxes), every tag
must additionally RESOLVE at its pin: exit 0 and no UNRESOLVED lines.

Note: this file deliberately never spells the uppercase tag token, so the
scanner has nothing to parse here.
"""

import os
import subprocess
import sys
import unittest

REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TOOL = os.path.join(REPO_ROOT, "tools", "update_theorem_refs.py")

# Known private-side checkout of the theorem repo (worktree pin 71ca7c61);
# $THEOREM_REF_REPO overrides. Absent on public CI — that path is the
# graceful-degradation test.
THEOREM_REPO = os.environ.get(
"THEOREM_REF_REPO",
"/home/shared/github/llorracc/HAFiscal-Latest/.worktrees/powerlaw-theorem",
)

MIN_EXPECTED_TAGS = 20


def _run_check(extra_args, env_overrides=None):
env = dict(os.environ)
env.pop("THEOREM_REF_REPO", None) # the test controls repo availability
if env_overrides:
env.update(env_overrides)
return subprocess.run(
[sys.executable, TOOL, "--check"] + extra_args,
cwd=REPO_ROOT,
env=env,
capture_output=True,
text=True,
timeout=300,
)


class TestTheoremRefsCheck(unittest.TestCase):
def test_check_without_theorem_repo_degrades_gracefully(self):
"""No theorem repo: syntax-check only, NOTICE printed, exit 0."""
r = _run_check([])
self.assertEqual(
r.returncode, 0,
f"--check without the theorem repo must exit 0, got "
f"{r.returncode}\nstdout:\n{r.stdout}\nstderr:\n{r.stderr}",
)
self.assertIn("NOTICE", r.stdout, r.stdout)
self.assertIn(" 0 malformed", r.stdout, r.stdout)
n_tags = int(r.stdout.rsplit("check: ", 1)[1].split(" tag(s)")[0])
self.assertGreaterEqual(
n_tags, MIN_EXPECTED_TAGS,
f"expected >= {MIN_EXPECTED_TAGS} tags, scanner found {n_tags}",
)

@unittest.skipUnless(
os.path.isdir(os.path.join(THEOREM_REPO, ".git"))
or os.path.isfile(os.path.join(THEOREM_REPO, ".git")),
"theorem repo checkout not available (public CI)",
)
def test_check_with_theorem_repo_all_tags_resolve(self):
"""Theorem repo present: every tag resolves at its pin; exit 0."""
r = _run_check(["--repo", THEOREM_REPO])
self.assertEqual(
r.returncode, 0,
f"--check with the theorem repo must exit 0, got "
f"{r.returncode}\nstdout:\n{r.stdout}\nstderr:\n{r.stderr}",
)
self.assertNotIn("UNRESOLVED", r.stdout, r.stdout)
self.assertNotIn("MALFORMED", r.stdout, r.stdout)
self.assertIn(" 0 finding(s) total", r.stdout, r.stdout)


if __name__ == "__main__":
unittest.main()
Loading
Loading