paper (Phase 2): fold hardened E13 into both versions, citation refresh, arXiv package
Speciation section rewritten around the hardened results: alignment modulo the full function-preserving symmetry group (answers 2606.23607 preemptively), the hybrid-fitness cliff (0.97 -> 0.03), the mu(S)/2 floor, and the pre-registered emergent converse (no isolation without functional conflict; the merge rescues forgetting specialists) — in the abstract, §5, §13 ledger, and the accessible version. Citation refresh (author names verified via arXiv API): concede First-Extinction Law (Benati 2509.20101) and quantitative-trait collapse (Yoon 2407.17493) alongside Riis; add verifier-injection (Yi 2510.16657), Livnat & Papadimitriou (CACM 2016) as the sex-as-computation precursor, and the adjacent 2024-26 merge/LMC/multi-agent literature (Ainsworth, Pari, Zhou, Cao, Sharma, Hu, Kozodoi, Li & Shen, Harris, Chen, Tanaka). arXiv package (paper/arxiv/): md2tex.py — a small block-based Markdown->LaTeX converter keeping the Markdown as source of truth — main.tex, generated body.tex, 3 vector figures; builds clean under tectonic (20 pp; pdflatex hint guarded for arXiv); ARXIV-SUBMISSION.md carries categories, license note, and a <=1,920-char abstract. 149 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BkRLcc18rwT2Lysu6PbG7v
This commit is contained in:
parent
ea051a5f92
commit
d6a5c5cacd
11 changed files with 671 additions and 44 deletions
159
paper/arxiv/md2tex.py
Normal file
159
paper/arxiv/md2tex.py
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
r"""Deterministic Markdown -> LaTeX converter for the arXiv preprint (paper-specific, not general).
|
||||
|
||||
Converts `paper/the-evolution-of-sex-for-ai.md` into `body.tex`, which `main.tex` inputs. Kept
|
||||
deliberately dumb and auditable: the paper uses a small Markdown subset (##/### headings, bold,
|
||||
italics, inline code, links, bullet/numbered lists, one blockquote, horizontal rules, and
|
||||
`(Figure: \`path\`.)` figure references), and this script handles exactly that subset. Re-run after
|
||||
editing the Markdown; the Markdown remains the source of truth.
|
||||
|
||||
Usage: python paper/arxiv/md2tex.py
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
SRC = Path(__file__).resolve().parents[1] / "the-evolution-of-sex-for-ai.md"
|
||||
OUT = Path(__file__).resolve().parent / "body.tex"
|
||||
|
||||
# Figure references in the text -> (graphics file under figs/, caption).
|
||||
FIGURES = {
|
||||
"results/E14/E14.png": ("figs/E14.pdf",
|
||||
"Mating systems (E14): the best mate-pool breadth shrinks as skills get more entangled. "
|
||||
"(A) best fitness peaks at intermediate breadth on rugged landscapes; (B) the population mean "
|
||||
"is monotonically favoured by promiscuity; (C) diversity is monotonically destroyed by it."),
|
||||
"results/E12/E12.png": ("figs/E12.pdf",
|
||||
"Model speciation, analytic (E12): hybrid fitness vs divergence traces compatible $\\rightarrow$ "
|
||||
"outbreeding depression $\\rightarrow$ inviability; the isolation cliff arrives earlier the "
|
||||
"denser the incompatibilities (epistasis), and damage grows super-linearly (the Orr--Turelli "
|
||||
"snowball)."),
|
||||
"results/speciation_real/speciation_real.png": ("figs/speciation_real.pdf",
|
||||
"Model speciation in real weights (E13). (A) the merge barrier decomposed by alignment "
|
||||
"strength: the independent-init barrier is a coordinate artefact (removed by alignment); the "
|
||||
"conflict barrier survives even the full function-preserving symmetry group. (B) the isolation "
|
||||
"cliff: residual barrier rises and hybrid accuracy falls ($0.97 \\rightarrow 0.03$) with "
|
||||
"functional conflict. (C) the pre-registered emergent test: divergent-but-compatible "
|
||||
"specialists develop no isolation at any divergence --- the merge instead rescues them "
|
||||
"(Fisher--Muller)."),
|
||||
}
|
||||
|
||||
UNICODE = {
|
||||
"—": "---", "–": "--", "→": r"\(\rightarrow\)", "≈": r"\(\approx\)",
|
||||
"≥": r"\(\geq\)", "×": r"\(\times\)", "·": r"\(\cdot\)", "μ": r"\(\mu\)",
|
||||
}
|
||||
|
||||
SPECIALS = {"&": r"\&", "%": r"\%", "#": r"\#", "_": r"\_", "$": r"\$",
|
||||
"~": r"\textasciitilde{}", "^": r"\textasciicircum{}"}
|
||||
|
||||
|
||||
def esc(s: str) -> str:
|
||||
s = s.replace("\\", r"\textbackslash{}")
|
||||
for k, v in SPECIALS.items():
|
||||
s = s.replace(k, v)
|
||||
for k, v in UNICODE.items():
|
||||
s = s.replace(k, v)
|
||||
return s
|
||||
|
||||
|
||||
def inline(s: str) -> str:
|
||||
"""Escape + convert inline markup. Code spans are protected, then bold, italic, links."""
|
||||
parts = re.split(r"(`[^`]*`)", s)
|
||||
out = []
|
||||
for p in parts:
|
||||
if p.startswith("`") and p.endswith("`") and len(p) >= 2:
|
||||
out.append(r"\texttt{" + esc(p[1:-1]) + "}")
|
||||
else:
|
||||
p = esc(p)
|
||||
p = re.sub(r"\[([^\]]+)\]\((https?://[^)]+)\)", r"\\href{\2}{\1}", p)
|
||||
p = re.sub(r"\*\*([^*]+)\*\*", r"\\textbf{\1}", p)
|
||||
p = re.sub(r"\*([^*]+)\*", r"\\emph{\1}", p)
|
||||
p = re.sub(r'"([^"]+)"', r"``\1''", p) # straight quotes -> LaTeX quotes
|
||||
out.append(p)
|
||||
return "".join(out)
|
||||
|
||||
|
||||
def figure_block(md_path: str) -> str:
|
||||
gfx, caption = FIGURES[md_path]
|
||||
return ("\\begin{figure*}[t]\\centering\n"
|
||||
f"\\includegraphics[width=\\textwidth]{{{gfx}}}\n"
|
||||
f"\\caption{{{caption}}}\n\\end{{figure*}}\n")
|
||||
|
||||
|
||||
def convert(text: str) -> str:
|
||||
"""Block-based conversion: soft-wrapped lines are joined per paragraph/item BEFORE inline
|
||||
conversion, so bold/italic/code spans and figure pointers crossing a line break work."""
|
||||
fig_queue: list[str] = []
|
||||
|
||||
def fig_sub(m):
|
||||
path = m.group(1)
|
||||
if path in FIGURES:
|
||||
fig_queue.append(figure_block(path))
|
||||
return ""
|
||||
return m.group(0)
|
||||
|
||||
lines = text.split("\n")
|
||||
i = 0
|
||||
# Skip the header block (title/subtitle/author) up to and including the first horizontal rule:
|
||||
# main.tex composes the title page itself.
|
||||
while i < len(lines) and lines[i].strip() != "---":
|
||||
i += 1
|
||||
i += 1
|
||||
|
||||
# Group into blocks separated by blank lines; a block is a heading, rule, quote, list, or paragraph.
|
||||
blocks: list[list[str]] = []
|
||||
cur: list[str] = []
|
||||
for line in lines[i:]:
|
||||
if line.strip() == "":
|
||||
if cur:
|
||||
blocks.append(cur); cur = []
|
||||
else:
|
||||
cur.append(line)
|
||||
if cur:
|
||||
blocks.append(cur)
|
||||
|
||||
def emit_para(joined: str, out: list[str]) -> None:
|
||||
joined = re.sub(r"\(Figure: `([^`]+)`\.?\)", fig_sub, joined)
|
||||
joined = re.sub(r"\s{2,}", " ", joined).strip()
|
||||
if joined:
|
||||
out.append(inline(joined))
|
||||
out.append("")
|
||||
while fig_queue:
|
||||
out.append(fig_queue.pop(0)); out.append("")
|
||||
|
||||
out: list[str] = []
|
||||
for block in blocks:
|
||||
first = block[0].strip()
|
||||
if first == "---" and len(block) == 1:
|
||||
out.append("\\medskip\\hrule\\medskip"); out.append("")
|
||||
elif first.startswith("## "):
|
||||
out.append(f"\\section*{{{inline(first[3:])}}}"); out.append("")
|
||||
elif first.startswith("### "):
|
||||
out.append(f"\\subsection*{{{inline(first[4:])}}}"); out.append("")
|
||||
elif first.startswith("> "):
|
||||
joined = " ".join(l.strip().lstrip("> ").strip() for l in block)
|
||||
out.append("\\begin{quote}" + inline(joined) + "\\end{quote}"); out.append("")
|
||||
elif re.match(r"^(- |\d+\. )", first):
|
||||
env = "itemize" if first.startswith("- ") else "enumerate"
|
||||
out.append(f"\\begin{{{env}}}")
|
||||
items: list[str] = []
|
||||
for l in block:
|
||||
s = l.strip()
|
||||
if re.match(r"^(- |\d+\. )", s):
|
||||
items.append(re.sub(r"^(- |\d+\. )", "", s))
|
||||
else:
|
||||
items[-1] = items[-1] + " " + s # soft-wrapped continuation of the item
|
||||
for it in items:
|
||||
it = re.sub(r"\(Figure: `([^`]+)`\.?\)", fig_sub, it)
|
||||
out.append("\\item " + inline(it.strip()))
|
||||
out.append(f"\\end{{{env}}}"); out.append("")
|
||||
while fig_queue:
|
||||
out.append(fig_queue.pop(0)); out.append("")
|
||||
else:
|
||||
emit_para(" ".join(l.strip() for l in block), out)
|
||||
return "\n".join(out) + "\n"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
OUT.write_text(convert(SRC.read_text()))
|
||||
print(f"wrote {OUT}")
|
||||
Loading…
Add table
Add a link
Reference in a new issue