"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## SETUP\n",
"# Protocol uses 3 qubits and 2 classical bits in 2 different registers\n",
"qr = QuantumRegister(3, name=\"q\")\n",
"crz, crx = ClassicalRegister(1, name=\"crz\"), ClassicalRegister(1, name=\"crx\")\n",
"teleportation_circuit = QuantumCircuit(qr, crz, crx)\n",
"\n",
"## STEP 1\n",
"# In our case, Telamon entangles qubits q1 and q2\n",
"# Let's apply this to our circuit:\n",
"create_bell_pair(teleportation_circuit, 1, 2)\n",
"# And view the circuit so far:\n",
"teleportation_circuit.draw()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's say Alice owns $q_1$ and Bob owns $q_2$ after they part ways.\n",
"\n",
"#### Step 2 \n",
"\n",
"Alice applies a CNOT gate to $q_1$, controlled by $\\vert\\psi\\rangle$ (the qubit she is trying to send Bob). Then Alice applies a Hadamard gate to $|\\psi\\rangle$. In our quantum circuit, the qubit ($|\\psi\\rangle$) Alice is trying to send is $q_0$:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"tags": [
"thebelab-init"
]
},
"outputs": [],
"source": [
"def alice_gates(qc, psi, a):\n",
" qc.cx(psi, a)\n",
" qc.h(psi)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"

"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## SETUP\n",
"# Protocol uses 3 qubits and 2 classical bits in 2 different registers\n",
"qr = QuantumRegister(3, name=\"q\")\n",
"crz, crx = ClassicalRegister(1, name=\"crz\"), ClassicalRegister(1, name=\"crx\")\n",
"teleportation_circuit = QuantumCircuit(qr, crz, crx)\n",
"\n",
"## STEP 1\n",
"create_bell_pair(teleportation_circuit, 1, 2)\n",
"\n",
"## STEP 2\n",
"teleportation_circuit.barrier() # Use barrier to separate steps\n",
"alice_gates(teleportation_circuit, 0, 1)\n",
"teleportation_circuit.draw()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Step 3\n",
"\n",
"Next, Alice applies a measurement to both qubits that she owns, $q_1$ and $\\vert\\psi\\rangle$, and stores this result in two classical bits. She then sends these two bits to Bob."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"tags": [
"thebelab-init"
]
},
"outputs": [],
"source": [
"def measure_and_send(qc, a, b):\n",
" \"\"\"Measures qubits a & b and 'sends' the results to Bob\"\"\"\n",
" qc.barrier()\n",
" qc.measure(a,0)\n",
" qc.measure(b,1)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"

"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## SETUP\n",
"# Protocol uses 3 qubits and 2 classical bits in 2 different registers\n",
"qr = QuantumRegister(3, name=\"q\")\n",
"crz, crx = ClassicalRegister(1, name=\"crz\"), ClassicalRegister(1, name=\"crx\")\n",
"teleportation_circuit = QuantumCircuit(qr, crz, crx)\n",
"\n",
"## STEP 1\n",
"create_bell_pair(teleportation_circuit, 1, 2)\n",
"\n",
"## STEP 2\n",
"teleportation_circuit.barrier() # Use barrier to separate steps\n",
"alice_gates(teleportation_circuit, 0, 1)\n",
"\n",
"## STEP 3\n",
"measure_and_send(teleportation_circuit, 0 ,1)\n",
"teleportation_circuit.draw()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Step 4\n",
"\n",
"Bob, who already has the qubit $q_2$, then applies the following gates depending on the state of the classical bits:\n",
"\n",
"00 $\\rightarrow$ Do nothing\n",
"\n",
"01 $\\rightarrow$ Apply $X$ gate\n",
"\n",
"10 $\\rightarrow$ Apply $Z$ gate\n",
"\n",
"11 $\\rightarrow$ Apply $ZX$ gate\n",
"\n",
"(*Note that this transfer of information is purely classical*.)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"tags": [
"thebelab-init"
]
},
"outputs": [],
"source": [
"# This function takes a QuantumCircuit (qc), integer (qubit)\n",
"# and ClassicalRegisters (crz & crx) to decide which gates to apply\n",
"def bob_gates(qc, qubit, crz, crx):\n",
" # Here we use c_if to control our gates with a classical\n",
" # bit instead of a qubit\n",
" qc.x(qubit).c_if(crx, 1) # Apply gates if the registers \n",
" qc.z(qubit).c_if(crz, 1) # are in the state '1'"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"

"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## SETUP\n",
"# Protocol uses 3 qubits and 2 classical bits in 2 different registers\n",
"qr = QuantumRegister(3, name=\"q\")\n",
"crz, crx = ClassicalRegister(1, name=\"crz\"), ClassicalRegister(1, name=\"crx\")\n",
"teleportation_circuit = QuantumCircuit(qr, crz, crx)\n",
"\n",
"## STEP 1\n",
"create_bell_pair(teleportation_circuit, 1, 2)\n",
"\n",
"## STEP 2\n",
"teleportation_circuit.barrier() # Use barrier to separate steps\n",
"alice_gates(teleportation_circuit, 0, 1)\n",
"\n",
"## STEP 3\n",
"measure_and_send(teleportation_circuit, 0, 1)\n",
"\n",
"## STEP 4\n",
"teleportation_circuit.barrier() # Use barrier to separate steps\n",
"bob_gates(teleportation_circuit, 2, crz, crx)\n",
"teleportation_circuit.draw()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And voila! At the end of this protocol, Alice's qubit has now teleported to Bob."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Simulating the Teleportation Protocol "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.1 How Will We Test the Protocol on a Quantum Computer? "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this notebook, we will initialize Alice's qubit in a random state $\\vert\\psi\\rangle$ (`psi`). This state will be created using an `Initialize` gate on $|q_0\\rangle$. In this chapter we use the function `random_statevector` to choose `psi` for us, but feel free to set `psi` to any qubit state you want."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"tags": [
"thebelab-init"
]
},
"outputs": [
{
"data": {
"text/latex": [
"$$\n",
"|\\psi\\rangle =\n",
"\\begin{bmatrix}\n",
"-0.38591 - 0.11057i & -0.31966 + 0.85829i \\\\\n",
" \\end{bmatrix}\n",
"$$"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"

"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Create random 1-qubit state\n",
"psi = random_statevector(2)\n",
"\n",
"# Display it nicely\n",
"display(array_to_latex(psi, prefix=\"|\\\\psi\\\\rangle =\"))\n",
"# Show it on a Bloch sphere\n",
"plot_bloch_multivector(psi)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's create our initialization instruction to create $|\\psi\\rangle$ from the state $|0\\rangle$:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"tags": [
"thebelab-init"
]
},
"outputs": [],
"source": [
"init_gate = Initialize(psi)\n",
"init_gate.label = \"init\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(`Initialize` is technically not a gate since it contains a reset operation, and so is not reversible. We call it an 'instruction' instead). If the quantum teleportation circuit works, then at the end of the circuit the qubit $|q_2\\rangle$ will be in this state. We will check this using the statevector simulator."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.2 Using the Simulated Statevector \n",
"\n",
"We can use the Aer simulator to verify our qubit has been teleported."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"

"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## SETUP\n",
"qr = QuantumRegister(3, name=\"q\") # Protocol uses 3 qubits\n",
"crz = ClassicalRegister(1, name=\"crz\") # and 2 classical registers\n",
"crx = ClassicalRegister(1, name=\"crx\")\n",
"qc = QuantumCircuit(qr, crz, crx)\n",
"\n",
"## STEP 0\n",
"# First, let's initialize Alice's q0\n",
"qc.append(init_gate, [0])\n",
"qc.barrier()\n",
"\n",
"## STEP 1\n",
"# Now begins the teleportation protocol\n",
"create_bell_pair(qc, 1, 2)\n",
"qc.barrier()\n",
"\n",
"## STEP 2\n",
"# Send q1 to Alice and q2 to Bob\n",
"alice_gates(qc, 0, 1)\n",
"\n",
"## STEP 3\n",
"# Alice then sends her classical bits to Bob\n",
"measure_and_send(qc, 0, 1)\n",
"\n",
"## STEP 4\n",
"# Bob decodes qubits\n",
"bob_gates(qc, 2, crz, crx)\n",
"\n",
"# Display the circuit\n",
"qc.draw()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can see below, using the statevector obtained from the aer simulator, that the state of $|q_2\\rangle$ is the same as the state $|\\psi\\rangle$ we created above, while the states of $|q_0\\rangle$ and $|q_1\\rangle$ have been collapsed to either $|0\\rangle$ or $|1\\rangle$. The state $|\\psi\\rangle$ has been teleported from qubit 0 to qubit 2."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"

"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sim = Aer.get_backend('aer_simulator')\n",
"qc.save_statevector()\n",
"out_vector = sim.run(qc).result().get_statevector()\n",
"plot_bloch_multivector(out_vector)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can run this cell a few times to make sure. You may notice that the qubits 0 & 1 change states, but qubit 2 is always in the state $|\\psi\\rangle$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.3 Using the Simulated Counts \n",
"\n",
"Quantum teleportation is designed to send qubits between two parties. We do not have the hardware to demonstrate this, but we can demonstrate that the gates perform the correct transformations on a single quantum chip. Here we again use the aer simulator to simulate how we might test our protocol.\n",
"\n",
"On a real quantum computer, we would not be able to sample the statevector, so if we wanted to check our teleportation circuit is working, we need to do things slightly differently. The `Initialize` instruction first performs a reset, setting our qubit to the state $|0\\rangle$. It then applies gates to turn our $|0\\rangle$ qubit into the state $|\\psi\\rangle$:\n",
"\n",
"$$ |0\\rangle \\xrightarrow{\\text{Initialize gates}} |\\psi\\rangle $$\n",
"\n",
"Since all quantum gates are reversible, we can find the inverse of these gates using:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"tags": [
"thebelab-init"
]
},
"outputs": [],
"source": [
"inverse_init_gate = init_gate.gates_to_uncompute()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This operation has the property:\n",
"\n",
"$$ |\\psi\\rangle \\xrightarrow{\\text{Inverse Initialize gates}} |0\\rangle $$\n",
"\n",
"To prove the qubit $|q_0\\rangle$ has been teleported to $|q_2\\rangle$, if we do this inverse initialization on $|q_2\\rangle$, we expect to measure $|0\\rangle$ with certainty. We do this in the circuit below:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"

"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"## SETUP\n",
"qr = QuantumRegister(3, name=\"q\") # Protocol uses 3 qubits\n",
"crz = ClassicalRegister(1, name=\"crz\") # and 2 classical registers\n",
"crx = ClassicalRegister(1, name=\"crx\")\n",
"qc = QuantumCircuit(qr, crz, crx)\n",
"\n",
"## STEP 0\n",
"# First, let's initialize Alice's q0\n",
"qc.append(init_gate, [0])\n",
"qc.barrier()\n",
"\n",
"## STEP 1\n",
"# Now begins the teleportation protocol\n",
"create_bell_pair(qc, 1, 2)\n",
"qc.barrier()\n",
"\n",
"## STEP 2\n",
"# Send q1 to Alice and q2 to Bob\n",
"alice_gates(qc, 0, 1)\n",
"\n",
"## STEP 3\n",
"# Alice then sends her classical bits to Bob\n",
"measure_and_send(qc, 0, 1)\n",
"\n",
"## STEP 4\n",
"# Bob decodes qubits\n",
"bob_gates(qc, 2, crz, crx)\n",
"\n",
"## STEP 5\n",
"# reverse the initialization process\n",
"qc.append(inverse_init_gate, [2])\n",
"\n",
"# Display the circuit\n",
"qc.draw()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can see the `inverse_init_gate` appearing, labelled 'disentangler' on the circuit diagram. Finally, we measure the third qubit and store the result in the third classical bit:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"

"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Need to add a new ClassicalRegister\n",
"# to see the result\n",
"cr_result = ClassicalRegister(1)\n",
"qc.add_register(cr_result)\n",
"qc.measure(2,2)\n",
"qc.draw()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"and we run our experiment:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"

"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"t_qc = transpile(qc, sim)\n",
"t_qc.save_statevector()\n",
"counts = sim.run(t_qc).result().get_counts()\n",
"qubit_counts = [marginal_counts(counts, [qubit]) for qubit in range(3)]\n",
"plot_histogram(qubit_counts)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can see we have a 100% chance of measuring $q_2$ (the purple bar in the histogram) in the state $|0\\rangle$. This is the expected result, and indicates the teleportation protocol has worked properly."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. Understanding Quantum Teleportation "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As you have worked with the Quantum Teleportation's implementation, it is time to understand the mathematics behind the protocol.\n",
"\n",
"#### Step 1\n",
"\n",
"Quantum Teleportation begins with the fact that Alice needs to transmit $|\\psi\\rangle = \\alpha|0\\rangle + \\beta|1\\rangle$ (a random qubit) to Bob. She doesn't know the state of the qubit. For this, Alice and Bob take the help of a third party (Telamon). Telamon prepares a pair of entangled qubits for Alice and Bob. The entangled qubits could be written in Dirac Notation as:\n",
"\n",
"$$ |e \\rangle = \\frac{1}{\\sqrt{2}} (|00\\rangle + |11\\rangle) $$\n",
"\n",
"Alice and Bob each possess one qubit of the entangled pair (denoted as A and B respectively),\n",
"\n",
"$$|e\\rangle = \\frac{1}{\\sqrt{2}} (|0\\rangle_A |0\\rangle_B + |1\\rangle_A |1\\rangle_B) $$\n",
"\n",
"This creates a three qubit quantum system where Alice has the first two qubits and Bob the last one.\n",
"\n",
"$$ \\begin{align*}\n",
"|\\psi\\rangle \\otimes |e\\rangle &= \\frac{1}{\\sqrt{2}} (\\alpha |0\\rangle \\otimes (|00\\rangle + |11\\rangle) + \\beta |1\\rangle \\otimes (|00\\rangle + |11\\rangle))\\\\\n",
"&= \\frac{1}{\\sqrt{2}} (\\alpha|000\\rangle + \\alpha|011\\rangle + \\beta|100\\rangle + \\beta|111\\rangle) \n",
"\\end{align*}$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Step 2\n",
"\n",
"Now according to the protocol Alice applies CNOT gate on her two qubits followed by Hadamard gate on the first qubit. This results in the state:\n",
"\n",
"$$ \n",
"\\begin{align*} (H \\otimes I \\otimes I) (CNOT \\otimes I) (|\\psi\\rangle \\otimes |e\\rangle)\n",
"&=(H \\otimes I \\otimes I) (CNOT \\otimes I) \\frac{1}{\\sqrt{2}} (\\alpha|000\\rangle + \\alpha|011\\rangle + \\beta|100\\rangle + \\beta|111\\rangle) \\\\\n",
"&= (H \\otimes I \\otimes I) \\frac{1}{\\sqrt{2}} (\\alpha|000\\rangle + \\alpha|011\\rangle + \\beta|110\\rangle + \\beta|101\\rangle) \\\\\n",
"&= \\frac{1}{2} (\\alpha(|000\\rangle + |011\\rangle + |100\\rangle + |111\\rangle) + \\beta(|010\\rangle + |001\\rangle - |110\\rangle - |101\\rangle)) \\\\\n",
"\\end{align*}\n",
"$$\n",
"\n",
"Which can then be separated and written as: \n",
"\n",
"$$\n",
"\\begin{align*}\n",
"= \\frac{1}{2}(\n",
" & \\phantom{+} |00\\rangle (\\alpha|0\\rangle + \\beta|1\\rangle) \\hphantom{\\quad )} \\\\\n",
" & + |01\\rangle (\\alpha|1\\rangle + \\beta|0\\rangle) \\hphantom{\\quad )}\\\\[4pt]\n",
" & + |10\\rangle (\\alpha|0\\rangle - \\beta|1\\rangle) \\hphantom{\\quad )}\\\\[4pt]\n",
" & + |11\\rangle (\\alpha|1\\rangle - \\beta|0\\rangle) \\quad )\\\\\n",
"\\end{align*}\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Step 3\n",
"\n",
"Alice measures the first two qubit (which she owns) and sends them as two classical bits to Bob. The result she obtains is always one of the four standard basis states $|00\\rangle, |01\\rangle, |10\\rangle,$ and $|11\\rangle$ with equal probability. \n",
"\n",
"On the basis of her measurement, Bob's state will be projected to, \n",
"$$ |00\\rangle \\rightarrow (\\alpha|0\\rangle + \\beta|1\\rangle)\\\\\n",
"|01\\rangle \\rightarrow (\\alpha|1\\rangle + \\beta|0\\rangle)\\\\\n",
"|10\\rangle \\rightarrow (\\alpha|0\\rangle - \\beta|1\\rangle)\\\\\n",
"|11\\rangle \\rightarrow (\\alpha|1\\rangle - \\beta|0\\rangle)$$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Step 4\n",
"\n",
"Bob, on receiving the bits from Alice, knows he can obtain the original state $|\\psi\\rangle$ by applying appropriate transformations on his qubit that was once part of the entangled pair.\n",
"\n",
"The transformations he needs to apply are:\n",
"\n",
"$$\n",
"\\begin{array}{c c c}\n",
"\\mbox{Bob's State} & \\mbox{Bits Received} & \\mbox{Gate Applied} \\\\\n",
"(\\alpha|0\\rangle + \\beta|1\\rangle) & 00 & I \\\\\n",
"(\\alpha|1\\rangle + \\beta|0\\rangle) & 01 & X \\\\\n",
"(\\alpha|0\\rangle - \\beta|1\\rangle) & 10 & Z \\\\\n",
"(\\alpha|1\\rangle - \\beta|0\\rangle) & 11 & ZX\n",
"\\end{array}\n",
"$$\n",
"\n",
"After this step Bob will have successfully reconstructed Alice's state."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. Teleportation on a Real Quantum Computer "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 5.1 IBM hardware and Deferred Measurement \n",
"\n",
"The IBM quantum computers currently do not support instructions after measurements, meaning we cannot run the quantum teleportation in its current form on real hardware. Fortunately, this does not limit our ability to perform any computations due to the _deferred measurement principle_ discussed in chapter 4.4 of [1]. The principle states that any measurement can be postponed until the end of the circuit, i.e. we can move all the measurements to the end, and we should see the same results.\n",
"\n",
"![deferred_measurement_gates](images/defer_measurement.svg)\n",
"\n",
"Any benefits of measuring early are hardware related: If we can measure early, we may be able to reuse qubits, or reduce the amount of time our qubits are in their fragile superposition. In this example, the early measurement in quantum teleportation would have allowed us to transmit a qubit state without a direct quantum communication channel.\n",
"\n",
"While moving the gates allows us to demonstrate the \"teleportation\" circuit on real hardware, it should be noted that the benefit of the teleportation process (transferring quantum states via classical channels) is lost.\n",
"\n",
"Let us re-write the `bob_gates` function to `new_bob_gates`:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"tags": [
"thebelab-init"
]
},
"outputs": [],
"source": [
"def new_bob_gates(qc, a, b, c):\n",
" qc.cx(b, c)\n",
" qc.cz(a, c)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And create our new circuit:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"

"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"qc = QuantumCircuit(3,1)\n",
"\n",
"# First, let's initialize Alice's q0\n",
"qc.append(init_gate, [0])\n",
"qc.barrier()\n",
"\n",
"# Now begins the teleportation protocol\n",
"create_bell_pair(qc, 1, 2)\n",
"qc.barrier()\n",
"# Send q1 to Alice and q2 to Bob\n",
"alice_gates(qc, 0, 1)\n",
"qc.barrier()\n",
"# Alice sends classical bits to Bob\n",
"new_bob_gates(qc, 0, 1, 2)\n",
"\n",
"# We undo the initialization process\n",
"qc.append(inverse_init_gate, [2])\n",
"\n",
"# See the results, we only care about the state of qubit 2\n",
"qc.measure(2,0)\n",
"\n",
"# View the results:\n",
"qc.draw()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 5.2 Executing "
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"tags": [
"uses-hardware"
]
},
"outputs": [],
"source": [
"# First, see what devices we are allowed to use by loading our saved accounts\n",
"IBMQ.load_account()\n",
"provider = IBMQ.get_provider(hub='ibm-q')"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"tags": [
"uses-hardware"
]
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Job Status: job has successfully run\n"
]
}
],
"source": [
"# get the least-busy backend at IBM and run the quantum circuit there\n",
"from qiskit.providers.ibmq import least_busy\n",
"from qiskit.tools.monitor import job_monitor\n",
"backend = least_busy(provider.backends(filters=lambda b: b.configuration().n_qubits >= 3 and\n",
" not b.configuration().simulator and b.status().operational==True))\n",
"t_qc = transpile(qc, backend, optimization_level=3)\n",
"job = backend.run(t_qc)\n",
"job_monitor(job) # displays job status under cell"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"tags": [
"uses-hardware"
]
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'0': 894, '1': 130}\n"
]
},
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"

"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Get the results and display them\n",
"exp_result = job.result()\n",
"exp_counts = exp_result.get_counts(qc)\n",
"print(exp_counts)\n",
"plot_histogram(exp_counts)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As we see here, there are a few results in which we measured $|1\\rangle$. These arise due to errors in the gates and the qubits. In contrast, our simulator in the earlier part of the notebook had zero errors in its gates, and allowed error-free teleportation."
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"tags": [
"uses-hardware"
]
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The experimental error rate : 12.695%\n"
]
}
],
"source": [
"print(f\"The experimental error rate : {exp_counts['1']*100/sum(exp_counts.values()):.3f}%\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. References \n",
"[1] M. Nielsen and I. Chuang, Quantum Computation and Quantum Information, Cambridge Series on Information and the Natural Sciences (Cambridge University Press, Cambridge, 2000).\n",
"\n",
"[2] Eleanor Rieffel and Wolfgang Polak, Quantum Computing: a Gentle Introduction (The MIT Press Cambridge England, Massachusetts, 2011)."
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/usr/local/anaconda3/lib/python3.7/site-packages/qiskit/aqua/__init__.py:86: DeprecationWarning: The package qiskit.aqua is deprecated. It was moved/refactored to qiskit-terra For more information see \n",
" warn_package('aqua', 'qiskit-terra')\n"
]
},
{
"data": {
"text/html": [
"### Version Information

"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import qiskit.tools.jupyter\n",
"%qiskit_version_table"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.7"
}
},
"nbformat": 4,
"nbformat_minor": 4
}

Qiskit Software | Version |
---|---|

`qiskit-terra` | 0.18.0 |

`qiskit-aer` | 0.8.2 |

`qiskit-ignis` | 0.6.0 |

`qiskit-ibmq-provider` | 0.15.0 |

`qiskit-aqua` | 0.9.4 |

`qiskit` | 0.28.0 |

System information | |

Python | 3.7.7 (default, May 6 2020, 04:59:01) \n", "[Clang 4.0.1 (tags/RELEASE_401/final)] |

OS | Darwin |

CPUs | 8 |

Memory (Gb) | 32.0 |

Tue Aug 24 11:07:09 2021 BST |