# Replication Tested on macOS 27 (Apple Silicon, 18 cores), Python 3.14.4, TeX Live 2026, on 2026-10-27. ```bash cd finance/agi-labor-capital-asset-valuation make setup # pip install -r requirements.txt (pinned) make test # pytest: static block (Restrepo P1–P6, KKT, accounting), dynamics (BGP, Jacobian, Newton), saved scenarios make benchmark # scripts/10_benchmark.py, 11_regime_map.py -> fig01, fig02, tab01, results/data/benchmark.csv make scenarios N=12 # scripts/21_run_all_scenarios.sh: 24 scenarios × 275 years, 12 in parallel (≈ 25 min per scenario, one core each) make ha # heterogeneous-agent GE for baseline, no_ai, citizen_fund_20 (≈ 20–40 min each) make figures tables # results/figures/fig03–fig10, results/tables/tab02–tab08 + numbers.tex (copied into paper/) make paper # paper/main.pdf via latexmk make slides # slides/main.pdf make all # everything except data download make data # optional: re-download the raw data (key-less endpoints; see data/README.md) ``` ## What each step produces and checks | Step | Output | Check | |---|---|---| | `test` | — | 10 static tests + 3 dynamic tests + one per saved scenario; a deliberately broken accounting fails `test_income_identity_fails_when_accounting_is_broken` | | `benchmark` | `results/data/benchmark.csv`, `regime_map.csv`; `fig01_benchmark`, `fig02_regimes`; `tab01_benchmark.tex` | P1–P6 of Restrepo (2025) hold to 1e-6 | | `scenarios` | `results/scenarios/_{paths.npz,u.npy,params.json,meta.json}`; `logs/scenario_.log` | `meta.json`: `converged`, `final_res` (< 1e-9), `horizon_check` (50 extra years: max deviation of r and log K over the first 225 years) | | `ha` | `results/ha/_ha.{npz,json}` | `hist`: max log excess demand for claims per iteration (< 1e-4 at convergence) | | `figures`, `tables` | `results/figures/*.{pdf,png}`, `results/tables/*.tex`, `results/tables/numbers.tex` | every number in the paper is a macro from `numbers.tex` or a table fragment | Seeds: none are needed (deterministic solvers; non-stochastic simulation of the distribution). Tolerances: static block ftol 1e-14 + KKT polish; transition 1e-9 (max residual); HA-GE 1e-4 (log excess demand). ## Solver notes * The transition is solved **directly at λ = 1** from a partial-equilibrium guess (`TwoClassModel.smart_guess`); if the Newton does not converge the driver falls back to a homotopy in the shock size (λ = 0, 0.25, …, 1), re-calibrating the base point at each λ (`solve.py`). * Each scenario uses one core; `scripts/21_run_all_scenarios.sh N` runs N at a time. * Cluster: the same scripts run unchanged on any MacLustr node (`rsync` the directory, `make scenarios N=30`). ## Reproducing the paper's numbers `paper/tables/numbers.tex` is generated by `scripts/50_tables.py`; the paper compiles only if it exists (`make tables` copies it). Figures are copied from `results/figures/` to `paper/figures/`.