MachineSex/figures/plot_E10.py
Giorgio Gilestro 48181a1c84 society: make the sexual-transmission model rigorous (E9 epistasis, E10 directed sex)
Deepen the sexual-reproduction frame before entering the full society, on
the two facets GG chose: landscape robustness and directed recombination.
Adds a Kauffman NK landscape (genotype.nk_fitness, tunable ruggedness),
finite n-parent crossover (genotype.crossover, per-gap recombination rate),
and hill-climb (parents = local optima = trained models).

E9 (recomb_landscape) -- the "why sex?" test: E8's dramatic super-parent
result used an ADDITIVE landscape. On rugged/epistatic landscapes, blindly
recombining local optima causes OUTBREEDING DEPRESSION -- offspring fall
below the parents, worse with both ruggedness and recombination rate (K=8,
free recomb: ~ -0.23), and the optimal recombination rate shrinks as
ruggedness grows. Design rule: merge freely when skills are complementary/
additive; sparingly (and with selection) when entangled.

E10 (directed_sex) -- directed sex beats biological sex: biology is stuck
with 2 random-mating parents and no offspring preview; an AI can choose
complementary mates, evaluate many recombinant offspring, keep the fittest,
and use unbounded parents (iterated recombine-then-select). Random
("biological") sex craters with ruggedness (0.66->0.51); directed sex
tracks/exceeds the best parent at every ruggedness -- converting the
outbreeding-depression catastrophe into a win. No biological analog.

Complete sexual-transmission picture: dramatic super-parent offspring when
skills are complementary (E8); outbreeding-depression risk when entangled
(E9); directed sex resolves the risk (E10). configs/layer1/{E9,E10}.yaml,
figures/plot_{E9,E10}.py, READMEs, +5 tests (117 green).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 11:13:37 +01:00

65 lines
3.1 KiB
Python
Raw 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.

"""E10 figure — directed sex beats biological sex (the distinctly-AI superpower).
On rugged (epistatic) landscapes, blind "biological" sex — random mates, no offspring selection —
suffers outbreeding depression: offspring are worse than the parents. But an AI can do what biology
cannot: choose complementary mates, evaluate *many* recombinant offspring, and keep only the fittest,
over several rounds, with no two-parent limit. This **directed sex** avoids the catastrophe and
matches or exceeds the best parent even when skills are entangled.
Two panels: (A) deployed capability vs landscape ruggedness — best single parent, random (blind) sex,
directed sex, and the global optimum; (B) each strategy's edge over the best parent, making the
random-sex collapse and the directed-sex rescue explicit. Reads only the committed bundle.
Usage: python figures/plot_E10.py [results/E10]
"""
from __future__ import annotations
import sys
from pathlib import Path
import matplotlib.pyplot as plt
sys.path.insert(0, str(Path(__file__).parent))
from _figlib import load_bundle, mean_ci, savefig # noqa: E402
def main(results_dir: str = "results/E10") -> None:
df, _ = load_bundle(results_dir)
fig, axes = plt.subplots(1, 2, figsize=(13, 5))
# Panel A: the three strategies + global optimum vs ruggedness.
ax = axes[0]
for col, c, lab in [("global_opt", "green", "global optimum"),
("directed_sex", "#d62728", "directed sex (AI: choose + select)"),
("best_parent", "#7f7f7f", "best single parent"),
("random_sex", "#1f77b4", "random sex (blind, biology)")]:
k, m, ci = mean_ci(df, "K", col)
ls = ":" if col == "global_opt" else "-o"
ax.plot(k, m, ls, color=c, label=lab) if col == "global_opt" else \
ax.errorbar(k, m, yerr=ci, fmt=ls, color=c, capsize=3, label=lab)
ax.set(xlabel="landscape ruggedness $K$ (epistasis)", ylabel="deployed capability (fitness)",
title="Random sex craters with ruggedness;\ndirected sex tracks/exceeds the best parent")
ax.legend(frameon=False, fontsize=8)
# Panel B: edge over best parent (random collapse vs directed rescue).
ax = axes[1]
bp = df.groupby("K")["best_parent"].mean()
for col, c, lab in [("directed_sex", "#d62728", "directed sex"),
("random_sex", "#1f77b4", "random sex")]:
s = df.groupby("K")[col].mean() - bp
ax.plot(s.index, s.values, "-o", color=c, label=lab)
ax.axhline(0, ls=":", color="gray", lw=1, label="best parent")
ax.set(xlabel="landscape ruggedness $K$", ylabel="capability best parent",
title="Directed sex stays ≥ parents; blind sex\nfalls far below (outbreeding depression)")
ax.legend(frameon=False, fontsize=9)
fig.suptitle("E10 — directed sex beats biological sex: mate choice + offspring selection + "
"unbounded parents rescue recombination where blind sex fails", y=1.02, fontsize=11)
fig.tight_layout()
savefig(fig, results_dir, "E10")
if __name__ == "__main__":
main(*sys.argv[1:])