Exploring Single-Qubit and Multi-Qubit States with Qiskit

This post documents an interactive laboratory session focused on manipulating and visualizing single and multi-qubit quantum states using the Qiskit framework. The exercises cover fundamental concepts, including state initialization, quantum gates, superposition, entanglement, measurement, and the quantum teleportation algorithm.

Single-Qubit State Manipulation

Single-qubit states, represented generally as \sqrt{1-p}|0 \rangle + e^{i\phi}\sqrt{p}|1 \rangle, where p denotes the probability of measuring the |1 \rangle state and \phi represents the relative phase.

A fundamental operation involves creating a quantum circuit. A single-qubit circuit without any gates was initialized as follows:

from qiskit import QuantumCircuit

mycircuit = QuantumCircuit(1)
mycircuit.draw('mpl')

This created a circuit with one qubit. To examine the state of this qubit, the |0 \rangle state was initialized using Qiskit’s Statevector class:

from qiskit.quantum_info import Statevector

sv = Statevector.from_label('0')
print(f"Statevector object: {sv}")
print(f"Statevector data: {sv.data}")

The output confirmed the statevector representation of |0 \rangle as:

\[|0 \rangle=\begin{bmatrix}1\\ 0\ \end{bmatrix}\]

Applying the empty circuit to this state resulted in no change, which was verified by evolving the statevector and calculating the state fidelity:

new_sv = sv.evolve(mycircuit)
print(f"Evolved statevector: {new_sv}")

from qiskit.quantum_info import state_fidelity
fidelity = state_fidelity(sv, new_sv)
print(f"State fidelity: {fidelity}")

A fidelity of 1 indicated that the initial and evolved states were identical. The qsphere visualization provided a geometric representation of the quantum state:

from qiskit.visualization import plot_state_qsphere

plot_state_qsphere(sv.data)

The application of the X gate, flips the qubit state from |0 \rangle to |1 \rangle:

mycircuit = QuantumCircuit(1)
mycircuit.x(0)
mycircuit.draw('mpl')

sv = Statevector.from_label('0')
new_sv = sv.evolve(mycircuit)
print(f"Evolved statevector after X gate: {new_sv}")
print(f"State fidelity with initial state: {state_fidelity(new_sv, sv)}")
plot_state_qsphere(new_sv.data)

The resulting statevector:

\[|1 \rangle=\begin{bmatrix}0\\ 1\ \end{bmatrix}\]

and the qsphere visualization confirmed the X gate’s action, indicating orthogonality.

The Hadamard (H) gate, which creates superposition states. Applying it to |0 \rangle produced the state :

\[\frac{1}{\sqrt{2}}(|0 \rangle + |1 \rangle) \]
sv = Statevector.from_label('0')
mycircuit = QuantumCircuit(1)
mycircuit.h(0)
mycircuit.draw('mpl')

new_sv = sv.evolve(mycircuit)
print(f"Evolved statevector after H gate on |0>: {new_sv}")
plot_state_qsphere(new_sv.data)

Applying the Hadamard gate to |1 \rangle resulted in the superposition state:

\[\frac{1}{\sqrt{2}}(|0 \rangle – |1 \rangle) \]
sv = Statevector.from_label('1')
mycircuit = QuantumCircuit(1)
mycircuit.h(0)

new_sv = sv.evolve(mycircuit)
print(f"Evolved statevector after H gate on |1>: {new_sv}")
plot_state_qsphere(new_sv.data)

The qsphere visualization clearly showed the phase difference through color coding. The T and S gates, which apply phase shifts of +\frac{\pi}{4} anfd +\frac{\pi}{2}, respectively, and provided an interactive widget for exploring the effects of various single-qubit gates.

Multi-Qubit State Exploration

The focus then shifted to multi-qubit states, particularly the generation of Bell states. The Bell state \frac{1}{\sqrt{2}}​(|00 \rangle+|11\rangle) was created by applying a Hadamard gate to the first qubit of a two-qubit system initialized in the |00 \rangle state, followed by a controlled-NOT (CNOT) gate:

sv = Statevector.from_label('00')
plot_state_qsphere(sv.data)

mycircuit = QuantumCircuit(2)
mycircuit.h(0)
mycircuit.cx(0,1)
mycircuit.draw('mpl')

new_sv = sv.evolve(mycircuit)
print(f"Evolved statevector (Bell state): {new_sv}")
plot_state_qsphere(new_sv.data)

The qsphere visualization illustrated the entangled nature of the Bell state. Simulating measurements of this state demonstrated the correlation between the two qubits:

counts = new_sv.sample_counts(shots=1000)

from qiskit.visualization import plot_histogram
plot_histogram(counts)

The histogram showed that measurements yielded either 00 or 11 with equal probability, highlighting the entanglement.

Quantum Measurement

The concept of explicit measurement within a quantum circuit was introduced. A circuit to create and measure the Bell state was constructed:

mycircuit = QuantumCircuit(2, 2)
mycircuit.h(0)
mycircuit.cx(0,1)
mycircuit.measure([0,1], [0,1])
mycircuit.draw('mpl')

This circuit included two qubits and two classical bits to store the measurement outcomes. The measure operation associated each qubit with a corresponding classical bit. The circuit was then simulated using Qiskit’s Aer simulator:

from qiskit import Aer, execute
simulator = Aer.get_backend('qasm_simulator')
result = execute(mycircuit, simulator, shots=10000).result()
counts = result.get_counts(mycircuit)
plot_histogram(counts)

The resulting histogram of measurement outcomes mirrored the results obtained by sampling the statevector.

Graded Exercise 1: Quantum Teleportation

Implementing the quantum teleportation algorithm to transfer the state 0.70<img src="">|∣0 \rangle+0.30<img src="">​|1 \rangle from Alice’s qubit to Bob’s qubit. The algorithm was broken down into four key steps:

  1. Initialization: Creating the state to be teleported on Alice’s qubit (q0).
  2. Entanglement: Creating an entangled pair (Bell state) between Alice’s auxiliary qubit (q1) and Bob’s qubit (q2).
  3. Bell Measurement: Performing a Bell measurement on Alice’s two qubits (q0 and q1).
  4. Controlled Operations: Applying classically controlled X and Z gates on Bob’s qubit (q2) based on the measurement outcomes.
import numpy as np from qiskit import QuantumCircuit

def initialize_qubit(given_circuit, qubit_index):
     amplitude_0 = np.sqrt(0.70) amplitude_1 = np.sqrt(0.30)
     given_circuit.initialize([amplitude_0, amplitude_1], qubit_index)
     return given_circuit

def entangle_qubits(given_circuit, qubit_Alice, qubit_Bob):
     given_circuit.h(qubit_Alice)
     given_circuit.cx(qubit_Alice, qubit_Bob)
     return given_circuit1

def bell_meas_Alice_qubits(given_circuit, qubit1_Alice, qubit2_Alice, clbit1_Alice, clbit2_Alice):      given_circuit.cx(qubit1_Alice, qubit2_Alice)
     given_circuit.h(qubit1_Alice)
     given_circuit.measure([qubit1_Alice, qubit2_Alice], [clbit1_Alice, clbit2_Alice])   
     return given_circuit

def controlled_ops_Bob_qubit(given_circuit, qubit_Bob, clbit1_Alice, clbit2_Alice):       given_circuit.z(qubit_Bob).c_if(clbit1_Alice, 1)
     given_circuit.x(qubit_Bob).c_if(clbit2_Alice, 1)
     return given_circuit

The complete teleportation circuit can then be assembled and visualized:

from qiskit import QuantumRegister, ClassicalRegister

all_qubits_Alice = QuantumRegister(2, name='alice_q')
all_qubits_Bob = QuantumRegister(1, name='bob_q')
creg1_Alice = ClassicalRegister(1, name='alice_c1')
creg2_Alice = ClassicalRegister(1, name='alice_c2')

mycircuit = QuantumCircuit(all_qubits_Alice, all_qubits_Bob, creg1_Alice, creg2_Alice, name='teleportation')
initialize_qubit(mycircuit, all_qubits_Alice[0])
mycircuit.barrier()
entangle_qubits(mycircuit, all_qubits_Alice[1], all_qubits_Bob[0])
mycircuit.barrier()
bell_meas_Alice_qubits(mycircuit, all_qubits_Alice[0], all_qubits_Alice[1], creg1_Alice, creg2_Alice)
mycircuit.barrier()
controlled_ops_Bob_qubit(mycircuit, all_qubits_Bob[0], creg1_Alice, creg2_Alice)

mycircuit.draw('mpl')

Conclusion

This post provided hands-on experience with Qiskit for manipulating and visualizing single and multi-qubit quantum states. The exercises covered essential quantum computing concepts, culminating in the implementation of the quantum teleportation algorithm. The use of the qsphere visualization tool offered valuable intuitive insights into the nature of quantum states and the effects of quantum gates.

Leave a Reply