SPB Git

spb/wp24_uqo

Public
4.3 KB · 82 lines python
1"""Figures and numbers from the heterogeneous-agent runs (results/ha/*_ha.npz).2Outputs: results/figures/fig10_distribution.{pdf,png}, results/tables/tab07_distribution.tex, results/data/ha_numbers.json"""3import glob4import json5import os67import matplotlib8import numpy as np910matplotlib.use("Agg")11import matplotlib.pyplot as plt1213ROOT = os.path.join(os.path.dirname(__file__), "..")14HA = os.path.join(ROOT, "results", "ha")15FIG = os.path.join(ROOT, "results", "figures")16TAB = os.path.join(ROOT, "results", "tables")17plt.rcParams.update({"font.size": 9, "axes.spines.top": False, "axes.spines.right": False, "legend.frameon": False})18C = {"baseline": "#1f3b73", "no_ai": "#7f8c8d", "citizen_fund_20": "#27ae60", "rapid_agi": "#c0392b"}19LAB = {"baseline": "baseline", "no_ai": "AI frozen", "citizen_fund_20": "citizen fund 20%", "rapid_agi": "rapid AGI"}2021runs = {}22for f in sorted(glob.glob(os.path.join(HA, "*_ha.npz"))):23    n = os.path.basename(f).replace("_ha.npz", "")24    runs[n] = dict(np.load(f))25    runs[n]["meta"] = json.load(open(f.replace(".npz", ".json")))26print("HA runs:", list(runs))27if runs:28    fig, ax = plt.subplots(2, 3, figsize=(10.5, 5.6))29    for n, d in runs.items():30        y = d["years"]; m = y <= 210031        kw = dict(color=C.get(n, "k"), label=LAB.get(n, n))32        ax[0, 0].plot(y[m], d["gini"][m], **kw)33        ax[0, 1].plot(y[m], d["top10"][m], **kw)34        ax[0, 2].plot(y[m], d["top1"][m], **kw)35        ax[1, 0].plot(y[m], d["bottom50"][m], **kw)36        ax[1, 1].plot(y[m], 100 * d["r"][1:len(y) + 1][m], **kw)37        ax[1, 1].plot(y[m], 100 * d["r_twoclass"][1:len(y) + 1][m], color=C.get(n, "k"), ls=":", lw=0.8)38        ax[1, 2].plot(y[m], (d["X"] / d["GDP"][:len(y)])[m], **kw)39    ax[0, 0].set_title("Wealth Gini"); ax[0, 1].set_title("Top-10% wealth share"); ax[0, 2].set_title("Top-1% wealth share")40    ax[1, 0].set_title("Bottom-50% wealth share"); ax[1, 1].set_title("Real return: HA (solid) vs two-class (dotted), %")41    ax[1, 2].set_title("Household expenditure / GDP")42    ax[0, 0].legend(fontsize=7)43    for a in ax.ravel():44        a.set_xlim(2026, 2100)45    fig.tight_layout()46    for ext in ("pdf", "png"):47        fig.savefig(os.path.join(FIG, f"fig10_distribution.{ext}"), dpi=200, bbox_inches="tight")48    years = (2026, 2030, 2040, 2050, 2075, 2100)49    with open(os.path.join(TAB, "tab07_distribution.tex"), "w") as f:50        f.write("\\begin{tabular}{@{}ll" + "r" * len(years) + "@{}}\n\\toprule\nScenario & Statistic & " + " & ".join(str(y) for y in years) + "\\\\\n\\midrule\n")51        for n, d in runs.items():52            for stat, lab in [("gini", "Gini"), ("top10", "Top 10\\%"), ("top1", "Top 1\\%"), ("bottom50", "Bottom 50\\%")]:53                vals = []54                for yy in years:55                    i = np.where(d["years"] == yy)[0]56                    vals.append(f"{d[stat][i[0]]:.3f}" if len(i) else "--")57                f.write(f"{LAB.get(n, n) if stat == 'gini' else ''} & {lab} & " + " & ".join(vals) + "\\\\\n")58            vals = []59            for yy in years:60                i = np.where(d["years"] == yy)[0]61                vals.append(f"{100 * d['r'][i[0] + 1]:.1f}" if len(i) else "--")62            f.write(f" & $r$ (\\%) & " + " & ".join(vals) + "\\\\\n\\midrule\n")63        f.write("\\bottomrule\n\\end{tabular}\n")64    nums = {}65    if "baseline" in runs:66        d = runs["baseline"]; i0 = 067        nums["GiniBase"] = f"{d['gini'][0]:.2f}"; nums["TopTenBase"] = f"{d['top10'][0]:.2f}"; nums["TopOneBase"] = f"{d['top1'][0]:.2f}"68        nums["BottomFiftyBase"] = f"{d['bottom50'][0]:.3f}"; nums["betaHigh"] = f"{d['meta']['beta_high']:.4f}"69        for yy in (2050, 2100):70            i = int(np.where(d["years"] == yy)[0][0])71            yw = {2050: "TwoZeroFiveZero", 2100: "TwoOneZeroZero"}[yy]72            nums[f"Gini{yw}"] = f"{d['gini'][i]:.2f}"73            nums[f"TopTen{yw}"] = f"{d['top10'][i]:.2f}"74            nums[f"TopOne{yw}"] = f"{d['top1'][i]:.2f}"75            nums[f"rHA{yw}"] = f"{100 * d['r'][i + 1]:.1f}"76            nums[f"rTC{yw}"] = f"{100 * d['r_twoclass'][i + 1]:.1f}"77        nums["HAconverged"] = "yes" if d["meta"]["converged"] else "no"78        nums["HAmaxGap"] = f"{d['meta']['hist'][-1]:.0e}"79    with open(os.path.join(ROOT, "results", "data", "ha_numbers.json"), "w") as f:80        json.dump(nums, f, indent=1)81    print(nums)82
Files · cdaafa84383ba9e74ff46735fd4b4598b964418c
Menu

Theme