""" 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: Layer 1: F(E) — byte-class frequencies (first 8 of 12 classes) bases 8-15: Layer 2: τ(E) — parse tree node-type frequencies (first 8 of 18 classes) bases 16-23: Layer 3: δ(E) — child-ordering frequencies (first 8 of 648 dimensions) bases 24-29: Layer 4: Consistency rules (G=pass, T=fail) Dependencies: phi.charclass, phi.ast_parse, phi.consistency """ from __future__ import annotations import hashlib import os import sys from typing import Dict, List, Optional # Allow direct execution without package context if not __package__: sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)) or ".") from charclass import compute_F from ast_parse import compute_tau, compute_delta, compute_lambda_and_r, NODE_TYPES from consistency import check_consistency, RULE_ORDER else: from .charclass import compute_F from .ast_parse import compute_tau, compute_delta, compute_lambda_and_r, 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 in [0, 1] to a 3-bit integer in {0..7}. Maps the unit interval onto 8 discrete values via ``round(x * 7)``, then clamps to [0, 7]. Each integer maps to one of the 8 hachimoji bases via INDEX_TO_BASE. Args: x: Float in [0, 1] (values outside are silently clamped). Returns: Integer in {0, 1, 2, 3, 4, 5, 6, 7}. Examples: >>> _float_to_3bit(0.0) 0 >>> _float_to_3bit(1.0) 7 """ return min(7, max(0, round(x * 7))) def _vec_to_bases(values: List[float]) -> str: """Map a list of floats in [0, 1] to hachimoji DNA bases. Each float is independently quantized to a 3-bit index via ``_float_to_3bit``, then mapped through INDEX_TO_BASE so that: {0 → A, 1 → B, 2 → C, 3 → G, 4 → P, 5 → S, 6 → T, 7 → Z} Args: values: Sequence of floats in [0, 1]. Returns: String of hachimoji bases, one per input value. Examples: >>> _vec_to_bases([0.0, 1.0]) 'AZ' """ 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. Layer 1: F(E) — byte-class frequencies on Δ₇ (bases 0-7) 2. Layer 2: τ(E) — AST node-type frequencies (bases 8-15) 3. Layer 3: δ(E) — child-ordering frequencies (bases 16-23) 4. Layer 4: Consistency rules (bases 24-29) 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). Examples: >>> r = encode_phi("x + 1") >>> r is not None True >>> r['length'] 30 >>> all(c in 'ABCGPSTZ' for c in r['dna_sequence']) True >>> r['consistency_dna'] == r['dna_sequence'][-6:] True >>> r['schema'] 'phi_embedding_v2' >>> encode_phi("") is None True """ 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) lambda_val, r = compute_lambda_and_r(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 exactly 8 hachimoji bases F_dna = _vec_to_bases(F[:8]) tau_dna = _vec_to_bases(tau[:8] if tau else [0.5]*8) delta_dna = _vec_to_bases((delta + [0.5]*8)[:8] if delta else [0.5]*8) # 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, "lambda": lambda_val, "r": r, "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", } if __name__ == "__main__": # ────────────────────────────────────────────────────────────────────── # Verification block — run with python -m phi.embed # ────────────────────────────────────────────────────────────────────── # --- _float_to_3bit --------------------------------------------------- assert _float_to_3bit(0.0) == 0, f"_float_to_3bit(0.0) = {_float_to_3bit(0.0)}" assert _float_to_3bit(1.0) == 7, f"_float_to_3bit(1.0) = {_float_to_3bit(1.0)}" mid = _float_to_3bit(0.5) assert mid in (3, 4), f"_float_to_3bit(0.5) = {mid}, expected 3 or 4" # --- _vec_to_bases ---------------------------------------------------- vb = _vec_to_bases([0.0, 1.0, 0.5]) assert len(vb) == 3, f"Expected 3 bases, got {len(vb)}" assert vb[0] == INDEX_TO_BASE[0], f"First base {vb[0]} != A" assert vb[1] == INDEX_TO_BASE[7], f"Second base {vb[1]} != Z" assert all(c in HACHIMOJI_BASES for c in vb), f"Invalid base in {vb}" # --- encode_phi (simple equation) -------------------------------------- r = encode_phi("x + 1") assert r is not None, "encode_phi('x + 1') returned None" assert r["length"] == 30, f"length = {r['length']}, expected 30" assert len(r["dna_sequence"]) == 30, \ f"dna_sequence len = {len(r['dna_sequence'])}, expected 30" assert all(c in HACHIMOJI_BASES for c in r["dna_sequence"]), \ f"Unknown base in {r['dna_sequence']}" # consistency_dna is the last 6 bases assert r["consistency_dna"] == r["dna_sequence"][-6:], \ f"consistency_dna mismatch: {r['consistency_dna']} vs {r['dna_sequence'][-6:]}" # Sub-field lengths assert len(r["F_dna"]) == 8, f"F_dna len = {len(r['F_dna'])}" assert len(r["tau_dna"]) == 8, f"tau_dna len = {len(r['tau_dna'])}" assert len(r["delta_dna"]) == 8, f"delta_dna len = {len(r['delta_dna'])}" # Schema assert r["schema"] == "phi_embedding_v2", \ f"schema = {r['schema']}, expected phi_embedding_v2" # --- Empty string ------------------------------------------------------ assert encode_phi("") is None, "encode_phi('') should be None" assert encode_phi(" ") is None, "encode_phi(' ') should be None" # --- Determinism ------------------------------------------------------- r1 = encode_phi("sin(x) + cos(y)") r2 = encode_phi("sin(x) + cos(y)") assert r1 is not None and r2 is not None assert r1["dna_sequence"] == r2["dna_sequence"], \ f"Determinism broken: {r1['dna_sequence']} != {r2['dna_sequence']}" assert r1["sha256_prefix"] == r2["sha256_prefix"], \ f"Determinism broken for hash: {r1['sha256_prefix']} != {r2['sha256_prefix']}" print("embed: all verification assertions passed.")