"""Dynamic-society tests (pure NumPy) — the culminating vertical claim (E11 / C3). Cover the finite-population operators (consensus, conformity, novelty) and the four ablation behaviours: the full society climbs to near the optimum; removing grounding collapses it to an unfit consensus (self-consumption); removing sex or diversity leaves it stuck below the full society. """ from __future__ import annotations import numpy as np from inheritance.dynamic_society import _conformity, _consensus, _novelty, run_dynamic_society def _run(arm_overrides: dict, seed: int = 0, gens: int = 50): base = {"L": 10, "K": 6, "N": 50, "g": 0.85, "mu": 0.03, "novelty": 0.5, "n_off": 100, "recomb_rate": 0.2, "sex": True, "select": "qd"} base.update(arm_overrides) return run_dynamic_society({"society": base, "generations": gens}, seed=seed) def test_consensus_and_conformity(): pop = np.array([[1, 1, 0, 0], [1, 0, 0, 1], [1, 1, 1, 0]], dtype=np.int8) cons = _consensus(pop) assert np.array_equal(cons, [1, 1, 0, 0]) # majority vote per locus conf = _conformity(pop, cons) assert np.isclose(conf[0], 1.0) # agent 0 == consensus assert conf.min() >= 0.0 and conf.max() <= 1.0 def test_novelty_is_zero_for_clones_and_high_for_spread(): clones = np.ones((4, 8), dtype=np.int8) assert np.allclose(_novelty(clones), 0.0) # identical -> no diversity spread = np.array([[0] * 8, [1] * 8], dtype=np.int8) assert np.allclose(_novelty(spread), 1.0) # opposite -> maximal diversity def test_full_society_climbs_toward_optimum(): df = _run({}) go = df["global_opt"].iloc[0] assert df["best_fitness"].iloc[-1] > df["best_fitness"].iloc[0] + 0.05 # it climbs assert df["best_fitness"].iloc[-1] > 0.9 * go # ... to near the optimum def test_no_grounding_collapses_to_unfit_consensus(): full = _run({})["best_fitness"].iloc[-1] dry = _run({"g": 0.0}) assert dry["best_fitness"].iloc[-1] < full - 0.1 # far below the grounded society assert dry["diversity"].iloc[-1] < 0.05 # diversity collapsed assert dry["conformity_true_gap"].iloc[-1] > 0.3 # agreement >> real capability (delusion) def test_ablations_stay_below_the_full_society(): full = _run({})["best_fitness"].iloc[-1] no_sex = _run({"sex": False})["best_fitness"].iloc[-1] no_div = _run({"select": "greedy", "novelty": 0.0})["best_fitness"].iloc[-1] assert no_sex <= full + 1e-6 and no_div <= full + 1e-6 # neither beats the full society assert min(no_sex, no_div) < full # ... and at least one is strictly worse