assembly-economics/simulations/gadm02/eco_classes.py
tegwick 8dd9e97d33 ASSEMBLY-WP-0007-T02: ecological resource classes (renewables, materials, sinks); sinks bind the generative regime; grounding test passed; low-carbon lever
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 14913@bnt-lap001
Assistant-Session: add7ef69-b901-4756-9a67-34cf1125d96f
2026-10-13 23:11:25 +02:00

76 lines
3.4 KiB
Python
Raw Permalink 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.

"""Ecological resource classes across the adoption band (ASSEMBLY-WP-0007-T02).
Which class binds first per scenario (GADM-Sectors-Scope.md § 2)? Does organism growth bind
energy and sinks before materials (ParameterGrounding.md § 3 test)?
Classes: renewables Er (energy, land, water, biosphere), materials Ed, sinks Es; floors 0.20.
Materials with strict depletion (rm 0) or replenishment at rest today (rm "rest").
Usage: python3 -B simulations/gadm02/eco_classes.py
"""
from __future__ import annotations
import sys
from pathlib import Path
sys.dont_write_bytecode = True
import gadm05 as g5 # noqa: E402
import grounding as gr # noqa: E402
from scenarios import load_all # noqa: E402
OUT = Path(__file__).resolve().parent / "results"
ANCHORS = list(gr.BAND)
NAMES = {"Er": "renewables", "Ed": "materials", "Es": "sinks"}
FLOOR = g5.ECO_PARAMS["eco_floor"]
def crossing(rows: list[dict], k: str) -> str:
if rows[0][k] < FLOOR:
return "below at start"
for r in rows:
if r[k] < FLOOR:
return f"t {r['t']:.0f}"
return "—"
def main() -> None:
OUT.mkdir(exist_ok=True)
scs = load_all()
var = {a: gr.variant(gr.BAND[a]) for a in ANCHORS}
lines = ["# GADM-0.5-dev: ecological resource classes across the band", "",
"Generated by `simulations/gadm02/eco_classes.py` (ASSEMBLY-WP-0007-T02). Floors 0.20 per class.",
"Starting levels and loads: `gadm05.py` (priors from measured indicators). Crossing = first year",
"below the floor. t = 100 levels.", ""]
res = {}
for rm in (0.0, "rest"):
lines += [f"## Materials replenishment: {'none (strict depletion)' if rm == 0.0 else 'at rest today'}", "",
"| Scenario | Anchor | Er / Ed / Es t100 | renewables below floor | materials below floor | sinks below floor | lowest at t100 |",
"|---|---|---|---|---|---|---|"]
for sc in ("baseline", "generative_regime", "attention_oligopoly"):
for a in ANCHORS:
rows = g5.simulate_eco({**scs[sc]["params"], **var[a][0]}, {**scs[sc]["init"], **var[a][1]},
eco={"rm": rm})
f = rows[-1]
res[(rm, sc, a)] = rows
low = min(g5.ECO, key=lambda k: f[k])
lines.append(f"| {scs[sc]['title']} | {a} | {f['Er']:.2f} / {f['Ed']:.2f} / {f['Es']:.2f} | "
f"{crossing(rows, 'Er')} | {crossing(rows, 'Ed')} | {crossing(rows, 'Es')} | {NAMES[low]} |")
lines.append("")
lines += ["## Organism growth: class draw attributable to adoption speed (baseline, B4 − B1)", "",
"Relative change of each class between t 0 and t 50, B4 minus B1 (negative = organisms draw more).", "",
"| Materials replenishment | renewables | materials | sinks | order (most hit first) |", "|---|---|---|---|---|"]
for rm in (0.0, "rest"):
rel = {}
for k in g5.ECO:
r4, r1 = res[(rm, "baseline", "B4")], res[(rm, "baseline", "B1")]
rel[k] = (r4[5][k] / r4[0][k] - 1) - (r1[5][k] / r1[0][k] - 1)
order = " > ".join(NAMES[k] for k in sorted(rel, key=lambda k: rel[k]))
lines.append(f"| {'none' if rm == 0.0 else 'at rest'} | {rel['Er']:+.3f} | {rel['Ed']:+.3f} | {rel['Es']:+.3f} | {order} |")
lines.append("")
(OUT / "eco_classes.md").write_text("\n".join(lines))
print("\n".join(lines))
if __name__ == "__main__":
main()