testing_space / practicality_oracle.py
everydaytok's picture
Update practicality_oracle.py
fb1a734 verified
import math
import copy
import json
import numpy as np
from fractions import Fraction
from typing import Dict, Tuple, Optional, Any, Callable
from dataclasses import dataclass, field
# ══════════════════════════════════════════════════════════════════════
# SECTION A: HEISENBERG QUANTUM SIMULATOR (CHP Stabilizer State)
# ══════════════════════════════════════════════════════════════════════
@dataclass
class StabilizerTableau:
n: int
tableau: np.ndarray = field(default=None)
def __post_init__(self):
if self.tableau is None:
self.tableau = np.zeros((2*self.n, 2*self.n+1), dtype=np.uint8)
for i in range(self.n):
self.tableau[i, i] = 1; self.tableau[self.n+i, self.n+i] = 1
class HeisenbergSimulator:
def __init__(self, n_qubits: int):
self.n = n_qubits
self.state = StabilizerTableau(n_qubits)
self.gate_count = 0
def copy(self):
new_sim = HeisenbergSimulator(self.n)
new_sim.state = self.state.copy()
new_sim.gate_count = self.gate_count
return new_sim
def h(self, q: int):
self.gate_count += 1
t = self.state.tableau
for i in range(2*self.n):
t[i, 2*self.n] ^= t[i, q] & t[i, self.n+q]
t[i, q], t[i, self.n+q] = t[i, self.n+q], t[i, q]
def cnot(self, c: int, target: int):
self.gate_count += 1
n = self.n; t = self.state.tableau
for i in range(2*n):
t[i, 2*n] ^= t[i,c] & t[i,n+target] & (t[i,target] ^ t[i,n+c] ^ 1)
t[i, target] ^= t[i, c]; t[i, n+c] ^= t[i, n+target]
def get_operator_expectation(self, pauli_string: str) -> float:
n = self.n
x_part, z_part = np.zeros(n, dtype=np.uint8), np.zeros(n, dtype=np.uint8)
phase = 0
for i, p in enumerate(pauli_string):
if p == 'X': x_part[i] = 1
elif p == 'Z': z_part[i] = 1
elif p == 'Y': x_part[i] = 1; z_part[i] = 1; phase += 1
t = self.state.tableau
for i in range(n, 2*n):
if (np.sum(t[i, :n] * z_part + t[i, n:2*n] * x_part) % 2) == 1: return 0.0
test_row = np.concatenate([x_part, z_part, [phase % 2]])
for i in range(n, 2*n):
if np.array_equal(t[i, :2*n], test_row[:2*n]): return 1.0 if t[i, 2*n] == 0 else -1.0
neg_row = test_row.copy(); neg_row[2*n] = 1 - neg_row[2*n]
if np.array_equal(t[i, :2*n], neg_row[:2*n]): return -1.0 if t[i, 2*n] == 0 else 1.0
return 1.0
# ══════════════════════════════════════════════════════════════════════
# SECTION B: THE TRUTH ORACLE (Ground Truth Verification)
# ══════════════════════════════════════════════════════════════════════
FACTORIZATION_TEST_CASES = [(15, 3, 5), (35, 5, 7), (85, 5, 17), (143, 11, 13)]
def extract_factors_from_binding(binding: Dict[str, float], N: int) -> Optional[Tuple[int, int]]:
for pname, qname in [('p', 'q'), ('factor_p', 'factor_q'), ('x', 'y')]:
if pname in binding and qname in binding:
p, q = round(binding[pname]), round(binding[qname])
if p * q == N and p >= 2 and q >= 2: return (min(p, q), max(p, q))
if 's' in binding and 'd' in binding:
s, d = binding['s'], binding['d']
p, q = round((s + d) / 2), round((s - d) / 2)
if p * q == N and p >= 2 and q >= 2: return (min(p, q), max(p, q))
if 't' in binding:
t = round(binding['t'])
if t >= 2 and N % t == 0: return (min(t, N//t), max(t, N//t))
for v, val in binding.items():
if not math.isfinite(val): continue
p = round(val)
if p >= 2 and p * p <= N and N % p == 0: return (p, N // p)
return None
def ground_truth_verify(binding: Dict[str, float], N: int) -> Tuple[bool, str]:
result = extract_factors_from_binding(binding, N)
if result is None: return False, "No valid integer factor pair extractable from binding"
p, q = result
if p * q == N: return True, f"{p} Γ— {q} = {N} βœ“"
return False, f"Round-trip failed: extracted ({p}, {q}), {p}Γ—{q}={p*q} β‰  {N}"
class AdversaryPreFlight:
def __init__(self, solver_callback: Callable, log_callback: Callable):
self.solver_callback = solver_callback
self.log = log_callback
self.test_cases = FACTORIZATION_TEST_CASES
self.rejection_log = []
def check_isomorphism(self, axl_def: Any) -> Tuple[bool, str]:
self.log("ADVERSARY PRE-FLIGHT: testing isomorphism on known toy cases...")
passed_count = 0
for N, true_p, true_q in self.test_cases:
new_axl = copy.deepcopy(axl_def)
if new_axl.observations:
old_N = list(axl_def.observations.values())[0]
for key in list(new_axl.observations.keys()):
if abs(new_axl.observations[key] - old_N) < 1e-6: new_axl.observations[key] = float(N)
for v in new_axl.variables:
if abs(v['lo'] - v['hi']) < 1e-6 and abs(v['lo'] - old_N) < 1e-6: v['lo'] = v['hi'] = float(N)
binding = self.solver_callback(new_axl, N)
if not binding:
self.log(f" N={N}: βœ— FAIL (Exact Integer Solver returned empty binding)")
continue
ok, msg = ground_truth_verify(binding, N)
self.log(f" N={N}: {'βœ“ PASS' if ok else 'βœ— FAIL'} | {msg}")
if ok: passed_count += 1
else: self.rejection_log.append({'N': N, 'reason': msg})
if passed_count == len(self.test_cases): return True, f"Passed all {passed_count} pre-flight cases"
elif passed_count == 0: return False, "REJECTED: failed all pre-flight cases β€” isomorphism invalid"
else: return False, f"REJECTED: passed {passed_count}/{len(self.test_cases)} β€” not reliable enough"
def failure_taxonomy(self, binding: Dict[str, float], N: int, ce: float) -> str:
ok, _ = ground_truth_verify(binding, N)
if ok: return "NONE β€” solved correctly"
if ce > 100: return "TYPE_A: Structural infeasibility β€” constraints contradict, redesign isomorphism"
result = extract_factors_from_binding(binding, N)
if result is None:
if any(abs(v - round(v)) > 0.3 for v in binding.values() if math.isfinite(v)):
return "TYPE_D: Integrality failure β€” optimizer stuck between integers"
return "TYPE_C: Wrong abstraction β€” inverse map broken, can't extract factors"
p, q = result
if p * q != N:
if abs(p * q - N) / N < 0.1: return "TYPE_D: Precision issue β€” close but not exact"
return "TYPE_C: Wrong abstraction β€” extracted integers don't multiply to N"
return "TYPE_B: Optimization landscape β€” increase rays or change initialization"
# ══════════════════════════════════════════════════════════════════════
# SECTION C: SHOR DEMO & PHYSICS BENCHMARKS (No missing import bugs!)
# ══════════════════════════════════════════════════════════════════════
def run_shors_demo(N: int):
print(f"\n=== Shor Demo: N={N} ===")
a = 2
r = 1
while pow(a, r, N) != 1: r += 1
print(f" Period r={r} (a={a} mod N={N})")
sim = HeisenbergSimulator(r)
for i in range(r-1):
sim.h(i)
sim.cnot(i, i+1)
zz = sim.get_operator_expectation('Z' * r)
print(f" ZZ...Z expectation = {zz:.4f}")
print(f" Variables tracked = {r} (vs 2^{r} = {2**r} SchrΓΆdinger amplitudes)")
half = pow(a, r//2, N)
f1 = math.gcd(half - 1, N)
f2 = math.gcd(half + 1, N)
print(f" Factors: gcd(a^(r/2)Β±1, N) = {f1}, {f2}")
print(f" Verify: {f1}Γ—{f2}={f1*f2} {'βœ“' if f1*f2==N else 'βœ—'}")
def benchmark_heisenberg_vs_schrodinger(n_max: int):
print(f"\n=== Heisenberg vs SchrΓΆdinger Scaling ===")
for n in range(2, n_max+1, 2):
heisenberg_vars = 2*n
schrodinger_dim = 2**n
compression = schrodinger_dim // heisenberg_vars
print(f" n={n:3d}: Heisenberg={heisenberg_vars:6d} vars | "
f"SchrΓΆdinger=2^{n} | Compression={compression:,}x")
# ══════════════════════════════════════════════════════════════════════
# SECTION D: SYSTEM PROMPTS & STRUCTURAL TEMPLATES
# ══════════════════════════════════════════════════════════════════════
NOVEL_ISOMORPHISM_DISCOVERY_PROMPT = """\
You are an isomorphism designer. Your task is to invent a continuous optimization encoding for integer factorization of N.
HARD REQUIREMENTS:
1. INVERSE MAP: Write f() and g() explicitly. g() must output exact integers.
2. MANUAL VERIFICATION: Show your objective evaluates to 0 for N=15, 35, 85 at the exact factor values.
3. LANDSCAPE: Explain local minima and why descent won't get trapped.
4. UNIQUENESS: Are the factors the ONLY zeros in [2, sqrt(N)]?
5. PSL TEMPLATE: Write the full ready-to-run block with tight bounds and GEQ guards.
Do NOT propose an isomorphism if you cannot answer these 5 constraints.
"""
ENCODER_PROMPT = """You are the Encoder. CRITICAL RULE: Every problem MUST include an explicit INVERSE MAP in the description.
OUTPUT SCHEMA (JSON only):
{"name": string, "description": string, "variables": [{"name": string, "lo": number, "hi": number, "is_int": boolean}], "constraints": [{"kind": "EQ"|"GEQ"|"LEQ", "expr": string, "weight": number}], "anchors": [], "observations": {"variable_name": number}}
RULES: Use ** for exponents. Variables > 10000 encode in log2 space."""
COLLAPSER_PROMPT = """You are the Grounded Hypothesis Collapser.
HARD RULE: For factorization problems, ALWAYS compute the integers (p, q) and verify p*q=N.
OUTPUT SCHEMA (JSON only):
{"scaled_formulas": {"metric": "expr"}, "hypothesis_markdown": "## Markdown output"}"""
STRUCTURAL_HYPOTHESIS_TEMPLATES = {
"Fermat Algebraic (Exact Bijection)": """\
CONCRETE HYPOTHESIS: Fermat Algebraic Factorization
====================================================
N = p*q is equivalent to 4N = s^2 - d^2
where s = p+q and d = p-q.
Factors: p = (s+d)/2, q = (s-d)/2.
MINIMIZE: d
Variables:
s in [2.0, 172.0]
d in [0.0, 84.0]
sum_sq in [340.0, 340.0]
p in [1.0, 85.0]
q in [1.0, 85.0]
Constraints:
EQ weight=100: sum_sq - (s**2 - d**2)
EQ weight=100: sum_sq - 340.0
EQ weight=10: p - (s + d) / 2.0
EQ weight=10: q - (s - d) / 2.0
GEQ: s - d - 2.0
GEQ: d - 0.0
GEQ: s - 2.0
Anchor: sum_sq - 340.0 = 0 (tolerance 0.001).
Observation: sum_sq = 340.0.
""",
"1D Sine Snap (Fixed Parameterization)": """\
CONCRETE HYPOTHESIS: 1D Sine-Snap Factorization (Fixed)
=========================================================
Key fix: only ONE free variable t. y is derived as N/t.
Eliminates y=0 collapse entirely.
MINIMIZE: snap
Variables:
t in [2.0, 9.0]
snap in [0.0, 2.0]
Constraints:
EQ weight=10: snap - (sin(t * 3.14159265)**2 + sin(85.0 / t * 3.14159265)**2)
GEQ: t - 2.0
LEQ: t - 9.0
Anchor: snap = 0 (tolerance 0.01).
Observation: snap = 0.0.
""",
"Shor Period-Finding: Heisenberg vs Schrodinger Resource Proof": """\
CONCRETE HYPOTHESIS: Shor Period-Finding Resource Comparison
============================================================
Prove Heisenberg picture uses O(n^2) bits vs Schrodinger 2^n complex numbers.
Variables:
n_qubits in [4.0, 50.0]
log2_heisenberg_bits in [0.0, 14.0]
log2_schrodinger_bits in [4.0, 54.0]
log2_compression in [0.0, 50.0]
clifford_gate_count in [6.0, 1300.0]
n_operators_tracked in [8.0, 100.0]
Constraints:
EQ weight=10: log2_heisenberg_bits - log(2*n_qubits*(2*n_qubits+1))/log(2)
EQ weight=10: log2_schrodinger_bits - n_qubits - log(16)/log(2)
EQ weight=10: log2_compression - log2_schrodinger_bits + log2_heisenberg_bits
EQ weight=10: n_operators_tracked - 2*n_qubits
EQ weight=10: clifford_gate_count - n_qubits*(n_qubits+1)/2
GEQ: log2_compression - 1.0
GEQ: n_qubits - 4.0
Anchor: log2_compression >= 1.0 (mode=geq, tolerance 0.5).
Observation: n_qubits = 20.
"""
}