ASSEMBLY-WP-0018-T01: dematerialization vs. Eurostat resource productivity; operator corrected; decoupling depends on phi_r (EU fit 0.66: none; DE 0.15: holds), BR-011; E5 wired

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
This commit is contained in:
tegwick 2026-10-13 23:26:24 +02:00
parent 956b9576b5
commit 78d79ac4e3
9 changed files with 232 additions and 16 deletions

View file

@ -43,6 +43,7 @@ cd simulations/gadm02 && python3 -B nonrival.py # GADM-0.5-dev rival vs. non-r
cd simulations/gadm02 && python3 -B eco_classes.py # GADM-0.5-dev ecological resource classes
cd simulations/gadm02 && python3 -B selection.py # GADM-0.5-dev endogenous selection weights
cd simulations/gadm02 && python3 -B demand.py # GADM-0.5-dev two-good demand split (dematerialization)
cd simulations/gadm02 && python3 -B dematerialization.py # material intensity vs. Eurostat resource productivity; phi_r fit
cd simulations/gadm02 && python3 -B matching.py && python3 -B matching.py --imm # model matching; IMM flip-detection acceptance test (~6 min)
```

View file

@ -259,3 +259,13 @@ values.
CB6 tells whether Argentina moves toward the export path that would let it
out-grow the EU on output (`models/CrossBorder.md` § 7): from about 4.5 % of
GDP upward.
## Dematerialization indicator (ASSEMBLY-WP-0018-T01)
| ID | Indicator | Jurisdiction | Source | Access | Cadence |
|---|---|---|---|---|---|
| E5 | Resource productivity: GDP per kg of domestic material consumption (chain-linked 2015 EUR) | EU, DE | Eurostat `env_ac_rp` (wired in `sources.json`, kind full) | api | a |
E5 constrains the rival share of organism output φ_r through the
material-intensity trend (`models/GADM-0.5.md` § 5). Post-2024 values are the
first that reflect generative-AI adoption.

View file

@ -30,6 +30,7 @@
{"id": "E1-DE", "indicator": "E1", "kind": "full", "jurisdiction": "DE", "label": "CO2 emissions excluding LULUCF", "adapter": "http_json", "url": "https://api.worldbank.org/v2/country/DEU/indicator/EN.GHG.CO2.MT.CE.AR5?format=json&mrnev=1", "path": "1.0.value", "period_path": "1.0.date", "unit": "Mt CO2e", "source": "World Bank WDI (EN.GHG.CO2.MT.CE.AR5)"},
{"id": "E1-AR", "indicator": "E1", "kind": "full", "jurisdiction": "AR", "label": "CO2 emissions excluding LULUCF", "adapter": "http_json", "url": "https://api.worldbank.org/v2/country/ARG/indicator/EN.GHG.CO2.MT.CE.AR5?format=json&mrnev=1", "path": "1.0.value", "period_path": "1.0.date", "unit": "Mt CO2e", "source": "World Bank WDI (EN.GHG.CO2.MT.CE.AR5)"},
{"id": "E2-EU-DE", "indicator": "E2", "kind": "full", "jurisdiction": "EU, DE", "label": "Domestic material consumption per capita", "adapter": "eurostat", "dataset": "env_ac_mfa", "filters": {"geo": ["EU27_2020", "DE"], "material": "TOTAL", "indic_env": "DMC", "unit": "T_HAB"}, "split_by": ["geo"], "last": 1},
{"id": "E4-EU-DE", "indicator": "E4", "kind": "full", "jurisdiction": "EU, DE", "label": "Circular material use rate", "adapter": "eurostat", "dataset": "env_ac_cur", "filters": {"geo": ["EU27_2020", "DE"], "unit": "PC"}, "split_by": ["geo"], "last": 1}
{"id": "E4-EU-DE", "indicator": "E4", "kind": "full", "jurisdiction": "EU, DE", "label": "Circular material use rate", "adapter": "eurostat", "dataset": "env_ac_cur", "filters": {"geo": ["EU27_2020", "DE"], "unit": "PC"}, "split_by": ["geo"], "last": 1},
{"id": "E5-EU-DE", "indicator": "E5", "kind": "full", "jurisdiction": "EU, DE", "label": "Resource productivity (GDP per kg of domestic material consumption, chain-linked 2015 EUR)", "adapter": "eurostat", "dataset": "env_ac_rp", "filters": {"geo": ["EU27_2020", "DE"], "unit": "EUR_KG_CLV15"}, "split_by": ["geo"], "last": 1}
]
}

View file

@ -181,10 +181,8 @@ A *decoupled decade* has VFAC rising, physical throughput falling and K_Ω not
falling, which excludes the artifact of § 1.3. Baseline: decoupled decades
0–0.09, and no sinks breach with or without the split.
Calibration check: throughput per unit of output falls by 0.1–0.5 % per year
in the first decade (split cases included). Observed EU dematerialization is
about 1.6 % per year (resource productivity, 2000–2022). The observed trend
includes efficiency gains that GADM does not model.
Calibration check: see § 5. (A first comparison here used total throughput
per output, which is the wrong operator.)
### 4.3 Readings
@ -201,8 +199,56 @@ includes efficiency gains that GADM does not model.
split moves it 15–50 years later. The strong split removes it within the
horizon at every anchor. Together with low-carbon electricity (§ 2.3), this
is the second lever on the regime's ecological cost.
4. **The readings are conservative against data.** Observed
dematerialization (−1.6 % per year) is three to sixteen times the modeled
intensity decline, because GADM has no autonomous efficiency trend.
Calibrating ε, λ and an efficiency trend to the observed series is the next
step (ASSEMBLY-WP-0018).
4. ~~The readings are conservative against data.~~ **Corrected in § 5:**
that comparison used total throughput per output, which includes compute
energy. On the right operator (material draw per output), the model already
dematerializes as fast as observed. The decoupling reading then depends on
the rival share φ_r, and the EU data do not support it.
## 5. Dematerialization against data (ASSEMBLY-WP-0018-T01)
**Data:** Eurostat resource productivity (`env_ac_rp`, GDP per kg of
domestic material consumption, chain-linked 2015 EUR). It rose 1.85 % per
year in the EU and 2.73 % per year in Germany over 2010–2024. Material
intensity fell at the same rates.
**Operator:** the material draw per unit of output in the first decade from
the calibrated start. Total throughput per output is the wrong operator,
because it includes compute energy, which grows with adoption.
| Jurisdiction | Observed | Model, no split (φ_r 0.2) | Model, split ε 2 (φ_r 0.2) | φ_r that reproduces the data (split ε 2) |
|---|---|---|---|---|
| EU | −1.85 %/y | −2.45 %/y | −2.89 %/y | **0.66** |
| DE | −2.73 %/y | −2.26 %/y | −2.64 %/y | **0.15** |
No efficiency trend is needed: non-rival organism output that needs no
materials already makes output grow faster than material use. The data
constrain the rival share of organism output φ_r, given the demand split. The
two parameters are not separately identified by one series.
Generative regime, demand split at its default (`dematerialization.py`,
`results/dematerialization.md`):
| φ_r | decoupled decades B1 / B2 / B3 / B4 | sinks breach B2 / B3 / B4, no split → split |
|---|---|---|
| 0.15 (fits DE) | 0 / 0.55 / 0.72 / 0.24 | 49 → none / 37 → 67 / 29 → 41 |
| 0.20 (prior) | 0 / 0.45 / 0.71 / 0.22 | 49 → 98 / 37 → 61 / 29 → 40 |
| 0.66 (fits EU) | 0 / 0 / 0 / 0.02 | 49 → 58 / 37 → 43 / 29 → 33 |
Readings:
1. **The decoupling reading of § 4 depends on the non-rival share of organism
output.** It holds when organism output is mostly non-rival (φ_r ≤ 0.2, the
task-data prior and the German fit). It disappears when it is mostly rival
(φ_r 0.66, the EU fit). Recorded as BR-011.
2. **The fit is weakly identified.** The 2010–2024 dematerialization
happened mostly before generative AI, while the model attributes it to
organism output and demand composition. Structural change, the energy
transition and offshoring of material-intensive production are not in the
model. The first decisive data are post-2024 values of E5, now wired into
the full checkpoint.
3. **Practical reading:** whether AI-era growth decouples welfare from
ecological load is an empirical question about *what organisms produce*.
Information services (non-rival) support decoupling. Automation of physical
production (rival) does not. The checkpoints should watch φ_r through L4
(task shares) and E5 (material intensity) together.

View file

@ -23,3 +23,4 @@ that part of the band.
| BR-008 | 2026-10-13 (WP-0011-T05) | Which levers bound domination (BR-007 follow-up) | closed model: host rights levers → coupled model: only host access rules on foreign operators and the home's levers reach the foreign-run channels | measured channels (Pd, Pmem, Plin, Pi) are operated from the US for EU and AR hosts | **structural, implemented:** cross-border coupling (`world.py`); observed DMA effect on search ≈ 0 (at most a 0.006/yr) | update 2026-10-13 (WP-0016-T01): a host lineage access rule does reach imported-lineage concentration (EU Plin 0.91 → 0.19 at a 0.15); portability needs the domestic lineage market's concentration (CB3) |
| BR-009 | 2026-10-13 (WP-0012) | Sentiment dynamics of the legitimacy loop | Σ relaxes toward 0.5 + gain × Δ(perceived benefit), so from the measured US Σ 0.285 it rises → measured US sentiment fell 2021–2026 (0.405 → 0.285) while adoption grew fast | the neutral reference 0.5 is an assumption; US adoption also shows no braking by low sentiment (all loop-on candidates fail the US match) | **resolved 2026-10-13 (WP-0017-T01):** parameter `sig_ref`; calibrated runs anchor Σ at its measured level, and adoption and legislation respond to changes relative to it. Default (None = 0.5) keeps earlier results. R1–R4 and H1/H2 verdicts unchanged; the matching loop weights become ≈ 0.5 | resolved; `sig_adopt` not yet identified |
| BR-010 | 2026-10-13 (WP-0007-T01) | Non-rival growth decouples welfare from throughput (core hypothesis, GADM-0.1 § 14) | output split rival / non-rival (GADM-0.5-dev): no genuine decoupling in any anchor; the generative regime's ecological cost unchanged | GADM has no demand composition: non-rival output adds to, but never replaces, rival consumption | **resolved 2026-10-13 (WP-0007-T04):** two-good demand split; the generative regime decouples in 45–71 % of decades at B2–B3, and its sinks breach moves 15–50 years later; band-dependent (none at B1) | resolved; calibration to observed dematerialization open (WP-0018) |
| BR-011 | 2026-10-13 (WP-0018-T01) | Genuine decoupling in the generative regime (BR-010 resolution) | holds for φ_r ≤ 0.2 (task-data prior; DE dematerialization fit 0.15) → disappears at φ_r 0.66 (EU dematerialization fit) | the reading depends on the rival share of organism output, which the 2010–2024 data constrain only weakly (pre-generative-AI) | none structural; empirical: watch L4 task shares and E5 material intensity after 2024 | open |

View file

@ -0,0 +1,106 @@
"""Calibrate dematerialization to observed resource productivity (ASSEMBLY-WP-0018-T01).
Observed: EU resource productivity (GDP per kg of domestic material consumption, chain-linked
2015 EUR; Eurostat env_ac_rp) rose 1.85 %/year in 2010-2024 (DE 2.73 %/year). Model operator:
the material draw per unit of output (rows "mat" / Y*) in the first decade. The model reproduces
the trend without an efficiency trend; the data constrain the rival share of organism output
phi_r (with the demand split at its default). The T04 readings are re-run at the fitted phi_r.
Usage: python3 -B simulations/gadm02/dematerialization.py
"""
from __future__ import annotations
import json
import sys
from pathlib import Path
sys.dont_write_bytecode = True
import band_probe as bp # noqa: E402
import demand as dm # noqa: E402
import gadm05 as g5 # noqa: E402
import grounding as gr # noqa: E402
from scenarios import load_all # noqa: E402
HERE = Path(__file__).resolve().parent
OUT = HERE / "results"
OBS = {"EU": -0.0185, "DE": -0.0273} # yearly change of material intensity, 2010-2024
SPLIT = {"dm_lam": 0.05, "dm_eps": 2.0}
def cal_start(jur: str) -> tuple[dict, dict]:
st = json.loads((OUT / "calibrated_starts.json").read_text())[jur]
return {k: v for k, v in st["params"].items() if k in g5.PARAMS}, dict(st["init"])
def trend(p: dict, s: dict, eff: float, years: int = 10) -> float:
"""Yearly change of material draw per unit of output over the first `years`."""
rows = g5.simulate_eco(p, s, eco={"rm": "rest"}, demand={**SPLIT, "eff": eff}, T=years, record_every=10)
a, b = rows[0], rows[-1]
return ((b["mat"] / b["Ystar"]) / (a["mat"] / a["Ystar"])) ** (1 / years) - 1
def mat_trend(p: dict, s: dict, phi: float, demand: dict, years: int = 10) -> float:
rows = g5.simulate_eco({**p, "phi_r": phi}, s, eco={"rm": "rest"}, demand=demand, T=years, record_every=10)
a, b = rows[0], rows[-1]
return ((b["mat"] / b["Ystar"]) / (a["mat"] / a["Ystar"])) ** (1 / years) - 1
def fit_phi(p: dict, s: dict, target: float) -> float:
"""Rival share of organism output phi_r that reproduces the observed material-intensity trend."""
lo, hi = 0.0, 1.0
for _ in range(25):
mid = 0.5 * (lo + hi)
lo, hi = (mid, hi) if mat_trend(p, s, mid, SPLIT) < target else (lo, mid)
return 0.5 * (lo + hi)
def main() -> None:
OUT.mkdir(exist_ok=True)
lines = ["# GADM-0.5-dev: dematerialization against observed resource productivity", "",
"Generated by `simulations/gadm02/dematerialization.py` (ASSEMBLY-WP-0018-T01). Observed: material",
"intensity (inverse of Eurostat resource productivity, env_ac_rp, chain-linked 2015 EUR per kg DMC),",
"2010-2024. Model operator: material draw per unit of output in the first decade from the calibrated",
"start (Calibration v0.5) with ecological classes. Total throughput per output is the wrong operator",
"(it includes compute energy).", "",
"## Fit", "",
"| Jurisdiction | observed | model, no split (φ 0.2) | model, split ε 2 (φ 0.2) | φ_r reproducing the observation (split ε 2) |",
"|---|---|---|---|---|"]
phis = {}
for jur, target in OBS.items():
p, s = cal_start(jur)
phis[jur] = fit_phi(p, s, target)
lines.append(f"| {jur} | {100 * target:+.2f} %/y | {100 * mat_trend(p, s, 0.2, {'dm_lam': 0.0}):+.2f} %/y | "
f"{100 * mat_trend(p, s, 0.2, SPLIT):+.2f} %/y | {phis[jur]:.2f} |")
scs = load_all()
var = {a: gr.variant(gr.BAND[a]) for a in dm.ANCHORS}
lines += ["", "## T04 readings at the prior and at the EU-fitted φ_r (generative regime, material replenishment at rest)",
"", "| φ_r | Anchor | decoupled decades no split → split | sinks breach no split → split | VFAC no split → split |",
"|---|---|---|---|---|"]
res = {}
for phi in (0.2, round(phis["DE"], 2), round(phis["EU"], 2)):
for a in dm.ANCHORS:
out = {}
for cn, cd in (("none", {"dm_lam": 0.0}), ("split", SPLIT)):
rows = g5.simulate_eco({**scs["generative_regime"]["params"], **var[a][0], "phi_r": phi},
{**scs["generative_regime"]["init"], **var[a][1]}, eco={"rm": "rest"}, demand=cd)
out[cn] = {"dec": dm.decoupled_windows(rows), "V": rows[-1]["VFAC"],
"sink": next((r["t"] for r in rows if r["Es"] < g5.ECO_PARAMS["eco_floor"]), None)}
res[(phi, a)] = out
fs = lambda x: f"t {x:.0f}" if x is not None else "none" # noqa: E731
lines.append(f"| {phi} | {a} | {out['none']['dec']:.2f} → {out['split']['dec']:.2f} | "
f"{fs(out['none']['sink'])} → {fs(out['split']['sink'])} | {out['none']['V']:.3f} → {out['split']['V']:.3f} |")
lines += ["", "## Readings and robustness class", "", "| Reading | " + " | ".join(dm.ANCHORS) + " | class |",
"|---|" + "---|" * (len(dm.ANCHORS) + 1)]
for phi in sorted({k[0] for k in res}):
vals = [res[(phi, a)]["split"]["dec"] for a in dm.ANCHORS]
lines.append(f"| decoupled decades with split, φ_r {phi} | " + " | ".join(f"{v:+.2f}" for v in vals)
+ f" | {bp.classify(vals, 'sign')} |")
lines.append("")
(OUT / "dematerialization.md").write_text("\n".join(lines))
print("\n".join(lines))
if __name__ == "__main__":
main()

View file

@ -18,6 +18,8 @@ writing, analysis; Anthropic Economic Index), xn = 0.3 (about aX).
from __future__ import annotations
import math
import gadm04 as g4
MODEL_VERSION = "GADM-0.5-dev"
@ -84,7 +86,9 @@ def _draws(s: dict, a: dict, p: dict, q: dict) -> tuple[float, float, float]:
# 1 - dm_eps * (qn - qn0), where qn = (Y_n / Y*) * sqrt(X * Q) is the quality-weighted non-rival
# offer. Physical throughput intensity thr and physical investment aK scale with Cr: the same
# capital stock serves dematerialized demand with less physical load. dm_lam = 0 switches it off.
DEM_PARAMS = {"dm_lam": 0.0, "dm_eps": 2.0}
DEM_PARAMS = {"dm_lam": 0.0, "dm_eps": 2.0, "eff": 0.0}
# eff (WP-0018-T01): autonomous efficiency trend of physical throughput intensity, per year:
# thr(t) = thr0 * Cr(t) * exp(-eff t). Compute energy (e2) has no efficiency trend (conservative).
def nonrival_quality(s: dict, a: dict) -> float:
@ -113,8 +117,8 @@ def simulate_eco(params: dict | None = None, init: dict | None = None, eco: dict
rows = []
steps = int(round(T / dt))
for i in range(steps + 1):
if qd["dm_lam"]:
p = {**p, "thr": thr0 * cr, "aK": aK0 * cr}
if qd["dm_lam"] or qd["eff"]:
p = {**p, "thr": thr0 * cr * math.exp(-qd["eff"] * i * dt), "aK": aK0 * cr}
d, a = g4.derivatives(s, p)
dr, dm, ds = _draws(s, a, p, q)
d["Er"] = rr * (1 - s["Er"]) - dr * s["Er"]
@ -124,7 +128,7 @@ def simulate_eco(params: dict | None = None, init: dict | None = None, eco: dict
if i % record_every == 0:
row = {"t": round(i * dt, 6), **s, "P": g4.g3.total_p(s), "G": a["Gagg"],
**{k: a[k] for k in ("H", "A", "Ystar", "Yr", "Yn", "dem", "B", "V", "Vsel")}, "Cr": cr,
"thru": p["e1"] * s["Kp"] * a["dem"] * p["thr"] + p["e2"] * s["Ko"]}
"thru": p["e1"] * s["Kp"] * a["dem"] * p["thr"] + p["e2"] * s["Ko"], "mat": dm}
row["VFAC"] = g4.g2.vfac(row)
rows.append(row)
if i < steps:

View file

@ -0,0 +1,39 @@
# GADM-0.5-dev: dematerialization against observed resource productivity
Generated by `simulations/gadm02/dematerialization.py` (ASSEMBLY-WP-0018-T01). Observed: material
intensity (inverse of Eurostat resource productivity, env_ac_rp, chain-linked 2015 EUR per kg DMC),
2010-2024. Model operator: material draw per unit of output in the first decade from the calibrated
start (Calibration v0.5) with ecological classes. Total throughput per output is the wrong operator
(it includes compute energy).
## Fit
| Jurisdiction | observed | model, no split (φ 0.2) | model, split ε 2 (φ 0.2) | φ_r reproducing the observation (split ε 2) |
|---|---|---|---|---|
| EU | -1.85 %/y | -2.45 %/y | -2.89 %/y | 0.66 |
| DE | -2.73 %/y | -2.26 %/y | -2.64 %/y | 0.15 |
## T04 readings at the prior and at the EU-fitted φ_r (generative regime, material replenishment at rest)
| φ_r | Anchor | decoupled decades no split → split | sinks breach no split → split | VFAC no split → split |
|---|---|---|---|---|
| 0.2 | B1 | 0.00 → 0.00 | t 83 → none | 0.607 → 0.613 |
| 0.2 | B2 | 0.00 → 0.45 | t 49 → t 98 | 0.583 → 0.598 |
| 0.2 | B3 | 0.00 → 0.71 | t 37 → t 61 | 0.564 → 0.585 |
| 0.2 | B4 | 0.00 → 0.22 | t 29 → t 40 | 0.509 → 0.533 |
| 0.15 | B1 | 0.00 → 0.00 | t 83 → none | 0.607 → 0.613 |
| 0.15 | B2 | 0.00 → 0.55 | t 49 → none | 0.583 → 0.599 |
| 0.15 | B3 | 0.00 → 0.72 | t 37 → t 67 | 0.564 → 0.587 |
| 0.15 | B4 | 0.00 → 0.24 | t 29 → t 41 | 0.509 → 0.535 |
| 0.66 | B1 | 0.00 → 0.00 | t 84 → t 100 | 0.606 → 0.608 |
| 0.66 | B2 | 0.00 → 0.00 | t 49 → t 58 | 0.582 → 0.588 |
| 0.66 | B3 | 0.00 → 0.00 | t 37 → t 43 | 0.563 → 0.571 |
| 0.66 | B4 | 0.00 → 0.02 | t 29 → t 33 | 0.506 → 0.515 |
## Readings and robustness class
| Reading | B1 | B2 | B3 | B4 | class |
|---|---|---|---|---|---|
| decoupled decades with split, φ_r 0.15 | +0.00 | +0.55 | +0.72 | +0.24 | QUALITATIVE BREAK |
| decoupled decades with split, φ_r 0.2 | +0.00 | +0.45 | +0.71 | +0.22 | QUALITATIVE BREAK |
| decoupled decades with split, φ_r 0.66 | +0.00 | +0.00 | +0.00 | +0.02 | QUALITATIVE BREAK |

View file

@ -4,7 +4,7 @@ type: workplan
title: "GADM-0.5 grounding: dematerialization, ecological classes, non-rival output"
domain: communication
repo: assembly-economics
status: proposed
status: active
flavor: residual
depends_on: [ASSEMBLY-WP-0007]
owner: claude-code
@ -25,11 +25,19 @@ GADM-0.5 replaces GADM-0.4 as the reference model.
```task
id: ASSEMBLY-WP-0018-T01
status: todo
status: done
priority: high
state_hub_task_id: "ba4ac94a-0351-52d7-8dbf-64fd837f8303"
```
**Done 2026-10-13:** on the right operator (material draw per output) the
model reproduces the observed trend without an efficiency trend (the first
comparison used total throughput, which was wrong). The data constrain φ_r:
EU 0.66, DE 0.15. At the EU fit, decoupling disappears (BR-011). Weakly
identified, because 2010–2024 is pre-generative-AI. E5 is wired into the full
checkpoint (`sources.json`). `dematerialization.py`, `models/GADM-0.5.md` § 5.
The efficiency parameter `eff` remains available (default 0).
Modeled throughput intensity falls 0.1–0.5 % per year; observed EU
dematerialization is about 1.6 % per year (resource productivity, Eurostat
env_ac_rp / env_ac_mfa, 2000–2022; UNEP IRP for US and AR). Add an autonomous