Single-qubit and multi-qubit states, quantum teleportation (My Lab)
Cahyati Supriyati Sangaji (My Note)
You will learn how to write Qiskit
code and investigate single-qubit and multi-qubit states using the qpshere
visualization. If you have not used Jupyter notebooks before, take a look at the following video to quickly get started.
Remember, to run a cell in Jupyter notebooks, you press Shift
+ Return/Enter
on your keyboard.
Installing necessary packages
Before we begin, you will need to install some prerequisites into your environment. Run the cell below to complete these installations. At the end, the cell outputs will be cleared.
!pip install -U seaborn==0.10
!pip install -U qiskit==0.19
!pip install -U ipywidgets==7.5.1from IPython.display import clear_output
clear_output()
Single-qubit states
Single qubit states can be written down generally as
Here, 𝑝 is the probability that a measurement of the state in the computational basis {|0⟩,|1⟩} will have the outcome 1, and 𝜙 is the phase between the two computational basis states.
Single-qubit gates can then be used to manipulate this quantum state by changing either 𝑝, 𝜙, or both.
Let’s begin by creating a single-qubit quantum circuit. We can do this in Qiskit
using the following:
from qiskit import QuantumCircuitmycircuit = QuantumCircuit(1)
mycircuit.draw('mpl')
The above quantum circuit does not contain any gates. Therefore, if you start in any state, say |0⟩, applying this circuit to your state doesn’t change the state.
To see this clearly, let’s create the statevector |0⟩. In Qiskit
, you can do this using the following:
from qiskit.quantum_info import Statevectorsv = Statevector.from_label('0')
You can see what’s contained in the object sv
:
sv
Out:
Statevector([1.+0.j, 0.+0.j],
dims=(2,))
The vector itself can be found by writing
sv.data
Out:
array([1.+0.j, 0.+0.j])
Recall this
We can now apply the quantum circuit mycircuit
to this state by using the following:
new_sv = sv.evolve(mycircuit)
Once again, you can look at the new statevector by writing
new_sv
Out:
Statevector([1.+0.j, 0.+0.j],
dims=(2,))
As you can see, the statevector hasn’t changed. Recall the concept of state projection that you learned. You can compute the projection of new_sv
onto sv
by writing
from qiskit.quantum_info import state_fidelitystate_fidelity(sv, new_sv)
Out:
1.0
As you can see, the projection of new_sv
onto sv
is 1, indicating that the two states are identical. You can visualize this state using the qsphere
by writing
from qiskit.visualization import plot_state_qsphereplot_state_qsphere(sv.data)
Applying an 𝑋 gate flips the qubit from the state |0⟩ to the state |1⟩. To see this clearly, we will first create a single-qubit quantum circuit with the 𝑋 gate.
mycircuit = QuantumCircuit(1)
mycircuit.x(0)mycircuit.draw('mpl')
Now, we can apply this circuit onto our state by writing
sv = Statevector.from_label('0')
new_sv = sv.evolve(mycircuit)
new_sv
Out:
Statevector([0.+0.j, 1.+0.j],
dims=(2,))
As you can see, the statevector now corresponds to that of the state |1⟩. Recall that
Now, the projection of new_sv
onto sv
is
state_fidelity(new_sv, sv)
Out:
0.0
This is not surprising. Recall that the states |0⟩ and |1⟩ are orthogonal. Therefore, ⟨0|1⟩=0. The state can be shown on the qsphere
by writing
plot_state_qsphere(new_sv.data)
Similarly, we can create the state
by applying a Hadamard gate as you learned. Here is how we can create the state and visualize it in Qiskit
:
sv = Statevector.from_label('0')
mycircuit = QuantumCircuit(1)
mycircuit.h(0)
mycircuit.draw('mpl')
new_sv = sv.evolve(mycircuit)
print(new_sv)
plot_state_qsphere(new_sv.data)
As you can see above, the state has equal components of |0⟩ and |1⟩. The size of the circle is proportional to the probability of measuring each basis state in the statevector. As a result, you can see that the size of the circles is half of the size of the circles in our previous visualizations.
Recall that we can also create other superpositions with different phase. Let’s create
which can be done by applying the Hadamard gate on the state |1⟩.
sv = Statevector.from_label('1')
mycircuit = QuantumCircuit(1)
mycircuit.h(0)new_sv = sv.evolve(mycircuit)
print(new_sv)
plot_state_qsphere(new_sv.data)
This time, the bottom circle, corresponding to the basis state |1⟩ has a different color corresponding to the phase of 𝜙=𝜋. This is because the coefficient of |1⟩ in the state
is −1, which is equal to 𝑒𝑖𝜋.
Other phases can also be created by applying different gates. The 𝑇 and � gates apply phases of +𝜋/4 and +𝜋/2, respectively. The widget below helps you see different gates, and their actions on single-qubit quantum states.
from resources.qiskit_textbook.widgets import gate_demo
gate_demo(qsphere=True)
Out:
VBox(children=(HBox(children=(Button(description='I', layout=Layout(height='3em', width='3em'), style=ButtonSt…Image(value=b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x01\xf8\x00\x00\x01\xf8\x08\x06\x00\x00\x00\xa6(\xff…
A summary of the operations of the most common gates on single-qubit states is given by the handy image below, where the phases are shown in degrees.
Multi-qubit states
Similar to the discussion above, you can also explore multi-qubit gates in Qiskit
. We will demonstrate below how to create the Bell state
from the state |00⟩. We’ll start by visualizing the state |00⟩ using the same procedure:
sv = Statevector.from_label('00')
plot_state_qsphere(sv.data)
Next, we use the Hadamard gate described above, along with a controlled-X gate, to create the Bell state.
mycircuit = QuantumCircuit(2)
mycircuit.h(0)
mycircuit.cx(0,1)
mycircuit.draw('mpl')
The result of this quantum circuit on the state |00⟩ is found by writing
new_sv = sv.evolve(mycircuit)
print(new_sv)
plot_state_qsphere(new_sv.data)
Note how this looks very similar to a single-qubit superposition with zero phase. Following entanglement, it is no longer possible to treat the two qubits individually, and they must be considered to be one system.
To see this clearly, we can see what would happen if we measured the Bell state above 1000 times.
counts = new_sv.sample_counts(shots=1000)from qiskit.visualization import plot_histogram
plot_histogram(counts)
As you can see above, all measurements give either the result 00
or 11
. In other words, if the measurement outcome for one of the qubits is known, then the outcome for the other is fully determined.
Ungraded exercise 1
Can you create the state
using a similar procedure?
### WRITE YOUR CODE
sv = Statevector.from_label('01')
plot_state_qsphere(sv.data)
mycircuit = QuantumCircuit(2)
mycircuit.h(0)
mycircuit.cx(0,1)
mycircuit.draw('mpl')
new_sv = sv.evolve(mycircuit)
print(new_sv)
plot_state_qsphere(new_sv.data)
counts = new_sv.sample_counts(shots=1000)from qiskit.visualization import plot_histogram
plot_histogram(counts)
Ungraded exercise 2
Can you create the state
using a similar procedure?
### WRITE YOUR CODE
sv = Statevector.from_label('10')
plot_state_qsphere(sv.data)
mycircuit = QuantumCircuit(2)
mycircuit.h(0)
mycircuit.cx(0,1)
mycircuit.draw('mpl')
new_sv = sv.evolve(mycircuit)
print(new_sv)
plot_state_qsphere(new_sv.data)
counts = new_sv.sample_counts(shots=1000)from qiskit.visualization import plot_histogram
plot_histogram(counts)
Measurements
In the above example, we simulated the action of a measurement by sampling counts from the statevector. A measurement can explicitly be inserted into a quantum circuit as well. Here is an example that creates the same Bell state and applies a measurement.
mycircuit = QuantumCircuit(2, 2)
mycircuit.h(0)
mycircuit.cx(0,1)
mycircuit.measure([0,1], [0,1])
mycircuit.draw('mpl')
Two new features appeared in the circuit compared to our previous examples.
- First, note that we used a second argument in the
QuantumCircuit(2,2)
command. The second argument says that we will be creating a quantum circuit that contains two qubits (the first argument), and two classical bits (the second argument). - Second, note that the
measure
command takes two arguments. The first argument is the set of qubits that will be measured. The second is the set of classical bits onto which the outcomes from the measurements of the qubits will be stored.
Since the above quantum circuit contains non-unitaries (the measurement gates), we will use Qiskit
's built-in Aer
simulators to run the circuit. To get the measurement counts, we can use the following code:
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)
As you can see, the measurement outcomes are similar to when we sampled counts from the statevector itself.
Graded exercise 1: Quantum teleportation
In this graded exercise, you will teleport the quantum state
from Alice’s qubit to Bob’s qubit. Recall that the teleportation algorithm consists of four major components:
- Initializing the state to be teleported. We will do this on Alice’s qubit
q0
. - Creating entanglement between two qubits. We will use qubits
q1
andq2
for this. Recall that Alice ownsq1
, and Bob ownsq2
. - Applying a Bell measurement on Alice’s qubits
q0
andq1
. - Applying classically controlled operations on Bob’s qubit
q2
depending on the outcomes of the Bell measurement on Alice's qubits.
This exercise guides you through each of these steps.
Initializing the state to be teleported
First, create a quantum circuit that creates the state
You can do this by using Qiskit
's initialize
function.
def initialize_qubit(given_circuit, qubit_index):
import numpy as np
### WRITE YOUR CODE BETWEEN THESE LINES - START
desired_vector = [np.sqrt(0.7),np.sqrt(0.3)]
given_circuit.initialize(desired_vector, qubit_index)
### WRITE YOUR CODE BETWEEN THESE LINES - END
return given_circuit
Next, we need to create entanglement between Alice’s and Bob’s qubits.
def entangle_qubits(given_circuit, qubit_Alice, qubit_Bob):
### WRITE YOUR CODE BETWEEN THESE LINES - START
given_circuit.h(qubit_Alice)
given_circuit.cx(qubit_Alice, qubit_Bob)
### WRITE YOUR CODE BETWEEN THESE LINES - END
return given_circuit
Next, we need to do a Bell measurement of Alice’s qubits.
def bell_meas_Alice_qubits(given_circuit, qubit1_Alice, qubit2_Alice, clbit1_Alice, clbit2_Alice):
### WRITE YOUR CODE BETWEEN THESE LINES - START
given_circuit.cx(qubit1_Alice, qubit2_Alice)
given_circuit.h(qubit1_Alice)
given_circuit.barrier()
given_circuit.measure(qubit1_Alice,clbit1_Alice)
given_circuit.measure(qubit2_Alice,clbit2_Alice)
### WRITE YOUR CODE BETWEEN THESE LINES - ENDreturn given_circuit
Finally, we apply controlled operations on Bob’s qubit. Recall that the controlled operations are applied in this order:
- an 𝑋X gate is applied on Bob’s qubit if the measurement coutcome of Alice’s second qubit,
clbit2_Alice
, is1
. - a 𝑍Z gate is applied on Bob’s qubit if the measurement coutcome of Alice’s first qubit,
clbit1_Alice
, is1
.
def controlled_ops_Bob_qubit(given_circuit, qubit_Bob, clbit1_Alice, clbit2_Alice):
### WRITE YOUR CODE BETWEEN THESE LINES - START
given_circuit.x(qubit_Bob).c_if(clbit2_Alice, 1)
given_circuit.z(qubit_Bob).c_if(clbit1_Alice, 1)
### WRITE YOUR CODE BETWEEN THESE LINES - END
return given_circuit
The next lines of code put everything together.
### imports
from qiskit import QuantumRegister, ClassicalRegister### set up the qubits and classical bits
all_qubits_Alice = QuantumRegister(2)
all_qubits_Bob = QuantumRegister(1)
creg1_Alice = ClassicalRegister(1)
creg2_Alice = ClassicalRegister(1)### quantum teleportation circuit here
# Initialize
mycircuit = QuantumCircuit(all_qubits_Alice, all_qubits_Bob, creg1_Alice, creg2_Alice)
initialize_qubit(mycircuit, 0)
mycircuit.barrier()
# Entangle
entangle_qubits(mycircuit, 1, 2)
mycircuit.barrier()
# Do a Bell measurement
bell_meas_Alice_qubits(mycircuit, all_qubits_Alice[0], all_qubits_Alice[1], creg1_Alice, creg2_Alice)
mycircuit.barrier()
# Apply classically controlled quantum gates
controlled_ops_Bob_qubit(mycircuit, all_qubits_Bob[0], creg1_Alice, creg2_Alice)### Look at the complete circuit
print(mycircuit.draw(output='text'))### store the circuit as the submitted answer
answer = mycircuit
Additional reading
- You can watch a video on building the quantum teleportation quantum circuit here: https://www.youtube.com/watch?v=mMwovHK2NrE&list=PLOFEBzvs-Vvp2xg9-POLJhQwtVktlYGbY&index=6&t=0s
- For additional details about the quantum teleportation algorithm, including the principle of deferred measurement, you can refer to the Qiskit Textbook’s section on the algorithm here: https://qiskit.org/textbook/ch-algorithms/teleportation.html
- The
1 minute Qiskit
episode entitledWhat is the qsphere?
succinctly describes the Qsphere visualization tool that we used in this lab. You can find it here: https://youtu.be/4SoK2h4a7us
References:
Qiskit (Global Summer School), Introduction to Quantum Computing and Quantum Hardware — Lab 1