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
97 lines
3.9 KiB
Python
97 lines
3.9 KiB
Python
"""Sanity tests for GADM-0.4 durable capability.
|
|
|
|
Usage: python3 -B -m unittest discover -s simulations/gadm02
|
|
"""
|
|
|
|
import unittest
|
|
|
|
import gadm04 as g
|
|
from scenarios import load_all
|
|
|
|
|
|
class TestDurableCapability(unittest.TestCase):
|
|
def test_bounded(self):
|
|
for name, sc in load_all().items():
|
|
for row in g.simulate(sc["params"], sc["init"]):
|
|
for k in g.STOCKS:
|
|
if not k.startswith("N"):
|
|
self.assertGreaterEqual(row[k], 0.0, (name, k))
|
|
self.assertLessEqual(row[k], 1.0, (name, k))
|
|
|
|
def test_initial_effective_capability_matches_gadm03(self): # H only; W and A differ (T04)
|
|
import gadm03c
|
|
self.assertAlmostEqual(g.simulate(T=0)[0]["H"], gadm03c.simulate(T=0)[0]["H"])
|
|
|
|
def test_initial_state_is_equilibrium_for_wealth_attention_and_channels(self):
|
|
d, _ = g.derivatives(dict(g.INIT), g.PARAMS)
|
|
for k in ("W", "Aw", "As", "Gw", "Gs", "Pm", "Pi", "Pd", "Pmem", "Plin", "Ppol"):
|
|
self.assertLess(abs(d[k]), 1e-4, k)
|
|
|
|
def test_cohort_agency_off_reproduces_aggregate_model(self):
|
|
# T04 state: baseline VFAC 0.320 with aggregate agency
|
|
self.assertAlmostEqual(g.simulate({"cohort_G": 0.0})[-1]["VFAC"], 0.320, places=3)
|
|
|
|
def test_aggregate_agency_is_adult_weighted(self):
|
|
r = g.simulate(T=0)[0]
|
|
w, s_ = r["n_w"], r["n_s"]
|
|
self.assertAlmostEqual(r["G"], (w * r["Gw"] + s_ * r["Gs"]) / (w + s_))
|
|
|
|
def test_calibration_matches_params(self):
|
|
cal = g.calibrate()
|
|
for k, v in cal.items():
|
|
self.assertAlmostEqual(g.PARAMS[k], v, places=6, msg=k)
|
|
|
|
def test_education_reaches_working_age_with_a_lag(self):
|
|
lo, hi = g.simulate({"edu": 1.0}), g.simulate({"edu": 1.5})
|
|
diff = [(a["t"], b["Hw"] - a["Hw"]) for a, b in zip(lo, hi)]
|
|
final = diff[-1][1]
|
|
self.assertGreater(final, 0.0)
|
|
half = next(t for t, x in diff if x >= 0.5 * final)
|
|
self.assertGreaterEqual(half, 10) # L3: a substantial lag ...
|
|
self.assertLessEqual(half, 30) # ... but within a generation
|
|
|
|
|
|
class TestGrounding(unittest.TestCase):
|
|
def test_grounded_variants_start_in_equilibrium(self):
|
|
import grounding as gr
|
|
for name in ("central", "slow"):
|
|
params, init = gr.variant(name)
|
|
d, _ = g.derivatives({**g.INIT, **init}, {**g.PARAMS, **params})
|
|
for k in gr.EQ_KEYS + ("Pm", "Pi", "Pd", "Pmem", "Plin", "Ppol"):
|
|
self.assertLess(abs(d[k]), 1e-3, (name, k))
|
|
|
|
def test_band_is_ordered_by_adoption_speed(self):
|
|
import grounding as gr
|
|
ko = [g.simulate(*gr.variant(gr.BAND[a]))[10]["Ko"] for a in ("B1", "B2", "B3", "B4")]
|
|
self.assertEqual(ko, sorted(ko))
|
|
|
|
def test_self_enhancement_off_by_default(self):
|
|
self.assertEqual(g.PARAMS["selfenh"], 0.0)
|
|
|
|
def test_grounded_adoption_is_slower_than_default(self):
|
|
import grounding as gr
|
|
p, i = gr.variant("central")
|
|
self.assertLess(g.simulate(p, i)[10]["Ko"], g.simulate()[10]["Ko"])
|
|
|
|
def test_legitimacy_loop_off_by_default(self):
|
|
self.assertEqual(g.PARAMS["sent"], 0.0)
|
|
r = g.simulate(T=10)[-1]
|
|
self.assertEqual((r["Sig"], r["Lg"]), (0.5, 0.5))
|
|
|
|
def test_legitimacy_loop_without_response_is_neutral(self):
|
|
# sentiment switched on but with zero gain stays neutral and leaves K_Omega unchanged
|
|
on = g.simulate({"sent": 1.0, "sig_gain": 0.0}, T=30)
|
|
off = g.simulate(T=30)
|
|
self.assertAlmostEqual(on[-1]["Sig"], 0.5, places=9)
|
|
self.assertAlmostEqual(on[-1]["Ko"], off[-1]["Ko"], places=9)
|
|
|
|
def test_legitimacy_loop_damps_aggressive_adoption(self):
|
|
import grounding as gr
|
|
p, i = gr.variant("aggressive")
|
|
off = max(r["Ko"] for r in g.simulate(p, i, T=30))
|
|
on = max(r["Ko"] for r in g.simulate({**p, "sent": 1.0}, i, T=30))
|
|
self.assertLess(on, off)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|