-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcircuit_cutting_example.py
142 lines (116 loc) · 5.22 KB
/
circuit_cutting_example.py
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
from qiskit import QuantumCircuit, execute, Aer
from circuit_cutter import QuantumCircuitCutter
import numpy as np
from typing import List, Dict
import matplotlib.pyplot as plt
def create_large_circuit(num_qubits: int = 8, depth: int = 100) -> QuantumCircuit:
"""Create a large quantum circuit for demonstration"""
circuit = QuantumCircuit(num_qubits)
# Add a mix of single and multi-qubit gates
for _ in range(depth):
# Random single-qubit gates
for qubit in range(num_qubits):
if np.random.random() < 0.3:
gate_choice = np.random.choice(['h', 'x', 'ry'])
if gate_choice == 'ry':
circuit.ry(np.random.random() * np.pi, qubit)
else:
getattr(circuit, gate_choice)(qubit)
# Random two-qubit gates
for _ in range(num_qubits // 2):
if np.random.random() < 0.3:
q1, q2 = np.random.choice(num_qubits, size=2, replace=False)
gate_choice = np.random.choice(['cx', 'cz'])
getattr(circuit, gate_choice)(q1, q2)
return circuit
def execute_subcircuits(subcircuits: List[QuantumCircuit],
shots: int = 1000) -> List[Dict]:
"""Execute subcircuits and return their results"""
backend = Aer.get_backend('qasm_simulator')
results = []
for subcircuit in subcircuits:
# Add measurements to output qubits
meas_circuit = subcircuit.circuit.copy()
meas_circuit.measure_all()
# Execute circuit
job = execute(meas_circuit, backend, shots=shots)
counts = job.result().get_counts()
results.append(counts)
return results
def analyze_cutting_performance(original_circuit: QuantumCircuit,
subcircuits: List[QuantumCircuit]):
"""Analyze and visualize circuit cutting performance"""
# Calculate size metrics
original_size = {
'width': original_circuit.num_qubits,
'depth': original_circuit.depth(),
'gates': len(original_circuit.data)
}
subcircuit_sizes = [{
'width': sc.circuit.num_qubits,
'depth': sc.circuit.depth(),
'gates': len(sc.circuit.data)
} for sc in subcircuits]
# Plot size comparison
metrics = ['width', 'depth', 'gates']
fig, axes = plt.subplots(1, len(metrics), figsize=(15, 5))
for i, metric in enumerate(metrics):
ax = axes[i]
# Original circuit
ax.bar(0, original_size[metric], label='Original', alpha=0.7)
# Subcircuits
subcircuit_values = [size[metric] for size in subcircuit_sizes]
ax.bar(range(1, len(subcircuit_values) + 1),
subcircuit_values,
label='Subcircuits',
alpha=0.7)
ax.set_title(f'Circuit {metric.capitalize()}')
ax.set_xticks(range(len(subcircuit_values) + 1))
ax.set_xticklabels(['Original'] + [f'Sub {i+1}' for i in range(len(subcircuit_values))])
plt.tight_layout()
plt.savefig('cutting_performance.png')
plt.close()
def demonstrate_circuit_cutting():
print("\nDemonstrating Quantum Circuit Cutting:")
# Create a large quantum circuit
print("1. Creating large quantum circuit...")
circuit = create_large_circuit(num_qubits=8, depth=100)
print(f"Original circuit size: {len(circuit.data)} gates, "
f"depth: {circuit.depth()}, "
f"qubits: {circuit.num_qubits}")
# Initialize circuit cutter
cutter = QuantumCircuitCutter(max_subcircuit_width=5, max_subcircuit_depth=50)
# Cut the circuit
print("\n2. Cutting circuit into smaller subcircuits...")
subcircuits = cutter.cut_circuit(circuit)
print(f"Generated {len(subcircuits)} subcircuits")
# Print subcircuit information
for i, sc in enumerate(subcircuits):
print(f"\nSubcircuit {i+1}:")
print(f"- Number of qubits: {sc.circuit.num_qubits}")
print(f"- Circuit depth: {sc.circuit.depth()}")
print(f"- Number of gates: {len(sc.circuit.data)}")
print(f"- Input qubits: {sc.input_qubits}")
print(f"- Output qubits: {sc.output_qubits}")
# Visualize the cuts
print("\n3. Generating circuit cutting visualization...")
cutter.visualize_cuts(circuit)
print("Circuit cuts visualization saved as 'circuit_cuts.png'")
# Execute subcircuits
print("\n4. Executing subcircuits...")
subcircuit_results = execute_subcircuits(subcircuits)
# Reconstruct results
print("\n5. Reconstructing full circuit results...")
full_results = cutter.reconstruct_results(subcircuit_results)
print("Top 5 most probable states:")
for state, prob in sorted(full_results.items(),
key=lambda x: x[1],
reverse=True)[:5]:
print(f"State {state}: probability {prob:.4f}")
# Analyze cutting performance
print("\n6. Analyzing cutting performance...")
analyze_cutting_performance(circuit, subcircuits)
print("Cutting performance analysis saved as 'cutting_performance.png'")
if __name__ == "__main__":
demonstrate_circuit_cutting()
print("\nCircuit cutting demonstration completed.")