""" phi.embed — Core Φ embedding: (F, τ, δ) → 30-base hachimoji DNA Combines all four layers into a single encoding pass. This is the only module that knows about the hachimoji alphabet and the DNA sequence layout. DNA layout (30 bases total): bases 0-7: F(E) — byte-class frequencies on Δ₇ bases 8-15: τ(E) — parse tree node-type frequencies bases 16-23: δ(E) — child-ordering frequencies bases 24-29: Layer 4 consistency (G=pass, T=fail) Dependencies: phi.charclass, phi.ast_parse, phi.consistency """ from __future__ import annotations import hashlib from typing import Dict, List, Optional from .charclass import compute_F from .ast_parse import compute_tau, compute_delta, NODE_TYPES from .consistency import check_consistency, RULE_ORDER # ── Hachimoji alphabet ─────────────────────────────────────────────────── HACHIMOJI_BASES = list("ABCGPSTZ") INDEX_TO_BASE = dict(enumerate(HACHIMOJI_BASES)) BASE_TO_INDEX = {b: i for i, b in enumerate(HACHIMOJI_BASES)} # ── Float-to-base conversion ───────────────────────────────────────────── def _float_to_3bit(x: float) -> int: """Quantize a float [0, 1] to a 3-bit integer (0-7).""" return min(7, max(0, round(x * 7))) def _vec_to_bases(values: List[float]) -> str: """Map floats in [0,1] to hachimoji bases (3 bits each, 8 bases).""" return "".join(INDEX_TO_BASE[_float_to_3bit(v)] for v in values) # ── Core encoding ──────────────────────────────────────────────────────── def encode_phi(equation: str) -> Optional[Dict]: """Apply Φ mapping: equation string → 30-base hachimoji DNA sequence. The four layers are: 1. F(E) — byte-class histogram (Δ₇) 2. (implicit — derived from the phase-alphabet mapping) 3. τ(E) + δ(E) — parse tree structure 4. 6 consistency rules → primer-binding region Returns a dict with the DNA sequence and all intermediate values, or None if the equation is empty. The returned dict is the standard Φ encoding record consumed by phi.output (FASTQ, Adleman graph, PCR protocol). """ if not equation or not equation.strip(): return None F = compute_F(equation) consistency = check_consistency(equation) tau = compute_tau(equation) delta = compute_delta(equation) # Fallback for unparseable equations: uniform distribution # (encodes as all-A — "null structural signal") if tau is None: tau = [1.0 / len(NODE_TYPES)] * len(NODE_TYPES) # Encode each layer as 8 hachimoji bases F_dna = _vec_to_bases(F[:8]) tau_dna = _vec_to_bases(tau[:8]) delta_dna = _vec_to_bases(delta[:8]) if delta else "AAAAAAAA" # Layer 4: encode consistency G=pass T=fail consistency_dna = "".join("G" if consistency[r] else "T" for r in RULE_ORDER) full_sequence = F_dna + tau_dna + delta_dna + consistency_dna quality_scores = "".join("A" if v else "P" for v in consistency.values()) seq_hash = hashlib.sha256(full_sequence.encode()).hexdigest()[:16] return { "equation": equation, "dna_sequence": full_sequence, "length": len(full_sequence), "bases": list(HACHIMOJI_BASES), "schema": "phi_embedding_v2", "F": [round(x, 4) for x in F], "tau": [round(x, 4) for x in tau], "delta": [round(x, 4) for x in delta] if delta else None, "F_dna": F_dna, "tau_dna": tau_dna, "delta_dna": delta_dna, "consistency": consistency, "consistency_pass": all(consistency.values()), "consistency_dna": consistency_dna, "quality_scores": quality_scores, "sha256_prefix": seq_hash, "pas_primer": "CCCCCC", "fail_primer": "AAAAAA", }