jmurray10's picture
Phase 4: Quantum-ML compression models and benchmarks
bc6498b verified
#!/usr/bin/env python3
"""Fixed Guppy Grover emulator for n=2 and n=3"""
from guppylang import guppy
from guppylang.std.builtins import result
from guppylang.std.quantum import qubit, h, x, cx, cz, measure
import math
import argparse
import csv
import json
@guppy
def grover_n2_marked_11() -> None:
"""Grover for n=2, marking |11⟩"""
# Initialize qubits
q0 = qubit()
q1 = qubit()
# Initial superposition
h(q0)
h(q1)
# Grover iteration (optimal is 1 iteration for n=2)
# Oracle for |11⟩
cz(q0, q1)
# Diffusion operator
h(q0)
h(q1)
x(q0)
x(q1)
h(q1)
cx(q0, q1)
h(q1)
x(q0)
x(q1)
h(q0)
h(q1)
# Measure
r0 = measure(q0)
r1 = measure(q1)
result("b0", r0)
result("b1", r1)
@guppy
def grover_n2_marked_10() -> None:
"""Grover for n=2, marking |10⟩"""
q0 = qubit()
q1 = qubit()
# Initial superposition
h(q0)
h(q1)
# Oracle for |10⟩
x(q1) # Flip phase for |10⟩
cz(q0, q1)
x(q1)
# Diffusion
h(q0)
h(q1)
x(q0)
x(q1)
h(q1)
cx(q0, q1)
h(q1)
x(q0)
x(q1)
h(q0)
h(q1)
# Measure
r0 = measure(q0)
r1 = measure(q1)
result("b0", r0)
result("b1", r1)
def run_grover_n2(pattern, shots=1000):
"""Run Grover for n=2 qubits"""
if pattern == 3: # |11⟩
sim = grover_n2_marked_11.emulator(n_qubits=2)
sim = sim.with_shots(shots)
results = sim.run()
elif pattern == 2: # |10⟩
sim = grover_n2_marked_10.emulator(n_qubits=2)
sim = sim.with_shots(shots)
results = sim.run()
else:
raise ValueError(f"Pattern {pattern} not implemented")
# Count successes
success_count = 0
pattern_bits = format(pattern, '02b')
for shot in results.results:
bits = ""
for entry in shot.entries:
if entry[0] == 'b0':
bits = str(entry[1]) + bits[1:] if len(bits) > 0 else str(entry[1])
elif entry[0] == 'b1':
bits = bits[0] + str(entry[1]) if len(bits) > 0 else "0" + str(entry[1])
if bits == pattern_bits:
success_count += 1
return success_count / shots
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--n", type=int, default=2, choices=[2])
ap.add_argument("--pattern", type=int, default=3)
ap.add_argument("--shots", type=int, default=1000)
ap.add_argument("--csv", type=str, default="guppy_results.csv")
args = ap.parse_args()
# Run for different k values (for n=2, optimal k=1)
print(f"\n{'='*60}")
print(f"GUPPY/SELENE GROVER EMULATOR - n={args.n}, pattern={args.pattern:02b}")
print(f"{'='*60}\n")
# For n=2, we run the circuit (which has k=1 built in)
p_success = run_grover_n2(args.pattern, args.shots)
k_opt = 1 # Optimal for n=2
results = {
"n": args.n,
"pattern": format(args.pattern, '02b'),
"k": k_opt,
"shots": args.shots,
"p_success": round(p_success, 3),
"backend": "guppy/selene"
}
print(f"Results: {json.dumps(results, indent=2)}")
# Save to CSV
with open(args.csv, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["n", "m", "marked", "k", "backend", "shots", "p_success", "wall_s", "k_opt"])
writer.writerow([args.n, 1, format(args.pattern, '02b'), k_opt, "guppy", args.shots, p_success, None, k_opt])
print(f"\n✅ Results saved to {args.csv}")
# Theoretical comparison
theoretical = 1.0 # For n=2, k=1 gives 100% success
print(f"\nTheoretical p_success: {theoretical:.3f}")
print(f"Achieved p_success: {p_success:.3f}")
print(f"Difference: {abs(theoretical - p_success):.3f}")
if __name__ == "__main__":
main()