File size: 3,913 Bytes
bc6498b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/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()