Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
NVIDIA
GitHub Repository: NVIDIA/cuda-q-academic
Path: blob/main/quick-start-to-quantum/interactive_widget/CNOT_visualization.py
1120 views
1
# Generates an interactive visualization of the CNOT gate
2
def create_CNOT_widget():
3
# Clear any existing widgets
4
import IPython.display
5
IPython.display.clear_output()
6
7
import cudaq
8
import numpy as np
9
import matplotlib.pyplot as plt
10
from IPython.display import display, HTML, clear_output
11
import ipywidgets as widgets
12
from ipywidgets import interactive_output, HBox, VBox
13
14
@cudaq.kernel
15
def initialize(qubits: cudaq.qview, state: list[int]):
16
"""Kernel to initialize the state indicated by the given list
17
0: |0>, 1: |1>, 2: |+>, 3: |->"""
18
for idx in range(len(state)):
19
if state[idx] == 1:
20
x(qubits[idx])
21
elif state[idx] == 2: # |+>
22
h(qubits[idx])
23
elif state[idx] == 3: # |->
24
x(qubits[idx])
25
h(qubits[idx])
26
27
@cudaq.kernel
28
def CNOT_example(state: list[int]):
29
"""Apply CNOT to the state given by the state numbers"""
30
qubits = cudaq.qvector(2)
31
# Initialize state
32
initialize(qubits, state)
33
# Apply CNOT
34
x.ctrl(qubits[0], qubits[1])
35
36
# Function to format complex number nicely
37
def format_complex(c):
38
if abs(c.imag) < 1e-10: # Real number
39
return f"{c.real:.3f}"
40
elif abs(c.real) < 1e-10: # Imaginary number
41
if abs(c.imag - 1) < 1e-10:
42
return "i"
43
elif abs(c.imag + 1) < 1e-10:
44
return "-i"
45
else:
46
return f"{c.imag:.3f}i"
47
else:
48
sign = "+" if c.imag >= 0 else "-"
49
return f"{c.real:.3f}{sign}{abs(c.imag):.3f}i"
50
51
# Function to update the circuit diagram
52
def update_circuit(q0_state, q1_state):
53
with output_circuit:
54
clear_output(wait=True)
55
print("Circuit:")
56
state_list = [q0_state, q1_state]
57
print(cudaq.draw(CNOT_example, state_list))
58
59
# Function to update the probability distribution
60
def update_prob_chart(q0_state, q1_state):
61
with output_prob:
62
clear_output(wait=True)
63
64
# Get the state after circuit execution
65
state_list = [q0_state, q1_state]
66
state = cudaq.get_state(CNOT_example, state_list)
67
68
# Calculate probabilities using Born's rule
69
probs = np.abs(state)**2
70
71
plt.figure(figsize=(6,4))
72
plt.bar(['|00⟩', '|01⟩', '|10⟩', '|11⟩'], probs, color='#76b900') # NVIDIA green
73
plt.ylim(0, 1)
74
plt.ylabel('Probability')
75
plt.title('Measurement Probability Distribution')
76
plt.show()
77
78
# Function to update the final state display
79
def update_final_state(q0_state, q1_state):
80
with output_state:
81
clear_output(wait=True)
82
state_list = [q0_state, q1_state]
83
state = cudaq.get_state(CNOT_example, state_list)
84
85
print("Final State:")
86
state_str = ""
87
basis_states = ['|00⟩', '|01⟩', '|10⟩', '|11⟩']
88
89
# Find first non-zero term
90
first_term = True
91
for i, (amplitude, basis) in enumerate(zip(state, basis_states)):
92
if abs(amplitude) > 1e-10: # Only show non-zero terms
93
if first_term:
94
state_str += f"({format_complex(amplitude)}){basis}"
95
first_term = False
96
else:
97
# Add explicit + or - sign
98
if amplitude.real < 0:
99
state_str += f"<span style='color: red'>-</span>({format_complex(abs(amplitude))}){basis}"
100
else:
101
state_str += f"+({format_complex(abs(amplitude))}){basis}"
102
103
display(HTML(state_str))
104
105
# Add titles
106
main_title = widgets.HTML(value="<h3>Two-Qubit CNOT Gate Visualization</h3>")
107
initial_state_title = widgets.HTML(value="<h4>Initial States:</h4>")
108
109
# Create dropdowns for each qubit
110
q0_dropdown = widgets.Dropdown(
111
options=[('|0⟩', 0), ('|1⟩', 1), ('|+⟩', 2), ('|-⟩', 3)],
112
value=0,
113
description='Qubit 0:',
114
)
115
116
q1_dropdown = widgets.Dropdown(
117
options=[('|0⟩', 0), ('|1⟩', 1), ('|+⟩', 2), ('|-⟩', 3)],
118
value=0,
119
description='Qubit 1:',
120
)
121
122
# Create output widgets
123
output_circuit = widgets.Output()
124
output_prob = widgets.Output()
125
output_state = widgets.Output()
126
127
def update_all(change):
128
update_circuit(q0_dropdown.value, q1_dropdown.value)
129
update_prob_chart(q0_dropdown.value, q1_dropdown.value)
130
update_final_state(q0_dropdown.value, q1_dropdown.value)
131
132
# Observe changes in dropdowns
133
q0_dropdown.observe(update_all, names='value')
134
q1_dropdown.observe(update_all, names='value')
135
136
# Display everything
137
display(VBox([
138
main_title,
139
initial_state_title,
140
HBox([q0_dropdown, q1_dropdown]),
141
output_circuit,
142
output_state,
143
output_prob
144
]))
145
146
# Initial update
147
update_circuit(q0_dropdown.value, q1_dropdown.value)
148
update_prob_chart(q0_dropdown.value, q1_dropdown.value)
149
update_final_state(q0_dropdown.value, q1_dropdown.value)
150
151
# When imported, this will create and display a new widget
152
if __name__ == '__main__':
153
widget = create_CNOT_widget()
154
display(widget)
155
156