- Wealth-concentration stock W with wealth-tax lever; converts into market and political channels only, moderated by checks (Q*S) - wealth_on switch reproduces the T03 model exactly (verified) - wealth.py: P3 supported and robust to conversion strength (full wealth tax lowers P by only 0.01-0.05 because membrane/lineage control does not run on wealth); effect on reachable channels depends on k_w - Tests for wealth switch and tax direction 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
57 lines
2 KiB
Python
57 lines
2 KiB
Python
"""Sanity tests for the GADM-0.3 power-channel model.
|
|
|
|
Usage: python3 -B -m unittest discover -s simulations/gadm02
|
|
"""
|
|
|
|
import unittest
|
|
|
|
import gadm03 as g
|
|
from scenarios import load_all
|
|
|
|
|
|
class TestGADM03(unittest.TestCase):
|
|
def test_stocks_stay_bounded_in_all_scenarios(self):
|
|
for name, sc in load_all().items():
|
|
for row in g.simulate(sc["params"], sc["init"]):
|
|
for k in g.STOCKS + ("P",):
|
|
self.assertGreaterEqual(row[k], 0.0, (name, k))
|
|
self.assertLessEqual(row[k], 1.0, (name, k))
|
|
|
|
def test_calibration_matches_params(self):
|
|
self.assertEqual(g.calibrate(), {c: g.PARAMS[c] for c in g.COEF.values()})
|
|
|
|
def test_initial_channels_are_stable_equilibria(self):
|
|
# Guards against calibrating a channel onto its unstable (threshold) root.
|
|
d, _ = g.derivatives(dict(g.INIT), g.PARAMS)
|
|
for k in g.CHANNELS:
|
|
self.assertAlmostEqual(d[k], 0.0, places=3, msg=k)
|
|
self.assertLess(g.channel_slope(dict(g.INIT), g.PARAMS, k), 0.0, k)
|
|
|
|
def test_one_dominant_channel_gives_full_domination(self):
|
|
s = {k: 0.0 for k in g.CHANNELS}
|
|
s["Plin"] = 1.0
|
|
self.assertAlmostEqual(g.total_p(s), 1.0)
|
|
|
|
def test_aggregation_does_not_compound_equal_channels(self):
|
|
s = {k: 0.5 for k in g.CHANNELS}
|
|
self.assertAlmostEqual(g.total_p(s), 0.5)
|
|
|
|
def test_wealth_off_ignores_wealth(self):
|
|
p = g.t03_params()
|
|
a = g.simulate(p, {"W": 0.1})[-1]
|
|
b = g.simulate(p, {"W": 0.9})[-1]
|
|
for k in g.CHANNELS:
|
|
self.assertAlmostEqual(a[k], b[k], places=12, msg=k)
|
|
|
|
def test_wealth_tax_lowers_wealth(self):
|
|
lo = g.simulate({"wtax": 0.0})[-1]["W"]
|
|
hi = g.simulate({"wtax": 1.0})[-1]["W"]
|
|
self.assertLess(hi, lo)
|
|
|
|
def test_unknown_parameter_rejected(self):
|
|
with self.assertRaises(KeyError):
|
|
g.simulate({"not_a_param": 1.0})
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|