Skip to content

Commit 8aae4f0

Browse files
committed
Add more examples
1 parent 04885a5 commit 8aae4f0

File tree

10 files changed

+6623
-25
lines changed

10 files changed

+6623
-25
lines changed

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,7 @@ cache/
365365
.cached/
366366
*.cache
367367

368-
# Lock files
369-
*.lock
368+
# Lock files (excluding uv.lock which should be tracked)
370369

371370
# ==============================================
372371
# Development and Testing

examples/first_program.py

Lines changed: 349 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,349 @@
1+
import superquantx as sqx
2+
import numpy as np
3+
import matplotlib.pyplot as plt
4+
5+
# Verify your installation
6+
print(f"SuperQuantX version: {sqx.__version__}")
7+
print(f"Available backends: {sqx.list_available_backends()}")
8+
9+
# Get a quantum backend
10+
backend = sqx.get_backend('simulator')
11+
12+
# Create a circuit with one qubit
13+
circuit = backend.create_circuit(n_qubits=1)
14+
15+
# Initially, the qubit is in state |0⟩
16+
print("Initial state: |0⟩")
17+
18+
# Apply a Hadamard gate to create superposition
19+
circuit = backend.add_gate(circuit, 'H', 0) # Now the qubit is in state (|0⟩ + |1⟩)/√2
20+
21+
# Measure the qubit
22+
circuit = backend.add_measurement(circuit)
23+
24+
# Run the circuit multiple times
25+
result = backend.execute_circuit(circuit, shots=1000)
26+
counts = result['counts']
27+
28+
print(f"Measurement results: {counts}")
29+
print("🎉 You've created quantum superposition!")
30+
31+
# Create a circuit with 2 qubits
32+
circuit = backend.create_circuit(n_qubits=2)
33+
34+
# Step 1: Put first qubit in superposition
35+
circuit = backend.add_gate(circuit, 'H', 0)
36+
37+
# Step 2: Entangle the qubits with CNOT gate
38+
circuit = backend.add_gate(circuit, 'CNOT', [0, 1]) # Controlled-X gate (CNOT)
39+
40+
# Step 3: Measure both qubits
41+
circuit = backend.add_measurement(circuit)
42+
43+
# Run the circuit
44+
result = backend.execute_circuit(circuit, shots=1000)
45+
counts = result['counts']
46+
47+
print(f"Bell state results: {counts}")
48+
49+
# Circuit information (visualization to be implemented)
50+
print(f"\nCircuit created successfully!")
51+
print(f"Circuit has {circuit.n_qubits} qubits")
52+
print(f"Current state vector shape: {circuit.state.shape}")
53+
54+
55+
# Let's verify the entanglement property
56+
print("\n🔍 Analyzing entanglement:")
57+
total_shots = sum(counts.values())
58+
59+
prob_00 = counts.get('00', 0) / total_shots
60+
prob_11 = counts.get('11', 0) / total_shots
61+
prob_01 = counts.get('01', 0) / total_shots
62+
prob_10 = counts.get('10', 0) / total_shots
63+
64+
print(f"P(00) = {prob_00:.3f}")
65+
print(f"P(11) = {prob_11:.3f}")
66+
print(f"P(01) = {prob_01:.3f}")
67+
print(f"P(10) = {prob_10:.3f}")
68+
69+
if prob_01 + prob_10 < 0.1: # Less than 10% due to statistical noise
70+
print("✅ Qubits are entangled!")
71+
else:
72+
print("❌ Something went wrong...")
73+
74+
75+
def quantum_random_number(num_bits=8):
76+
"""Generate a random number using quantum superposition."""
77+
78+
# Create circuit with specified number of qubits
79+
circuit = backend.create_circuit(n_qubits=num_bits)
80+
81+
# Put all qubits in superposition
82+
for i in range(num_bits):
83+
circuit = backend.add_gate(circuit, 'H', i)
84+
85+
# Measure all qubits
86+
circuit = backend.add_measurement(circuit)
87+
88+
# Run the circuit once
89+
result = backend.execute_circuit(circuit, shots=1)
90+
91+
# Convert result to integer
92+
binary_result = list(result['counts'].keys())[0]
93+
random_number = int(binary_result, 2)
94+
95+
return random_number, binary_result
96+
97+
# Generate some quantum random numbers
98+
print("🎲 Quantum Random Numbers:")
99+
for i in range(5):
100+
number, binary = quantum_random_number(8) # 8-bit numbers (0-255)
101+
print(f" {number:3d} (binary: {binary})")
102+
103+
104+
105+
def quantum_interference_demo():
106+
"""Demonstrate quantum interference patterns."""
107+
108+
circuit = backend.create_circuit(n_qubits=1)
109+
110+
# Create superposition
111+
circuit = backend.add_gate(circuit, 'H', 0)
112+
113+
# Add a phase (rotation around Z-axis)
114+
circuit = backend.add_gate(circuit, 'RZ', 0, [np.pi/4]) # 45-degree phase
115+
116+
# Apply another Hadamard - this creates interference
117+
circuit = backend.add_gate(circuit, 'H', 0)
118+
119+
circuit = backend.add_measurement(circuit)
120+
121+
# Run multiple times to see the pattern
122+
result = backend.execute_circuit(circuit, shots=1000)
123+
counts = result['counts']
124+
125+
return counts
126+
127+
# Test different phases
128+
phases = [0, np.pi/4, np.pi/2, 3*np.pi/4, np.pi]
129+
results = []
130+
131+
print("🌊 Quantum Interference Patterns:")
132+
print("Phase\t|0⟩ Count\t|1⟩ Count")
133+
print("-" * 35)
134+
135+
for phase in phases:
136+
circuit = backend.create_circuit(n_qubits=1)
137+
circuit = backend.add_gate(circuit, 'H', 0)
138+
circuit = backend.add_gate(circuit, 'RZ', 0, [phase])
139+
circuit = backend.add_gate(circuit, 'H', 0)
140+
circuit = backend.add_measurement(circuit)
141+
142+
result = backend.execute_circuit(circuit, shots=1000)
143+
counts = result['counts']
144+
145+
count_0 = counts.get('0', 0)
146+
count_1 = counts.get('1', 0)
147+
148+
print(f"{phase:.2f}\t{count_0}\t\t{count_1}")
149+
results.append((phase, count_0, count_1))
150+
151+
152+
class QuantumCoin:
153+
"""A quantum coin flipper with controllable bias."""
154+
155+
def __init__(self, backend_name='simulator'):
156+
self.backend = sqx.get_backend(backend_name)
157+
158+
def flip(self, bias=0.5, shots=1000):
159+
"""
160+
Flip the quantum coin.
161+
162+
Args:
163+
bias (float): Probability of getting 'heads' (0.0 to 1.0)
164+
shots (int): Number of measurements
165+
166+
Returns:
167+
dict: Results with counts for heads and tails
168+
"""
169+
# Calculate rotation angle for desired bias
170+
theta = 2 * np.arcsin(np.sqrt(bias))
171+
172+
circuit = self.backend.create_circuit(n_qubits=1)
173+
174+
# Start in |0⟩ (tails)
175+
# Rotate to achieve desired bias
176+
circuit = self.backend.add_gate(circuit, 'RY', 0, [theta])
177+
178+
circuit = self.backend.add_measurement(circuit)
179+
180+
result = self.backend.execute_circuit(circuit, shots=shots)
181+
counts = result['counts']
182+
183+
# Map 0->tails, 1->heads
184+
heads = counts.get('1', 0)
185+
tails = counts.get('0', 0)
186+
187+
return {
188+
'heads': heads,
189+
'tails': tails,
190+
'bias': heads / (heads + tails) if (heads + tails) > 0 else 0
191+
}
192+
193+
# Test the quantum coin
194+
coin = QuantumCoin()
195+
196+
print("🪙 Quantum Coin Flipper Test:")
197+
biases = [0.1, 0.3, 0.5, 0.7, 0.9]
198+
199+
for target_bias in biases:
200+
result = coin.flip(bias=target_bias, shots=1000)
201+
print(f"Target: {target_bias:.1f}, Actual: {result['bias']:.3f}, "
202+
f"Heads: {result['heads']}, Tails: {result['tails']}")
203+
204+
205+
def plot_quantum_results(counts, title="Quantum Measurement Results"):
206+
"""Plot quantum measurement results."""
207+
208+
states = list(counts.keys())
209+
values = list(counts.values())
210+
211+
plt.figure(figsize=(10, 6))
212+
bars = plt.bar(states, values, alpha=0.7)
213+
214+
# Color bars differently for different states
215+
colors = ['skyblue', 'lightcoral', 'lightgreen', 'gold']
216+
for i, bar in enumerate(bars):
217+
bar.set_color(colors[i % len(colors)])
218+
219+
plt.title(title, fontsize=16, fontweight='bold')
220+
plt.xlabel('Quantum State', fontsize=12)
221+
plt.ylabel('Count', fontsize=12)
222+
plt.grid(axis='y', alpha=0.3)
223+
224+
# Add value labels on bars
225+
for bar in bars:
226+
height = bar.get_height()
227+
plt.text(bar.get_x() + bar.get_width()/2., height,
228+
f'{int(height)}',
229+
ha='center', va='bottom')
230+
231+
plt.tight_layout()
232+
# Save instead of showing to avoid timeout in automated tests
233+
plt.savefig('/tmp/quantum_results.png', dpi=150, bbox_inches='tight')
234+
plt.close() # Close to free memory
235+
print(f"✅ Plot saved successfully with data: {dict(zip(states, values))}")
236+
237+
# Example: Visualize Bell state results
238+
circuit = backend.create_circuit(n_qubits=2)
239+
circuit = backend.add_gate(circuit, 'H', 0)
240+
circuit = backend.add_gate(circuit, 'CNOT', [0, 1])
241+
circuit = backend.add_measurement(circuit)
242+
243+
result = backend.execute_circuit(circuit, shots=1000)
244+
counts = result['counts']
245+
246+
plot_quantum_results(counts, "Bell State |Φ⁺⟩ = (|00⟩ + |11⟩)/√2")
247+
248+
249+
def compare_backends(algorithm_func, *args, **kwargs):
250+
"""Run the same algorithm on different backends."""
251+
252+
available_backends = sqx.list_available_backends()
253+
results = {}
254+
255+
# Only test backends that are actually available and support gate-model circuits
256+
for backend_name in available_backends:
257+
# Skip quantum annealing backends (they use a different programming model)
258+
if backend_name in {'ocean', 'dwave'}:
259+
print(f"⏭️ Skipping {backend_name}: Quantum annealing backend (not compatible with gate circuits)")
260+
continue
261+
262+
if available_backends[backend_name].get('available', False):
263+
try:
264+
print(f"🔄 Testing {backend_name}...")
265+
result = algorithm_func(backend_name, *args, **kwargs)
266+
results[backend_name] = result
267+
print(f"✅ {backend_name} completed successfully")
268+
269+
except Exception as e:
270+
print(f"❌ {backend_name} failed: {e}")
271+
results[backend_name] = None
272+
else:
273+
reason = available_backends[backend_name].get('reason', 'Not available')
274+
print(f"⏭️ Skipping {backend_name}: {reason}")
275+
276+
return results
277+
278+
def bell_state_test(backend_name):
279+
"""Create Bell state on specified backend."""
280+
backend = sqx.get_backend(backend_name)
281+
circuit = backend.create_circuit(n_qubits=2)
282+
283+
circuit = backend.add_gate(circuit, 'H', 0)
284+
circuit = backend.add_gate(circuit, 'CNOT', [0, 1])
285+
circuit = backend.add_measurement(circuit)
286+
287+
result = backend.execute_circuit(circuit, shots=1000)
288+
return result['counts']
289+
290+
# Compare Bell state across backends
291+
print("🔍 Cross-Backend Comparison:")
292+
backend_results = compare_backends(bell_state_test)
293+
294+
print("\n📊 Results Summary:")
295+
for backend_name, counts in backend_results.items():
296+
if counts:
297+
prob_entangled = (counts.get('00', 0) + counts.get('11', 0)) / 1000
298+
print(f"{backend_name}: Entanglement fidelity = {prob_entangled:.3f}")
299+
print(f" Results: {counts}")
300+
301+
print("\n💡 Note: This example uses gate-model quantum computing.")
302+
print(" Ocean/D-Wave backends are quantum annealers for optimization problems")
303+
print(" and use a completely different programming model (QUBO/Ising).")
304+
305+
306+
307+
def phase_kickback_demo():
308+
"""Demonstrate quantum phase kickback."""
309+
310+
print("🔄 Quantum Phase Kickback Demonstration")
311+
print("This shows how a controlled operation can affect the control qubit")
312+
313+
circuit = backend.create_circuit(n_qubits=2)
314+
315+
# Put control qubit in superposition
316+
circuit = backend.add_gate(circuit, 'H', 0)
317+
318+
# Put target qubit in |1⟩ state (important for kickback!)
319+
circuit = backend.add_gate(circuit, 'X', 1)
320+
321+
# Apply controlled-Z gate
322+
circuit = backend.add_gate(circuit, 'CZ', [0, 1])
323+
324+
# Measure in X-basis to see phase difference
325+
circuit = backend.add_gate(circuit, 'H', 0) # H†|±⟩ = |0⟩/|1⟩
326+
circuit = backend.add_measurement(circuit)
327+
328+
result = backend.execute_circuit(circuit, shots=1000)
329+
counts = result['counts']
330+
331+
print(f"Results: {counts}")
332+
333+
# Compare with reference (no kickback)
334+
circuit_ref = backend.create_circuit(n_qubits=2)
335+
circuit_ref = backend.add_gate(circuit_ref, 'H', 0)
336+
circuit_ref = backend.add_gate(circuit_ref, 'X', 1)
337+
# Skip the CZ gate
338+
circuit_ref = backend.add_gate(circuit_ref, 'H', 0)
339+
circuit_ref = backend.add_measurement(circuit_ref)
340+
341+
result_ref = backend.execute_circuit(circuit_ref, shots=1000)
342+
counts_ref = result_ref['counts']
343+
344+
print(f"Reference (no CZ): {counts_ref}")
345+
print("The difference shows the phase kickback effect!")
346+
347+
return counts, counts_ref
348+
349+
phase_kickback_demo()

0 commit comments

Comments
 (0)