{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "

✅ Put your name here

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#

In-Class Assignment 24: Programming Quantum Computers

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this assignment, we'll use what we learned about quantum bits and quantum circuits in previous assignments to do useful computation. We'll continue using Qiskit to write quantum algorithms (i.e., algorithms for quantum computers). You'll use a quantum computer simulator to test your algorithms, and you'll even get the chance to run the algorithms you wrote on real quantum computers!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##

Itinerary

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
AssignmentTopicDescription
Pre Class 23Background for Quantum ComputingHow Computers Store Information
In Class 23Classsical and Quantum BitsInformation in Quantum States
Pre Class 24Software for Quantum ComputingHigh Level Software and the Circuit Model
In Class 24Programming Quantum ComputersManipulating Quantum Bits to Perform Useful Computations
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##

Learning Goals

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The learning goals for this assignment are:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Be able to write quantum circuits in Qiskit to perform useful computation such as generating random numbers.\n", "1. Understand how qubits can be \"copied\" using the quantum teleportation protocol.\n", "1. Reflect on the strengths/weaknesses and opportunities/challenges for quantum computing." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##

Recap of Pre-Class Assignment: Quantum Circuits

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, we breifly recap a quantum circuit, which was covered in yesterday's pre-class assignment.\n", "\n", "A quantum circuit (`QuantumCircuit` in Qiskit) consists of:\n", "\n", "1. A collection of qubits, called a `QuantumRegister` in Qiskit.\n", "1. A collection of bits, called a `ClassicalRegister` in Qiskit.\n", "1. A collection of operations on qubits and, sometimes, bits.\n", "\n", "For your benefit, an example of creating a `QuantumCircuit` in Qiskit is shown below." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Imports for the notebook.\"\"\"\n", "import qiskit" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Example of a quantum circuit in Qiskit.\"\"\"\n", "# quantum register with two qubits\n", "qreg = qiskit.QuantumRegister(2)\n", "\n", "# classical register with one bit\n", "creg = qiskit.ClassicalRegister(2)\n", "\n", "# create a quantum circuit out with both registers\n", "circ = qiskit.QuantumCircuit(qreg, creg)\n", "\n", "# do some operation on the zeroth qubit\n", "circ.x(qreg[0])\n", "\n", "# do another operation on the zeroth qubit\n", "circ.y(qreg[0])\n", "\n", "# do some operation on the first qubit\n", "circ.z(qreg[1])\n", "\n", "# measure the qubits\n", "circ.measure(qreg, creg)\n", "\n", "# draw the circuit\n", "circ.draw()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We read this diagram according to the rules below.\n", "\n", "1. All qubits start in the ground state $|0\\rangle$ at the left of the diagram.\n", "1. All bits start in the state 0 at the left of the diagram (below the qubits).\n", "1. Time flows from left to right. Qubits evolving through time are shown with a single line. Bits are shown with two lines.\n", "1. Operations are shown as boxes with symbols representing the operation.\n", "\n", "In the remainder of the assignment, we'll write quantum circuits that perform useful computations." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#

Part 1: Quantum Random Number Generator

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this problem, you'll get the chance to write a quantum algorithm that produces a random bit. We explored this problem when we wrote our own `Qubit` class in the previous In Class Assignment. Now, you'll use Qiskit to do this." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Question: What operation did we perform on our `Qubit` starting in the state $|0\\rangle$ to produce a random state when measured?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Answer: Erase the contents of this cell and put your answer here!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##

Step 1: Set up the Quantum Circuit

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: In the following cell, use Qiskit to:\n", "\n", "1. Create a quantum register with one qubit.\n", "1. Create a classical register with one bit.\n", "1. Create a `QuantumCircuit` object consisting of your quantum and classical registers.\n", "1. Add the operations for a random bit generator, which consist of a Hadamard gate and a measurement.\n", "1. Draw the resulting circuit.\n", "\n", "Hint: If you're stuck, refer to the provided code above (or the Pre-Class Assignment) and make the appropriate modifications." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Set up the quantum circuit.\"\"\"\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"ANSWER.\"\"\"\n", "\n", "# ===================================================\n", "# create a quantum circuit with one qubit and one bit\n", "# ===================================================\n", "\n", "qreg = qiskit.QuantumRegister(1)\n", "creg = qiskit.ClassicalRegister(1)\n", "circ = qiskit.QuantumCircuit(qreg, creg)\n", "\n", "# ===============================================\n", "# add the operations for the random bit generator\n", "# ===============================================\n", "\n", "circ.h(qreg[0])\n", "circ.measure(qreg[0], creg[0])\n", "\n", "# ========================\n", "# draw the quantum circuit\n", "# ========================\n", "\n", "circ.draw()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##

Step 2: Run the Circuit and Display the Results

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that we have a quantum circuit, we need something to execute its instructions, called a backend in Qiskit. There are two options:\n", "\n", "1. A quantum computer simulator, which is a program that runs on a classical computer designed to mimic the evolution of a quantum computer. The `Qubit` class you wrote was a basic version of a quantum computer simulator. \n", "\n", "1. An actual quantum computer, which natively performs all operations in the quantum circuit.\n", "\n", "Note: As we've seen during In Class Assignment 23, the outcome of measuring a `Qubit` was random. Because of this, it's common to run a quantum circuit many times and sample from the output distribution. The number of times a quantum circuit is run is called `shots` in Qiskit.\n", "\n", "Typically, algorithms are first run on a simulator to test them (and because there's only so many quantum computers in the world today). You're only required to run quantum circuits on a simulator for this assignment, but bonus problems are available to use a real quantum computer!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: In the following cell, use Qiskit to:\n", "\n", "1. Get a backend for a quantum computer simulator.\n", "1. Execute your random bit generator circuit above using 100 `shots`.\n", "1. Make a histogram that displays the frequency of measured 0's and 1's. (Hint: Qiskit has built-in features to do this in the `tools.visualization` module. You may want to look back to Pre Class 24 to see how we parse the output of a circuit execution in Qiskit.)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Get a backend and run the circuit.\"\"\"\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "\"\"\"ANSWER: Getting a backend and running the circuit.\"\"\"\n", "\n", "# ==============================================\n", "# get a backend for a quantum computer simulator\n", "# ==============================================\n", "\n", "backend = qiskit.Aer.get_backend(\"qasm_simulator\")\n", "\n", "# ==============================\n", "# run the circuit on the backend\n", "# ==============================\n", "\n", "job = qiskit.execute(circ, backend, shots=100)\n", "result = job.result()\n", "counts = result.get_counts()\n", "\n", "# ===================\n", "# display the results\n", "# ===================\n", "\n", "qiskit.tools.visualization.plot_histogram(counts)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##

Step 3: Extend the Random Number Generator

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You should have seen roughly equal frequencies of 0 and 1 outcomes above. Now, the problem we want to solve is this: How can we write a quantum circuit that generates numbers in an arbitrary range? In particular, we want to generate a random number between 0 and 31." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Question: How many bits are needed to store a number between 0 and 31? Hint: Think back to Pre-Class 23. How did we store a letter of the alphabet using bits?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Answer: Erase the contents of this cell and put your answer here!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Remember that when we measure a qubit, we get one bit of information. Therefore, to produce a random number between 0 and 31, we'll need the same number of qubits as the number of bits to store a number between 0 and 31 (i.e., your answer to the previous question)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: In the following cell, use Qiskit to write a quantum circuit that can generate random numbers in the range 0 to 31." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Extending the random number generator.\"\"\"\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"ANSWER: Extending the random number generator.\"\"\"\n", "\n", "# number of qubits and bits to use\n", "n = 5\n", "\n", "# ==========================\n", "# creating a quantum circuit\n", "# ==========================\n", "\n", "qreg = qiskit.QuantumRegister(n)\n", "creg = qiskit.ClassicalRegister(n)\n", "circ = qiskit.QuantumCircuit(qreg, creg)\n", "\n", "# =====================================================\n", "# adding the operations for the random number generator\n", "# =====================================================\n", "\n", "for x in range(n):\n", " circ.h(qreg[x])\n", "\n", "for x in range(n):\n", " circ.measure(qreg[x], creg[x])\n", " \n", "# ========================\n", "# draw the quantum circuit\n", "# ========================\n", "\n", "circ.draw()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: In the following cell:\n", "\n", "1. Execute the quantum circuit you've written using a quantum computer simulator backend.\n", "1. Display the results of the frequency of ALL measurement outcomes using `1000` shots." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Execute your quantum circuit here.\"\"\"\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "\"\"\"ANSWER: Getting a backend and running the circuit.\"\"\"\n", "\n", "# =================\n", "# getting a backend\n", "# =================\n", "\n", "backend = qiskit.Aer.get_backend(\"qasm_simulator\")\n", "\n", "# ==================================\n", "# running the circuit on the backend\n", "# ==================================\n", "\n", "job = qiskit.execute(circ, backend, shots=1000)\n", "result = job.result()\n", "\n", "# ======================\n", "# displaying the results\n", "# ======================\n", "\n", "counts = result.get_counts()\n", "qiskit.tools.visualization.plot_histogram(counts)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: In the following cell:\n", "\n", "1. Compute the most probable outcome (bit string) and convert it to an integer in the range 0-31.\n", "\n", "Hint: You can get the key of a dictionary with the maximum value by doing `max(dictionary, key=dictionary.get)`.\n", "\n", "Hint: In Python, ```int(\"10\", 2)``` returns 2, and \"10\" is the integer 2 in binary." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Compute the random number in the range 0-31 from the output of the circuit.\"\"\"\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"ANSWER: Compute the random number in the range 0-31 from the output of the circuit.\"\"\"\n", "\n", "# get the most probable outcome\n", "max_string = max(counts, key=counts.get)\n", "\n", "# print it out\n", "print(\"Most frequent bitstring:\", max_string)\n", "\n", "# convert the binary string to an integer\n", "random_number = int(max_string, 2)\n", "\n", "# print it out\n", "print(\"Value of bit string in base 10:\", random_number)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##

Executing on a Real Quantum Computer

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that you have a quantum circuit written, you can easily change the `backend` to run it on a real quantum computer rather than a quantum computer simulator. In order to use real quantum computers, you'll need to set up an account on the IBM Q website and get an API Token. If you haven't done this already, the steps are listed below.\n", "\n", "If you don't have an account:\n", "\n", "1. Go to https://quantumexperience.ng.bluemix.net/qx/experience.\n", "1. Click \"Sign in\" in the upper right.\n", "1. In the pop-up screen, select \"Sign Up\" or \"Sign up using Github.\" The first requires an email, the second requires you to log into GitHub and authorize access to your account (to get an email).\n", "1. Fill out the form.\n", "\n", "Once you have an account:\n", "\n", "1. Go to https://quantumexperience.ng.bluemix.net/qx/account/profile.\n", "1. Click \"Advanced\" in the upper right of the page.\n", "1. Copy your API Token into the cell below. (Should be a long string of digits and characters.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: Enter your API token between the quotes in the following cell." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Put your API Token here. This cell will throw an error until a valid API_TOKEN is entered.\"\"\"\n", "\n", "API_TOKEN = \"\"\n", "qiskit.IBMQ.enable_account(API_TOKEN)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Register to use backends.\"\"\"\n", "\n", "# NOTE: student API tokens will of course be different. They should look something like this, though\n", "API_TOKEN = \"3ce852634bcc0d3fc6a5af0920aff9ad4be74ec6972f2a8e06b384796d4b28fd933c7386d2e1296ee5b0425afb317f75d44f558ba6ba18cd8fc899a1fe9fcbb8\"\n", "qiskit.IBMQ.enable_account(API_TOKEN)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Your account should now be enabled and you should be able to see quantum computers as `backends`. Run the following cell to see what backends are available." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "\"\"\"See all available backends.\"\"\"\n", "print(qiskit.IBMQ.backends())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Question: What backends do you see? Which ones are real quantum computers?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Answer: Erase the contents of this cell and put your answer here!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: Pick a quantum computer as a `backend` to run on in the following cell." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Select an available backend to use.\"\"\"\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"ANSWER: Put your code here for running this circuit on a quantum computer simulator.\"\"\"\"\"\"ANSWER: Selecting a backend. Either ibmqx2, ibmqx4, or ibmqx5, whichever is available.\n", "Hopefully not all will be under maintenance during the assignment...\"\"\"\n", "backend = qiskit.IBMQ.backends()[1]\n", "print(backend)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Question: Research the quantum computer you selected on the web and write some facts about it. (How many qubits does it have? When was it first put online?) This website may be helpful." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Answer: Erase the contents of this cell and put your answer here!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now that you've selected a backend, pick one of the two circuits you wrote to run, and list it in the cell below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: Erase the contents of this cell and write which circuit you chose to execute here. (Random bit generator or random number generator.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: In the cell below, write code to run your circuit on a real quantum computer using Qiskit." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Run your algorithm on a real quantum computer.\"\"\"\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"ANSWER: Running on a real quantum computer.\"\"\"\n", "job = qiskit.execute(circ, backend)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The cell below will check the status of your submission. Note: This assumes you named your job submisstion `job`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Print the status of the job submission, as well as the queue position.\n", "Check your status/queue position by occasionally running this cell as you work through later problems.\"\"\"\n", "print(job.status())\n", "print(job.queue_position())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When you submit a circuit to be executed (a \"job\"), the job gets submitted to the queue, since these computers are available to everyone. Depending on the time of day, your job could take a few minutes to a few hours to execute.\n", "\n", "While you wait for your job to execute, you should continue working through the notebook. You can check the status and queue position of your job periodically." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you encounter errors: First try to fix them by asking an instructor, TA, or LA. If this fails, an alternative to running an algorithm on a quantum computer is described below. This assumes you have set up an account to use IBM's quantum computers. (If not, see these instructions above.)\n", "\n", "1. Navigate to the IBM Quantum Composer website https://quantumexperience.ng.bluemix.net/qx/editor. You'll need to be logged in if you are not already.\n", "1. Scroll down to the \"New experiment\" section with a quantum circuit diagram.\n", "1. Drag in gates from the \"Gates\" section to the right and drop them on qubits to manually program your algorithm. To do the random bit generator, you should add a Hadmard gate and measurement on the same qubit.\n", "1. Click \"Run\" and follow the instructions. This will submit your job. When it's finished, an email will be sent to the email address you signed up with containing the results of your algorithm." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Congratulations! You just ran an algorithm on a quantum computer!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: In the code cell below, make a histogram to display the frequencies of your results in the same way as the previous steps. To do this, you'll need to make sure your job has executed. You may need to hard code in your results if you used the Quantum Composer.)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Make a histogram of output results here.\"\"\"\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"ANSWER: Make a histogram of output results here.\"\"\"\n", "result = job.result()\n", "counts = result.get_counts()\n", "qiskit.tools.visualization.plot_histogram(counts)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Question: How do your results compare to the same algorithm you ran on a simulator? Current quantum computers are noisy devices, so for algorithms with many gates, the output distribution can look very different compared to when the algorithm is run on a simulator. For algorithms with few gates, the results should be comparable." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Answer: Erase the contents of this cell and put your answer here!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#

Part 2: Quantum Teleportation Algorithm

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "During In Class Assignment 23, we talked about the differences between copying a bit and copying a qubit. To copy a bit, it's easy: you just look at the bit's value, record it, and write it into a new bit. For a qubit, on the other hand, which has a wavefunction which \"gets destroyed\" when you measure it, the problem is a bit more subtle. \n", "\n", "As copying information is such an important routine in communication and computation, you may wonder if there's anything we can do? Luckily, there is, but it involves destroying the original qubit! (There's no free lunch with copying qubits!) It's called quantum teleportation. The image below shows a stylized quantum circuit diagram. We describe this diagram below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"Stylized" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For clarity, let's say there's two people, Alice and Bob. Alice has some qubit $|\\psi\\rangle = \\alpha |0\\rangle + \\beta |1\\rangle$ that she wants to send to Bob. This is the message at the top of the above diagram. Here's what happens. Alice starts with one qubit, Bob starts with two.\n", "\n", "1. Bob prepares an EPR pair with two qubits (far left of diagram), and sends one of them to Alice. (An EPR pair is a special pair of qubits that we'll cover in Step 1 below.)\n", "1. Alice performs the same operations as Bob on her qubits in reverse, then measures both qubits.\n", "1. Alice tells Bob her measurement results, which allows Bob to reconstruct the state $|\\psi\\rangle$ by performing the appropriate operations on his qubit.\n", "\n", "We'll work through these steps in more detail as you complete this problem." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##

Step 1: Bob Prepares an EPR Pair

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To prepare an EPR pair, it's as easy as two operations, one of which we already know: A Hadamard gate!\n", "\n", "The other operation is called a Controlled-NOT operation, or just CNOT. The CNOT gate acts on two qubits with the following effect:\n", "\n", "\\begin{align}\n", " \\text{CNOT}|0\\rangle |0\\rangle &= |0\\rangle |0\\rangle \\\\\n", " \\text{CNOT}|0\\rangle |1\\rangle &= |0\\rangle |1\\rangle \\\\\n", " \\text{CNOT}|1\\rangle |0\\rangle &= |1\\rangle |1\\rangle \\\\\n", " \\text{CNOT}|1\\rangle |1\\rangle &= |1\\rangle |0\\rangle\n", "\\end{align}\n", "\n", "If you look closely, you'll see that the CNOT gate flips the second qubit if the first qubit is $|1\\rangle$ and does nothing otherwise. (The name makes sense: A NOT gate on the second qubit controlled on the first qubit.)\n", "\n", "Don't worry, you won't have to code how the CNOT gate works: Qiskit has this for you. You just need to implement it. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "####

---------------- Brief Remark about EPR Pairs and Quantum Entanglement ----------------

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An EPR pair has special properties that quantum teleportation exploits. Below, we create an EPR Pair with two qubits. An EPR pair shows an example of quantum entanglement in quantum mechanics. Quantum entanglement has cool and useful properties, which we'll now briefly explore. As an aside, Albert Einstein never fully understood quantum entanglement before he passed away -- here's your chance to surpass Einstein! (The E in EPR stands for Einstein.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: Read through the following code to understand what's happening, then run the cell." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "\"\"\"Example code: exploring quantum entanglement.\"\"\"\n", "# get a circuit with two qubits and two bits\n", "qreg = qiskit.QuantumRegister(2)\n", "creg = qiskit.ClassicalRegister(2)\n", "entanglement_circuit = qiskit.QuantumCircuit(qreg, creg)\n", "\n", "# add operations to create an entangled state\n", "entanglement_circuit.h(qreg[0])\n", "entanglement_circuit.cx(qreg[0], qreg[1])\n", "\n", "# measure both qubits\n", "entanglement_circuit.measure(qreg[0], creg[0])\n", "entanglement_circuit.measure(qreg[1], creg[1])\n", "\n", "# print out the circuit diagram\n", "print(entanglement_circuit.draw())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The circuit (without the measurements) shown above produces an EPR Pair. When we run this circuit (with the measurements), we'll see a particular correlation in the measurement outcomes." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: In the following cell, run the `entanglement_circuit` above on a quantum computer simulator backend for `100` shots. You could also run this on a quantum computer backend if you want!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Put your code here for running this circuit on a quantum computer simulator.\"\"\"\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "\"\"\"ANSWER: Put your code here for running this circuit on a quantum computer simulator.\"\"\"\n", "# get a backend\n", "backend = qiskit.Aer.get_backend(\"statevector_simulator\")\n", "\n", "# or on a quantum computer\n", "#backend = qiskit.IBMQ.backends()[1]\n", "\n", "# submit the job\n", "job = qiskit.execute(entanglement_circuit, backend, shots=100)\n", "\n", "# get the counts\n", "res = job.result()\n", "counts = res.get_counts()\n", "\n", "# not necessary, but helpful. alternatively, print out counts\n", "qiskit.tools.visualization.plot_histogram(counts)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Question: Look at the outcome of your circuit (by making a histogram or looking at the measurement counts). You should only see two outcomes. What outcomes are they?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Answer: Erase the contents of this cell and put your answer here!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There's only two outcomes because of quantum entanglement, a form of correlation between qubits. The EPR Pair has the property that, when one qubit is measured, the other qubit \"collapses\" into the state that was measured. So, when one qubit is measured as $0$ above, the other qubit becomes $|0\\rangle$, and hence is always measured as $0$. Similarly for $1$. This quantum correlation is a stronger correlation than is possible in classical systems (systems described by classical, not quantum, physics), as proved by John Stewart Bell in 1964 and verified experimentally in 2015, which refuted Einstein's disagreement with entanglement from 1935." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "####

---------------- End Brief Remark about EPR Pairs and Quantum Entanglement ----------------

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now back to the teleportation circuit, which exploits quantum entanglement." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: In the following cell:\n", "\n", "1. Create a quantum circuit with three qubits and three classical bits. Important: Make three separate `QuantumRegister`s and three separeate `ClassicalRegister`s (as opposed to one `QuantumRegister` of size three, etc.) This will make it easier for us to program the algorithm.\n", "1. Perform a NOT operation on Alice's qubit -- the first (top) in the circuit. This will be the qubit (or message) she sends to Bob. In general, this could be any qubit, this is just one example.\n", "1. Prepare an EPR pair on Bob's qubits -- the last (bottom) two in the circuit.\n", "1. Draw your circuit diagram.\n", "\n", "Your circuit diagram at the end should look something like (you can ignore the grey vertical lines):\n", "\n", "\"Quantum" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Put your code here.\"\"\"\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "\"\"\"ANSWER: Alice prepares a state, Bob makes an EPR pair.\n", "\n", "NOTE: Barriers are not necessary for student's code, they're just here for clarity.\"\"\"\n", "\n", "# =======================================\n", "# get a quantum circuit with three qubits\n", "# =======================================\n", "\n", "# three qubits\n", "alice = qiskit.QuantumRegister(1, name=\"alice\")\n", "shared = qiskit.QuantumRegister(1, name=\"shared\")\n", "bob = qiskit.QuantumRegister(1, name=\"bob\")\n", "\n", "# three bits\n", "alice_measure0 = qiskit.ClassicalRegister(1, name=\"alice_measure0\")\n", "alice_measure1 = qiskit.ClassicalRegister(1, name=\"alice_measure1\")\n", "bob_measure = qiskit.ClassicalRegister(1, name=\"bob_measure\")\n", "\n", "# circuit with all qubits and bits\n", "circ = qiskit.QuantumCircuit(alice, shared, bob, alice_measure0, alice_measure1, bob_measure)\n", "\n", "# ==============================\n", "# Alice prepares a qubit to send\n", "# ==============================\n", "\n", "circ.x(alice)\n", "circ.barrier() # not necessary\n", "\n", "# ========================\n", "# Bob prepares an EPR pair\n", "# ========================\n", "\n", "circ.h(shared)\n", "circ.cx(shared, bob)\n", "\n", "# =====================\n", "# print out the circuit\n", "# =====================\n", "\n", "circ.draw()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##

Step 2: Alice Reverses Bob's Operations and Measures

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we imagine Bob sends his qubit to Alice, who could in theory be as far away as she wishes. Once Alice receives the qubit (which is right away for us), she reverses the operations that Bob performed on her two qubits and measures." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: Using your same quantum circuit from above, add the following operations.\n", "\n", "1. Perform a CNOT on Alice's two qubits (control on the one she originally had).\n", "1. Perform a Hadamard gate on Alice's first qubit (the one she originally had).\n", "1. Measure both of Alice's qubits (the top two in the circuit shown below).\n", "1. Draw your circuit diagram.\n", "\n", "Your circuit diagram at the end should look something like (you can ignore the grey vertical lines):\n", "\n", "\"Quantum" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Put your code here.\"\"\"\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "\"\"\"ANSWER: Perform the operations above and draw the circuit.\n", "\n", "NOTE: Barriers are not necessary.\n", "\"\"\"\n", "\n", "# ==================\n", "# Alice's operations\n", "# ==================\n", "\n", "circ.barrier() # not necessary\n", "circ.cx(alice, shared)\n", "circ.h(alice)\n", "\n", "# ====================\n", "# Alice's measurements\n", "# ====================\n", "\n", "circ.barrier() # not necessaary\n", "circ.measure(alice, alice_measure0)\n", "circ.measure(shared, alice_measure1)\n", "\n", "# ================\n", "# draw the circuit\n", "# ================\n", "\n", "circ.draw()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##

Step 3: Bob Performs Conditional Operations

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we imagine that Alice sends the results of her measurements to Bob. Remember, her measurements are just bits, so there's no problem communicating them to Bob. Note: Because Alice has to transmit classical information, quantum teleportation is not superluminal (faster than the speed of light), despite popular science misconceptions.\n", "\n", "Bob then listens to Alice and acts accordingly on his qubit." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: Using your same quantum circuit from above, add the following operations.\n", "\n", "1. If Alice measured a 1 on her FIRST qubit, perform a Z gate on Bob's qubit. (Hint 1: Look up the `Z` gate in Qiskit's documentation. Hint 2: Use the `c_if` method to implement this gate conditioned on the measurement outcome.)\n", "1. If Alice measured a 1 on her SECOND qubit, perform a NOT gate on Bob's qubit.\n", "1. Measure Bob's qubit. (This is just for us to see the result. In practice, the qubit wouldn't be measured if Bob wanted the quantum state.)\n", "1. Draw the circuit diagram.\n", "\n", "\n", "Your circuit diagram at the end should look something like (you can ignore the grey vertical lines):\n", "\n", "\"Quantum" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Put your code here.\"\"\"\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"ANSWER: Perform the above operations on Bob's qubit.\n", "\n", "NOTE: Barriers are again not necessary.\n", "\"\"\"\n", "\n", "# ======================\n", "# conditional operations\n", "# ======================\n", "\n", "circ.z(bob).c_if(alice_measure0, 1)\n", "circ.x(bob).c_if(alice_measure1, 1)\n", "\n", "# =======================\n", "# measure the Bob's qubit\n", "# =======================\n", "\n", "circ.measure(bob, bob_measure)\n", "\n", "# =====================\n", "# print out the circuit\n", "# =====================\n", "\n", "circ.draw()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##

Step 4: Run the Circuit

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You've now written the entire quantum teleportation algorithm! Congrats! All that's left to do is execute the circuit in the same way we've done before." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Do this: In the following cell:\n", "\n", "1. Get a quantum computer simulator as a backend.\n", "1. Using your backend, execute your quantum teleportation circuit using 1000 `shots`.\n", "1. Make a histogram of the frequency of the outcome measurements." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"Put your code here.\"\"\"\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\"\"\"ANSWER: Run the quantum teleportation circuit.\"\"\"\n", "\n", "# =============\n", "# get a backend\n", "# =============\n", "\n", "backend = qiskit.Aer.get_backend(\"qasm_simulator\")\n", "\n", "# ==============================\n", "# run the circuit on the backend\n", "# ==============================\n", "\n", "job = qiskit.execute(circ, backend, shots=1000)\n", "result = job.result()\n", "\n", "# ===================\n", "# display the results\n", "# ===================\n", "\n", "counts = result.get_counts()\n", "qiskit.tools.visualization.plot_histogram(counts)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Question: Make sense of your results by answering the following questions.\n", "\n", "1. How many measurement outcomes could there be in total for measuring three qubits?\n", "1. How many measurement outcomes do you see in your histogram? (You should see fewer than your answer to the above question.)\n", "1. If the quantum teleportation algorithm worked, what should Bob always measure?\n", "1. Does this agree with your results above? (Hint: See if one of the measured bits is always the same.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Answer: Erase the contents of this cell and put your answer here!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#

Part 3: Other Quantum Algorithms

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You've just written two quantum algorithms, congrats! The first quantum algorithm, the random number generator, is useful because it generates truly random numbers guarunteed by the laws of (quantum) physics. Random numbers have a lot of practical applications ranging including communication, cryptography, and computation, of course.\n", "\n", "This isn't just an artificial example, either! Quantum random number generation is a real protocol used in academia and industry. For example, you can run the cell below to see an online quantum random number generator by researchers at the Austrailian National University, and read about how NIST is using similar technology for internet security." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "\"\"\"Livestream truly random numbers guarunteed by quantum physics!\n", "\n", "You may have to scroll down in the webpage after executing this cell.\"\"\"\n", "from IPython.display import HTML\n", "HTML(\n", "\"\"\"\n", "\n", "\"\"\"\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The second algorithm, the quantum teleportation algorithm, is used for memory systems in quantum computers as well as in communication protocols for the quantum internet. (Read about the quantum internet being developed in Europe here if you're interested.) Generating an EPR pair is also used in a lot of quantum cryptography applications as well." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One of the most exciting aspects of quantum computing is that some problems, though not all, can be solved a LOT faster on quantum computers than on classical computers. Shor's algorithm, a quantum algorithm for factoring numbers, is the most famous and what started the field. It got a lot of people interested because the security of, say, your credit card information when you buy something on Amazon is protected by the fact that no one has come up with a fast algorithm for factoring numbers on classical computers." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Question: Do a web search for other quantum algorithms and list at least three of them here, including what they're called, what they do, and any other information you can find. Cite your source(s). Hint: This webiste may be useful: http://quantumalgorithmzoo.org/." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " **Answer:** Erase the contents of this cell and put your answer here!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "About Shor's algorithm breaking cryptography with a quantum computer... Don't worry! Your credit card information and messages are still safe online! In principle, they could be hacked if we had a big enough quantum computer, but currently we don't. Not even close! Building a good quantum computer with many qubits is one of the biggest engineering challenges facing many technology companies like IBM, Microsoft, Rigetti, and Google today. (And also academics as well! The Labratory for Hybrid Quantum Systems (LHQS) at MSU and run by Dr. Johannes Pollanen works on qubit technologies based superconducting qubits and electrons on the surface of helium.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Question: Do a web search to find out some challenges in building quantum computers. List at least two of them here. Cite your source(s)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " **Answer:** Erase the contents of this cell and put your answer here!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Even with these challenges, the problem of demonstrating a computational speedup on a quantum computer is the million dollar question... literally! If you come up with a quantum algorithm and prove it's faster than any existing algorithm on a current classical computer, you're entitled to a million dollars from a quantum computing company called Rigetti. (Read about the \"Quantum Advantage Prize\" here if you're interested.)\n", "\n", "And of course, the question of what else we could do with a good quantum computer is one of the most interesting and exciting questions in physics and computational science today." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#

Assignment Wrap-up

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Take a moment to fill out the following brief survey to complete your assignment." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##

Survey

" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import HTML\n", "HTML(\n", "\"\"\"\n", "\n", "\"\"\"\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##

Congrats, You're Finished!

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, you just need to submit this assignment by uploading it to the course Desire2Learn web page for today's submission folder. (Don't forget to add your name in the first cell.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

© Copyright 2019, Michigan State University Board of Trustees.

" ] } ], "metadata": { "kernelspec": { "display_name": "env", "language": "python", "name": "env" }, "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.6.8" } }, "nbformat": 4, "nbformat_minor": 2 }