Research-Stack/4-Infrastructure/shim/genetic_braid_bridge.py
allaun b038778361 feat(lean): SDPVerify, GoormaghtighCert, Hachimoji modules; Gremlin mathblob graph loader; branch cleanup
- SDPVerify.lean: certificate verification engine (714 lines, compiles cleanly)
- GoormaghtighCert.lean: Goormaghtigh conjecture SDP certificate
- HachimojiManifoldAxiom/HachimojiSubstitution: Hachimoji DNA encoding
- GeneticBraidBridge.lean: genetic algorithm braid bridge
- load_dependency_graph/load_module_graph: Gremlin Cosmos DB graph loaders
- test_graph_queries/rrc_math_xref: graph verification queries
- Gremlin mathblob DB provisioned and accessible
- Branch cleanup: deleted 11 stale remote branches

Build: 3297 jobs, 0 errors (lake build Semantics.SDPVerify)
2026-06-19 23:06:16 -05:00

513 lines
18 KiB
Python

#!/usr/bin/env python3
"""GeneticBraidBridge — map ANY genetic alphabet to BraidState.
Accepts DNA, RNA, mRNA, Hachimoji (8-letter), XNA (16-letter hex),
6-state (genetic ground-up), and custom alphabets. Each symbol maps to a
braid generator on one of 8 strands (BraidStorm topology). Codons compose
into braid words. The bridge emits a BraidState JSON ready for:
- eigensolid_convergence (Lean)
- receipt_invertible (Lean)
- RRC classification (LogogramProjection)
- crossStep iteration
- Sidon slack measurement
Usage:
python3 genetic_braid_bridge.py --alphabet dna --seq ATGCCGTAA
python3 genetic_braid_bridge.py --alphabet hachimoji --seq ACGTZPSB
python3 genetic_braid_bridge.py --alphabet xna --seq 0123456789ABCDEF
python3 genetic_braid_bridge.py --alphabet rna --seq AUGCCGUAA --translate
"""
from __future__ import annotations
import argparse
import hashlib
import json
import math
import sys
from dataclasses import dataclass, field, asdict
from typing import Optional
# ── Canonical BraidStorm constants ──────────────────────────────────────
SIDON_LABELS: list[int] = [1, 2, 4, 8, 16, 32, 64, 128]
N_STRANDS = 8
# Golden ratio inverse Q16_16: φ⁻¹ ≈ 0x00009E70
PHI_INV_Q16 = 0x9E70
# ── Genetic alphabet definitions ────────────────────────────────────────
@dataclass(frozen=True)
class GeneticAlphabet:
name: str
symbols: str
bits_per_symbol: int
strand_map: dict[str, int] # symbol → strand index (0..N_STRANDS-1)
complement_map: dict[str, str]
codon_length: int = 3
description: str = ""
# Strand-to-Sidon mapping:
# Each symbol claims a primary strand; the braid generator crosses
# that strand with its pair (strand ^ 1).
# For alphabets ≤4, symbols map to strands 0-3 (4 pairs).
# For alphabets ≤8, symbols map to strands 0-7 (4 pairs).
# For 16-letter alphabets, symbols map in pairs to strands 0-7.
def _build_4sym_strand_map(symbols: str) -> dict[str, int]:
return {s: i for i, s in enumerate(symbols)}
def _build_8sym_strand_map(symbols: str) -> dict[str, int]:
return {s: i for i, s in enumerate(symbols)}
def _build_16sym_strand_map(symbols: str) -> dict[str, int]:
return {s: i % 8 for i, s in enumerate(symbols)}
ALPHABETS: dict[str, GeneticAlphabet] = {
"dna": GeneticAlphabet(
name="dna",
symbols="ACGT",
bits_per_symbol=2,
strand_map=_build_4sym_strand_map("ACGT"),
complement_map={"A": "T", "C": "G", "G": "C", "T": "A"},
codon_length=3,
description="Standard DNA: 4 bases, 64 codons (NCBI Table 1)",
),
"rna": GeneticAlphabet(
name="rna",
symbols="ACGU",
bits_per_symbol=2,
strand_map=_build_4sym_strand_map("ACGU"),
complement_map={"A": "U", "C": "G", "G": "C", "U": "A"},
codon_length=3,
description="RNA: 4 bases, catalytic/regulatory",
),
"mrna": GeneticAlphabet(
name="mrna",
symbols="ACGU",
bits_per_symbol=2,
strand_map=_build_4sym_strand_map("ACGU"),
complement_map={"A": "U", "C": "G", "G": "C", "U": "A"},
codon_length=3,
description="mRNA: messenger RNA, same alphabet as RNA",
),
"hachimoji": GeneticAlphabet(
name="hachimoji",
symbols="ACGTZPSB",
bits_per_symbol=3,
strand_map=_build_8sym_strand_map("ACGTZPSB"),
complement_map={
"A": "T", "C": "G", "G": "C", "T": "A",
"Z": "P", "P": "Z", "S": "B", "B": "S",
},
codon_length=3,
description="Hachimoji: 8 bases, 512 codons (Benner et al.)",
),
"xna": GeneticAlphabet(
name="xna",
symbols="0123456789ABCDEF",
bits_per_symbol=4,
strand_map=_build_16sym_strand_map("0123456789ABCDEF"),
complement_map={}, # no canonical complement for generic XNA
codon_length=2,
description="XNA: 16-symbol hex, 256 2-codons",
),
"genetic6": GeneticAlphabet(
name="genetic6",
symbols="ACGTUX",
bits_per_symbol=3,
strand_map=_build_8sym_strand_map("ACGTUX"), # uses 6 of 8 strands
complement_map={"A": "U", "C": "G", "G": "C", "U": "A", "X": "X"},
codon_length=3,
description="6-state quantum nucleotide (A/C/G/T/U/X from GeneticGroundUp)",
),
}
# ── Sidon / Braid Core ──────────────────────────────────────────────────
@dataclass
class BraidStrand:
phase_x: int = 0
phase_y: int = 0
slot: int = 0
residue: int = 0
jitter: int = 0
bracket_lower: int = 0
bracket_upper: int = 0
bracket_gap: int = 0
bracket_kappa: int = 0
bracket_phi: int = 0
admissible: bool = True
@dataclass
class BraidState:
strands: list[BraidStrand] = field(default_factory=lambda: [BraidStrand() for _ in range(N_STRANDS)])
step_count: int = 0
def _xor_slot(a: int, b: int) -> int:
return a ^ b
def _braid_cross(si: BraidStrand, sj: BraidStrand) -> tuple[BraidStrand, int]:
"""Simulate braidCross: merge two strands, return merged strand + residual."""
zx = si.phase_x + sj.phase_x
zy = si.phase_y + sj.phase_y
slot = _xor_slot(si.slot, sj.slot)
residue = abs(zx - si.phase_x) + abs(zy - si.phase_y)
jitter = si.jitter + sj.jitter
merged = BraidStrand(
phase_x=zx, phase_y=zy, slot=slot,
residue=residue, jitter=jitter,
admissible=True,
)
return merged, residue
def cross_step(state: BraidState) -> BraidState:
"""One BraidStorm crossStep iteration on 4 adjacent pairs."""
def _cross_pair(i: int, j: int) -> BraidStrand:
merged, _ = _braid_cross(state.strands[i], state.strands[j])
return merged
pairs = [(0, 1), (2, 3), (4, 5), (6, 7)]
new_strands = list(state.strands)
for i, j in pairs:
new_strands[i] = _cross_pair(i, j)
new_strands[j] = _braid_cross(state.strands[j], state.strands[i])[0]
return BraidState(strands=new_strands, step_count=state.step_count + 1)
def is_eigensolid(state: BraidState) -> bool:
"""Check if crossStep(state) == state (strand data unchanged)."""
stepped = cross_step(state)
for i in range(N_STRANDS):
s1 = state.strands[i]
s2 = stepped.strands[i]
if (s1.phase_x != s2.phase_x or s1.phase_y != s2.phase_y or
s1.slot != s2.slot or s1.residue != s2.residue):
return False
return True
def iterate_to_convergence(state: BraidState, max_steps: int = 100) -> BraidState:
"""Apply crossStep until eigensolid or max_steps."""
for _ in range(max_steps):
if is_eigensolid(state):
break
state = cross_step(state)
return state
# ── Genetic → Braid translation ────────────────────────────────────────
def normalize_sequence(alphabet: GeneticAlphabet, seq: str) -> str:
allowed = set(alphabet.symbols)
clean = "".join(ch.upper() for ch in seq if not ch.isspace())
bad = sorted({ch for ch in clean if ch not in allowed})
if bad:
raise ValueError(f"{alphabet.name}: unsupported symbols: {''.join(bad)}")
return clean
def symbols_to_braid_word(alphabet: GeneticAlphabet, seq: str) -> list[tuple[int, int]]:
"""Map a genetic sequence to a list of (strand_i, strand_j) crossings.
Each symbol maps to its assigned strand. The braid generator crosses
that strand with its pair (strand ^ 1). Codons (3 symbols) produce
3 crossings that engage their respective strand pairs.
"""
clean = normalize_sequence(alphabet, seq)
word: list[tuple[int, int]] = []
for sym in clean:
s = alphabet.strand_map[sym]
word.append((s, s ^ 1))
return word
def braid_word_to_state(word: list[tuple[int, int]], initial_slots: Optional[list[int]] = None) -> BraidState:
"""Apply a braid word to an initial BraidState.
Each crossing (i, j) XORs the slots and accumulates phase.
"""
slots = list(initial_slots) if initial_slots else list(SIDON_LABELS)
strands = [BraidStrand(slot=slots[i]) for i in range(N_STRANDS)]
state = BraidState(strands=strands, step_count=0)
for i, j in word:
merged, _ = _braid_cross(state.strands[i], state.strands[j])
state.strands[i] = merged
return state
def sequence_to_braid_state(
alphabet: GeneticAlphabet,
seq: str,
initial_slots: Optional[list[int]] = None,
) -> tuple[BraidState, list[tuple[int, int]]]:
"""Full pipeline: genetic sequence → braid word → BraidState."""
word = symbols_to_braid_word(alphabet, seq)
state = braid_word_to_state(word, initial_slots)
return state, word
# ── Receipt emission ────────────────────────────────────────────────────
def encode_receipt(state: BraidState, alphabet: GeneticAlphabet,
seq: str, seq_hash: str, word: list[tuple[int, int]],
logogram_hash: str = "",
) -> dict:
"""Emit a genetic braid receipt JSON.
Matches BraidReceipt structure from BraidEigensolid.lean:
crossing_matrix, sidon_slack, step_count, residuals, write_time, scar_absent
"""
strand0 = state.strands[0]
strand7 = state.strands[7]
sidon_slack = 128 - strand7.slot
residuals = [s.residue for s in state.strands]
max_slot = max(s.slot for s in state.strands)
max_slot_index = max(range(N_STRANDS), key=lambda i: state.strands[i].slot)
receipt = {
"schema": "genetic_braid_receipt_v1",
"generated_at_utc": __import__("datetime").datetime.utcnow().isoformat() + "Z",
"genetic": {
"alphabet": alphabet.name,
"symbols": alphabet.symbols,
"codon_length": alphabet.codon_length,
"sequence_length": len(seq),
"sequence_hash_sha256": seq_hash,
"sequence": seq if len(seq) <= 200 else seq[:100] + "...[truncated]..." + seq[-100:],
},
"braid": {
"word_length": len(word),
"sidon_labels": SIDON_LABELS,
"sidon_slack": max(0, sidon_slack),
"max_slot_used": max_slot,
"max_slot_strand": max_slot_index,
"slots": [s.slot for s in state.strands],
"residues": residuals,
"residue_sum": sum(residuals),
},
"receipt": {
"crossing_matrix": {
"lower": strand0.bracket_lower,
"upper": strand0.bracket_upper,
"gap": strand0.bracket_gap,
"kappa": strand0.bracket_kappa,
"phi": strand0.bracket_phi,
"admissible": strand0.admissible,
},
"sidon_slack": max(0, sidon_slack),
"step_count": state.step_count,
"residuals": residuals,
"write_time": 0,
"scar_absent": all(s.admissible for s in state.strands),
},
"meta_solid": {
"sidon_doublings_total": 7,
"sidon_doublings_consumed": int(math.log2(max(max_slot, 1))).bit_length()
if max_slot > 0 else 0,
"capacity_ratio": round(max_slot / 128.0, 4) if max_slot > 0 else 0,
},
"logogram_hash_sha256": logogram_hash or seq_hash,
"claim_boundary": "genetic-to-braid-bridge;no-lean-spectral;no-classifier",
}
preimage = json.dumps(receipt, sort_keys=True)
receipt["receipt_hash_sha256"] = hashlib.sha256(preimage.encode()).hexdigest()
return receipt
# ── Codon tables ────────────────────────────────────────────────────────
CODON_TABLES: dict[str, dict[str, str]] = {
"standard": {
"TTT": "Phe", "TTC": "Phe", "TTA": "Leu", "TTG": "Leu",
"TCT": "Ser", "TCC": "Ser", "TCA": "Ser", "TCG": "Ser",
"TAT": "Tyr", "TAC": "Tyr", "TAA": "Stop", "TAG": "Stop",
"TGT": "Cys", "TGC": "Cys", "TGA": "Stop", "TGG": "Trp",
"CTT": "Leu", "CTC": "Leu", "CTA": "Leu", "CTG": "Leu",
"CCT": "Pro", "CCC": "Pro", "CCA": "Pro", "CCG": "Pro",
"CAT": "His", "CAC": "His", "CAA": "Gln", "CAG": "Gln",
"CGT": "Arg", "CGC": "Arg", "CGA": "Arg", "CGG": "Arg",
"ATT": "Ile", "ATC": "Ile", "ATA": "Ile", "ATG": "Met",
"ACT": "Thr", "ACC": "Thr", "ACA": "Thr", "ACG": "Thr",
"AAT": "Asn", "AAC": "Asn", "AAA": "Lys", "AAG": "Lys",
"AGT": "Ser", "AGC": "Ser", "AGA": "Arg", "AGG": "Arg",
"GTT": "Val", "GTC": "Val", "GTA": "Val", "GTG": "Val",
"GCT": "Ala", "GCC": "Ala", "GCA": "Ala", "GCG": "Ala",
"GAT": "Asp", "GAC": "Asp", "GAA": "Glu", "GAG": "Glu",
"GGT": "Gly", "GGC": "Gly", "GGA": "Gly", "GGG": "Gly",
},
}
# ── CLI ─────────────────────────────────────────────────────────────────
def _build_arg_parser() -> argparse.ArgumentParser:
p = argparse.ArgumentParser(description=__doc__)
p.add_argument("--alphabet", choices=sorted(ALPHABETS), default="dna",
help="Genetic alphabet")
p.add_argument("--seq", default="",
help="Genetic sequence (raw text)")
p.add_argument("--seq-file", default="",
help="Read sequence from file (FASTA or raw)")
p.add_argument("--codon-table", choices=list(CODON_TABLES),
help="Codon translation table")
p.add_argument("--translate", action="store_true",
help="Translate to amino acids (requires --codon-table or standard)")
p.add_argument("--complement", action="store_true",
help="Show complement sequence")
p.add_argument("--converge", action="store_true",
help="Run crossStep to eigensolid convergence")
p.add_argument("--output", default="",
help="Write receipt JSON to file")
p.add_argument("--table", action="store_true",
help="List supported alphabets")
return p
def main() -> int:
args = _build_arg_parser().parse_args()
if args.table:
rows = []
for name, alpha in sorted(ALPHABETS.items()):
rows.append({
"name": alpha.name,
"symbols": alpha.symbols,
"bits_per_symbol": alpha.bits_per_symbol,
"codon_length": alpha.codon_length,
"n_codons": len(alpha.symbols) ** alpha.codon_length,
"description": alpha.description,
})
print(json.dumps(rows, indent=2))
return 0
alphabet = ALPHABETS[args.alphabet]
# Read sequence
seq = args.seq
if args.seq_file:
with open(args.seq_file) as f:
content = f.read().strip()
if content.startswith(">"):
lines = content.splitlines()
seq = "".join(l for l in lines[1:] if not l.startswith(">"))
else:
seq = content
if not seq:
print("Error: no sequence provided (use --seq or --seq-file)", file=sys.stderr)
return 1
seq = normalize_sequence(alphabet, seq)
seq_hash = hashlib.sha256(seq.encode()).hexdigest()
# Complement
if args.complement:
comp = "".join(alphabet.complement_map.get(s, s) for s in seq)
print(f"Complement: {comp}")
return 0
# Translation
if args.translate:
table_name = args.codon_table or "standard"
table = CODON_TABLES.get(table_name, {})
if not table:
print(f"Error: unknown codon table '{table_name}'", file=sys.stderr)
return 1
# Convert T→U for RNA alphabets
working_seq = seq
if alphabet.name in ("rna", "mrna"):
working_seq = working_seq.replace("T", "U")
codons = [working_seq[i:i+3] for i in range(0, len(working_seq) - 2, 3)]
aa_seq = []
for codon in codons:
aa = table.get(codon, "?")
aa_seq.append(aa)
if aa == "Stop":
break
print(f"Sequence ({alphabet.name}, {len(seq)} bp):")
print(f" {seq}")
print(f"Translation ({table_name}):")
print(f" {'-'.join(aa_seq)}")
degeneracy_map = {
"Phe": 2, "Leu": 6, "Ile": 3, "Met": 1, "Val": 4,
"Ser": 6, "Pro": 4, "Thr": 4, "Ala": 4, "Tyr": 2,
"His": 2, "Gln": 2, "Asn": 2, "Lys": 2, "Asp": 2,
"Glu": 2, "Cys": 2, "Trp": 1, "Arg": 6, "Gly": 4,
"Stop": 3,
}
degeneracies = [degeneracy_map.get(aa, 0) for aa in aa_seq]
avg_degeneracy = round(sum(degeneracies) / max(len(degeneracies), 1), 2)
print(f"\nAvg degeneracy: {avg_degeneracy}")
# Braid bridge
state, word = sequence_to_braid_state(alphabet, seq)
if args.converge:
initial_state = BraidState(
strands=[BraidStrand(slot=SIDON_LABELS[i]) for i in range(N_STRANDS)],
step_count=0,
)
pre_state, pre_word = sequence_to_braid_state(alphabet, seq)
state = iterate_to_convergence(pre_state)
receipt = encode_receipt(state, alphabet, seq, seq_hash, word)
receipt["sidon_meta"] = {
"standard_code_capacity_pct": round(64 / 128 * 100, 1),
"actual_capacity_pct": round(max(s.slot for s in state.strands) / 128 * 100, 1),
"sidon_doublings_consumed": int(math.log2(max(max(s.slot for s in state.strands), 1))) + 1,
"slack_regime": _classify_slack(state),
}
if args.output:
with open(args.output, "w") as f:
json.dump(receipt, f, indent=2)
print(f"Receipt written to {args.output}")
else:
print(json.dumps(receipt, indent=2))
return 0
def _classify_slack(state: BraidState) -> str:
max_slot = max(s.slot for s in state.strands)
slack = 128 - max_slot
if slack >= 64:
return "gas (abundant slack, sparse encoding)"
elif slack >= 8:
return "liquid (moderate slack, efficient encoding)"
elif slack > 0:
return "meta-solid (tight encoding, near capacity)"
else:
return "solid (capacity exceeded, compression regime)"
if __name__ == "__main__":
raise SystemExit(main())