Watching qubits on the Bloch sphere#
This notebook uses quantum_mind.viz to follow every qubit of a Qiskit circuit gate by gate, in 3D:
a trajectory through a circuit, as an interactive animation (rotate, zoom, play, slider);
live updates of the spheres from inside a loop (
LiveBloch);Bloch vectors measured on a simulator with the noise model of an IBM device (tomography).
Requires pip install "quantum-mind[all] @ git+https://github.com/yeshwanthguru/Quantum-mind".
# Use the installed package, or the source tree when running from a clone
try:
import quantum_mind
except ImportError:
import sys, pathlib; sys.path.insert(0, str(pathlib.Path.cwd().parent / 'src')); import quantum_mind
print('quantum_mind', quantum_mind.__version__)
quantum_mind 3.1.0
1. A circuit, gate by gate#
Each gate is applied in small fractional steps, so rotations appear as arcs. While the two qubits are entangled, each one’s reduced state is mixed and its vector moves inside the sphere.
import numpy as np
from qiskit import QuantumCircuit
from quantum_mind.viz import circuit_trajectory, animate_bloch
qc = QuantumCircuit(2)
qc.h(0); qc.ry(np.pi / 3, 1); qc.cx(0, 1); qc.rz(np.pi / 2, 0); qc.cx(0, 1); qc.h(0)
traj = circuit_trajectory(qc, steps=12)
traj.names = ['qubit 0', 'qubit 1']
print(traj.frames, 'frames; vector lengths after each gate:')
for k in range(0, traj.frames, 12):
print(' %-6s %s' % (traj.labels[k], traj.purity()[k].round(3)))
73 frames; vector lengths after each gate:
start [1. 1.]
h [1. 1.]
ry [1. 1.]
cx [0.866 0.866]
rz [0.866 0.866]
cx [1. 1.]
h [1. 1.]
fig = animate_bloch(traj, title='Entangling and disentangling two qubits')
fig # press play, or drag the slider
2. Live updates#
LiveBloch redraws the spheres in place. In Jupyter it is an interactive widget; in a script it opens
a Matplotlib window. Call update(state) from any simulation loop, or play(trajectory).
from quantum_mind.viz import LiveBloch, rotation_trajectory
live = LiveBloch(2, names=['qubit 0', 'qubit 1'])
live.show()
live.play(traj, fps=30)
Live widget: it updates in place when the notebook runs in Jupyter.
<quantum_mind.viz.interactive.LiveBloch at 0x7fd532c55100>
# Or drive it from your own loop: here a single qubit precessing about the x axis
spin = LiveBloch(1, names=['spin']).show()
for frame in rotation_trajectory([1, 0, 0], 2 * np.pi, steps=60).vectors:
spin.update(frame)
Live widget: it updates in place when the notebook runs in Jupyter.
3. Measured Bloch vectors#
bloch_tomography measures every qubit in the X, Y and Z bases on any backend accepted by
quantum_mind.circuits.run and reconstructs the Bloch vectors. Compare the ideal simulator with the noise model
of IBM’s Torino device; with an IBM Quantum account the same call runs on hardware
(backend='ibm:least_busy').
from qiskit.quantum_info import Statevector
from quantum_mind.viz import bloch_vectors, bloch_tomography, bloch_figure
ideal = bloch_vectors(Statevector(qc))
noisy = bloch_tomography(qc, 'aer:FakeTorino', shots=8000)
print('ideal ', ideal.round(3).tolist())
print('noisy ', noisy.round(3).tolist())
bloch_figure(noisy, names=['qubit 0 (FakeTorino)', 'qubit 1 (FakeTorino)'])
ideal [[0.0, -1.0, 0.0], [0.866, -0.0, 0.5]]
noisy [[0.004, -0.987, 0.002], [0.854, 0.001, 0.494]]