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/<name>_{paths.npz,u.npy,params.json,meta.json}; logs/scenario_<name>.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/<name>_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 Nruns N at a time. - Cluster: the same scripts run unchanged on any MacLustr node (
rsyncthe 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/.