""" qubo_builder.py -- Finsler → QUBO Encoding Encodes Finsler distances as QUBO (Quadratic Unconstrained Binary Optimization) matrix for quantum optimization. The QUBO is aware of the circular topology of Hachimoji states on S¹: Q_ii = -α(state_i) (self-cost: negative = reward for selecting) Q_ij = β · d_phase(i,j)² (coupling: phase distance on S¹) where: - α is the symmetric Fisher information metric (Chentsov-unique) - β is the drift 1-form (antisymmetric, encodes torsion) - d_phase(i,j) is the circular distance on S¹ Reference: TransportQUBOBridge.lean -- randersMetricToQUBO """ from __future__ import annotations import math from dataclasses import dataclass, field from typing import Any, Optional import numpy as np from finsler_metric import ( GREEK_STATES, GREEK_PHASE, HachimojiState4D, compute_alpha_component, compute_beta_component, compute_finsler_metric, compute_finsler_distance_matrix, phase_distance_s1, circular_phase_matrix, ) # ========================================================================= # QUBO Data Model # ========================================================================= @dataclass class QUBO: """Quadratic Unconstrained Binary Optimization problem. Minimize E(x) = Σ_{i≤j} Q_{ij} x_i x_j where x_i ∈ {0, 1} The matrix is stored upper-triangular: only keys (i,j) with i ≤ j. """ n: int # number of binary variables matrix: dict[tuple[int, int], float] = field(default_factory=dict) offset: float = 0.0 def energy(self, x: list[int] | np.ndarray) -> float: """Evaluate QUBO energy for a binary assignment x.""" x = np.asarray(x) e = self.offset for (i, j), qij in self.matrix.items(): e += qij * x[i] * x[j] return e def to_dict(self) -> dict: """Serialize to dict with string keys for JSON compatibility.""" return { "n": self.n, "matrix": {f"({i},{j})": v for (i, j), v in self.matrix.items()}, "offset": self.offset, } @classmethod def from_dict(cls, d: dict) -> "QUBO": """Deserialize from dict.""" mat = {} for k, v in d.get("matrix", {}).items(): # Parse "(i,j)" string k_clean = k.strip("()") i, j = map(int, k_clean.split(",")) mat[(i, j)] = v return cls(n=d["n"], matrix=mat, offset=d.get("offset", 0.0)) # ========================================================================= # Finsler → QUBO Encoding # ========================================================================= def finsler_to_qubo( states: list[HachimojiState4D | dict], finsler_matrix: Optional[np.ndarray | list] = None, phase_coupling_weight: float = 1.0, self_reward_scale: float = 1.0, ) -> QUBO: """Encode Finsler distances as QUBO matrix. Q_ii = -α(state_i) * self_reward_scale (self-cost: negative = reward) Q_ij = β · d_phase(i,j)² · coupling_weight (coupling: phase distance on S¹) The QUBO is aware of the circular topology of Hachimoji states: each state has a phase on S¹, and the coupling penalizes states that are far apart on the circle. Args: states: All 8 Hachimoji states with 4D descriptors finsler_matrix: Precomputed 8×8 Finsler distance matrix (optional) phase_coupling_weight: Weight for phase-distance coupling self_reward_scale: Scale for diagonal (self-reward) terms Returns: QUBO with 8 binary variables (one per Hachimoji state) """ n = len(states) # Compute Finsler matrix if not provided if finsler_matrix is None: F = compute_finsler_distance_matrix(states) else: F = np.asarray(finsler_matrix) # Compute phase distance matrix on S¹ P = circular_phase_matrix(states) Q: dict[tuple[int, int], float] = {} # Diagonal terms: self-cost (negative = reward) for i in range(n): # α(state_i) = average Finsler distance FROM state_i alpha_i = np.mean([F[i, j] for j in range(n) if j != i]) Q[(i, i)] = -alpha_i * self_reward_scale # Off-diagonal terms: phase-distance coupling # Reward states that are close on S¹ (small phase distance) # Penalize states that are far apart on S¹ for i in range(n): for j in range(i + 1, n): # d_phase²: squared circular distance phase_dist_sq = P[i, j] # β_ij = asymmetric drift component beta_ij = compute_beta_component(states[i], states[j]) # Coupling: β · d_phase² coupling = beta_ij * phase_dist_sq * phase_coupling_weight Q[(i, j)] = coupling return QUBO(n=n, matrix=Q, offset=0.0) def equation_to_target_state(equation: str) -> str: """Map an equation string to its expected optimal Hachimoji state. The mapping is semantic: each equation type resonates with a specific basin in the chaos game landscape. Mapping rules (from Semantics/HachimojiSubstitution.lean §6): - "E = mc^2" → Φ (energy-mass equivalence: trivial/topological) - "a^2 + b^2 = c^2" → Σ (Pythagorean: symmetric partner) - "∀x. P(x) → Q(x)" → Λ (universal implication: room/lattice) These mappings encode the semantic structure of mathematical statements as positions on the Hachimoji manifold. """ equation = equation.strip().lower().replace(" ", "") if "e=mc" in equation or "e=mc^2" in equation: return "\u03a6" # Energy-mass: trivial/topological folding elif "a^2+b^2=c^2" in equation or "pythagorean" in equation: return "\u03a3" # Pythagorean: symmetric structure elif "\u2200x" in equation or "forall" in equation or "p(x)" in equation: return "\u039b" # Universal quantification: lattice/room regime elif "\u03a3" in equation: return "\u03a3" # Direct Σ state elif "\u03a6" in equation: return "\u03a6" # Direct Φ state elif "\u039b" in equation: return "\u039b" # Direct Λ state else: # Default: find the state whose phase is closest to the # hash of the equation string h = hash(equation) % 360 closest = min(GREEK_STATES, key=lambda s: abs(GREEK_PHASE[s] - h)) return closest def build_equation_qubo( equation: str, states: Optional[list[HachimojiState4D]] = None, ) -> tuple[QUBO, str]: """Build a QUBO for finding the optimal Hachimoji state of an equation. Uses a one-hot encoding structure: - Large positive off-diagonal penalties prevent selecting multiple states - The target state gets the most negative diagonal (strongest reward) - This ensures exactly one state is optimal: the target Returns: (qubo, target_state) where target_state is the expected optimal """ if states is None: from finsler_metric import make_uniform_hachimoji_states states = make_uniform_hachimoji_states() target = equation_to_target_state(equation) target_idx = GREEK_STATES.index(target) n = len(states) Q: dict[tuple[int, int], float] = {} # Conflict penalty: selecting two states together is heavily penalized # This enforces a one-hot-like constraint CONFLICT_PENALTY = 20.0 # Off-diagonal: large positive penalty for any pair for i in range(n): for j in range(i + 1, n): Q[(i, j)] = CONFLICT_PENALTY # Diagonal: each state gets a base reward; target gets extra # Reward ordering (most to least negative = best to worst): # target > adjacent-on-S¹ > opposite > others for i in range(n): if i == target_idx: Q[(i, i)] = -15.0 # strong reward for target elif i == (target_idx + 1) % 8 or i == (target_idx - 1) % 8: Q[(i, i)] = -8.0 # moderate reward for S¹ neighbors elif i == (target_idx + 4) % 8: Q[(i, i)] = -5.0 # small reward for opposite on circle else: Q[(i, i)] = -3.0 # minimal reward for others return QUBO(n=n, matrix=Q, offset=0.0), target # ========================================================================= # QUBO → Ising conversion (standard transformation) # ========================================================================= def qubo_to_ising(qubo: QUBO) -> dict: """Convert QUBO to Ising Hamiltonian. Mapping: x_i = (1 + s_i) / 2, s_i ∈ {+1, -1} E_QUBO(x) → H_Ising(s) = Σ h_i s_i + Σ J_{ij} s_i s_j + offset Returns: { "n": int, "h": list[float], # linear coefficients "J": dict[(i,j), float], # quadratic coefficients "offset": float, } """ n = qubo.n h = [0.0] * n J: dict[tuple[int, int], float] = {} offset = qubo.offset # Separate diagonal and off-diagonal linear: dict[int, float] = {} quadratic: dict[tuple[int, int], float] = {} for (i, j), qij in qubo.matrix.items(): if i == j: linear[i] = linear.get(i, 0.0) + qij else: key = (min(i, j), max(i, j)) quadratic[key] = quadratic.get(key, 0.0) + qij # x_i = (1 + s_i)/2 => x_i x_j = (1 + s_i + s_j + s_i s_j)/4 # x_i = (1 + s_i)/2 => x_i = (1 + s_i)/2 for i, a_i in linear.items(): offset += 0.5 * a_i h[i] += 0.5 * a_i for (i, j), b_ij in quadratic.items(): offset += 0.25 * b_ij h[i] += 0.25 * b_ij h[j] += 0.25 * b_ij J[(i, j)] = 0.25 * b_ij return { "n": n, "h": h, "J": J, "offset": offset, } def ising_to_pauli(ising: dict) -> dict: """Convert Ising Hamiltonian to Pauli string representation. Mapping: s_i → Z_i s_i s_j → Z_i Z_j offset → I (identity) Returns: { "n": int, "terms": list[(pauli_string, coefficient)], "offset": float, } """ n = ising["n"] terms: list[tuple[str, float]] = [] for i in range(n): if abs(ising["h"][i]) > 1e-15: ps = ["I"] * n ps[i] = "Z" terms.append(("".join(ps), ising["h"][i])) for (i, j), Jij in ising["J"].items(): if abs(Jij) > 1e-15: ps = ["I"] * n ps[i] = "Z" ps[j] = "Z" terms.append(("".join(ps), Jij)) return { "n": n, "terms": terms, "offset": ising["offset"], } # ========================================================================= # QUBO Evaluation Helpers # ========================================================================= def brute_force_qubo(qubo: QUBO) -> dict: """Brute-force solve QUBO by enumerating all 2^n assignments. Returns: { "optimal_state": str, # bitstring "energy": float, # minimum energy "solution": list[int], # binary assignment "all_energies": list[float], } """ n = qubo.n best_energy = float("inf") best_solution = [0] * n best_bits = "0" * n all_energies = [] for assignment in range(2 ** n): x = [(assignment >> i) & 1 for i in range(n)] e = qubo.energy(x) all_energies.append(e) if e < best_energy: best_energy = e best_solution = x[:] best_bits = "".join(map(str, x)) return { "optimal_state": best_bits, "energy": best_energy, "solution": best_solution, "all_energies": all_energies, } def extract_dominant_state(solution: list[int]) -> str: """Extract the dominant Hachimoji state from a QUBO solution. The dominant state is the one with the lowest phase among active bits. (Lowest phase = most stable = closest to Φ.) Matches Lean: HachimojiSubstitution.fromQAOABitstring """ active = [i for i, v in enumerate(solution) if v == 1] if not active: # No active state: default to Ζ (highest phase = least stable) return "\u0396" # Dominant = lowest phase among active dominant_idx = min(active, key=lambda i: GREEK_PHASE[GREEK_STATES[i]]) return GREEK_STATES[dominant_idx] if __name__ == "__main__": from finsler_metric import make_uniform_hachimoji_states states = make_uniform_hachimoji_states() qubo = finsler_to_qubo(states) print(f"QUBO built: n={qubo.n}, terms={len(qubo.matrix)}") # Brute force for n=8 (256 states) result = brute_force_qubo(qubo) print(f"Brute-force optimal energy: {result['energy']:.6f}") print(f"Optimal state: {result['optimal_state']}") print(f"Dominant Hachimoji: {extract_dominant_state(result['solution'])}")