assembly-economics/simulations/gadm02/grounded_readings.py
tegwick 218d196738 ASSEMBLY-WP-0008: empirical grounding of key GADM parameters
- Research on organism adoption, commons, power persistence, lobbying,
  human-capital persistence, age gaps and care load
- grounding.py: grounded parameter sets (central / slow adoption) with own
  equilibrium start and recalibrated channels; tested
- grounded_readings.py: all structural readings survive grounding; default
  adopts organisms too fast; governance stakes rise with adoption speed;
  care load overstated ~4x (joint recalibration of attention extraction)
- ParameterGrounding.md v0.2: register with statuses, evidence, mappings,
  validation/falsification tests for ASSEMBLY-WP-0007
- GADM-0.4 model version finalised

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1494246@bnt-lap001
Assistant-Session: caf6de6f-f9e4-47ce-a584-49baa271fa4b
2026-10-12 09:45:19 +02:00

92 lines
4.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Key readings under the evidence-grounded parameter sets (ASSEMBLY-WP-0008).
Compares GADM-0.4 defaults with the grounded 'central' and 'slow' adoption
variants on: scenario VFAC and ranking, lowest domination, organism lever
order, P3 (wealth tax), L2/G3 (care relief), and attention levels.
Usage: python3 -B simulations/gadm02/grounded_readings.py
"""
from __future__ import annotations
import itertools
import sys
from pathlib import Path
sys.dont_write_bytecode = True
import gadm04 as g # noqa: E402
import grounding as gr # noqa: E402
from scenarios import load_all # noqa: E402
OUT = Path(__file__).resolve().parent / "results"
GRID = {"lineage": ({"L": 0.1, "lin_open": 0.1}, {"L": 0.8, "lin_open": 0.8}),
"membrane": ({"m": 0.2}, {"m": 0.8}),
"attention": ({"x_att": 0.9}, {"x_att": 0.2})}
def sim(sc: dict, prm: dict, ini: dict, extra: dict | None = None) -> dict:
return g.simulate({**sc["params"], **prm, **(extra or {})}, {**sc["init"], **ini})[-1]
def main() -> None:
OUT.mkdir(exist_ok=True)
scs = load_all()
variants = [("GADM-0.4 defaults", {}, {}), ("grounded, central adoption", *gr.variant("central")),
("grounded, slow adoption", *gr.variant("slow"))]
lines = [f"# {g.MODEL_VERSION}: readings under grounded parameters", "",
"Generated by `simulations/gadm02/grounded_readings.py`. t = 100 years.",
"Grounded sets: `simulations/gadm02/grounding.py`; justification in",
"`models/ParameterGrounding.md`.", "",
"## Scenarios (VFAC / P / A)", "",
"| Scenario | " + " | ".join(v[0] for v in variants) + " |", "|---|" + "---|" * len(variants)]
res = {v[0]: {n: sim(sc, v[1], v[2]) for n, sc in scs.items()} for v in variants}
for n, sc in scs.items():
lines.append(f"| {sc['title']} | " + " | ".join(
f"{res[v[0]][n]['VFAC']:.3f} / {res[v[0]][n]['P']:.2f} / {res[v[0]][n]['A']:.2f}" for v in variants) + " |")
lines += ["", "## Key readings", "",
"| Reading | " + " | ".join(v[0] for v in variants) + " |", "|---|" + "---|" * len(variants)]
names = list(scs)
ref = sorted(names, key=lambda n: -res[variants[0][0]][n]["VFAC"])
rows = {k: [] for k in ("best", "worst", "rho", "lowP", "levers", "order", "p3", "care", "kO")}
for label, prm, ini in variants:
r = res[label]
order = sorted(names, key=lambda n: -r[n]["VFAC"])
rank = {n: i for i, n in enumerate(order)}
rref = {n: i for i, n in enumerate(ref)}
k = len(names)
rows["best"].append(scs[order[0]]["title"])
rows["worst"].append(scs[order[-1]]["title"])
rows["rho"].append(f"{1 - 6 * sum((rank[n] - rref[n]) ** 2 for n in names) / (k * (k * k - 1)):.2f}")
rows["lowP"].append(scs[min(names, key=lambda n: r[n]["P"])]["title"])
out = {}
for lv in itertools.product((0, 1), repeat=3):
ex = {}
for ax, l in zip(GRID, lv):
ex.update(GRID[ax][l])
out[lv] = sim(scs["baseline"], prm, ini, ex)["VFAC"]
eff = [sum((1 if lv[i] else -1) * v for lv, v in out.items()) / 4 for i in range(3)]
rows["levers"].append(" / ".join(f"{e:+.3f}" for e in eff))
rows["order"].append("yes" if eff[0] > eff[1] > eff[2] > 0 else "no")
mem = scs["generative_concentrated_lineages"]
dp = sim(mem, prm, ini, {"wtax": 1.0})["P"] - sim(mem, prm, ini, {"wtax": 0.0})["P"]
rows["p3"].append(f"{dp:+.3f} ({'holds' if -dp < 0.06 else 'fails'})")
b0 = sim(scs["baseline"], prm, ini, {"cp": 0.0})
b1 = sim(scs["baseline"], prm, ini, {"cp": 0.30})
b1c = sim(scs["baseline"], prm, ini, {"cp": 0.30, "care_relief": 0.0})
gain = b1["Gs"] - b0["Gs"]
rows["care"].append(f"Gs +{gain:.3f}, care share {((b1['Gs'] - b1c['Gs']) / gain):.0%}" if gain > 0 else "—")
bl = g.simulate({**scs["baseline"]["params"], **prm}, {**scs["baseline"]["init"], **ini})
rows["kO"].append(f"{bl[10]['Ko']:.2f} / {bl[25]['Ko']:.2f} / {bl[-1]['Ko']:.2f}")
labels = {"best": "best scenario", "worst": "worst scenario", "rho": "ranking ρ vs. defaults",
"lowP": "lowest domination", "levers": "lineage / membrane / attention effect",
"order": "lever order lineage > membrane > attention", "p3": "P3: wealth tax ΔP",
"care": "G3: senior agency gain at cp 0.3", "kO": "baseline K_Ω at t 10 / 25 / 100"}
for k, lab in labels.items():
lines.append(f"| {lab} | " + " | ".join(rows[k]) + " |")
(OUT / "grounded_readings.md").write_text("\n".join(lines) + "\n")
print("\n".join(lines))
if __name__ == "__main__":
main()