diff --git a/docs/tutorials/educators/textbook_algorithms.ipynb b/docs/tutorials/educators/textbook_algorithms.ipynb index 16a27434e70..1f271172744 100644 --- a/docs/tutorials/educators/textbook_algorithms.ipynb +++ b/docs/tutorials/educators/textbook_algorithms.ipynb @@ -1,24 +1,16 @@ { "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "cedf868076a2" - }, - "source": [ - "##### Copyright 2020 The Cirq Developers" - ] - }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "cellView": "form", "id": "906e07f6e562" }, "outputs": [], "source": [ - "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n", + "#@title Copyright 2020 The Cirq Developers\n", + "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", @@ -73,7 +65,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": { "id": "pPMSHs4HQfSR" }, @@ -84,18 +76,18 @@ "except ImportError:\n", " print(\"installing cirq...\")\n", " !pip install cirq --quiet\n", + " import cirq\n", " print(\"installed cirq.\")" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "id": "57aaba33f657" }, "outputs": [], "source": [ - "import cirq\n", "import random\n", "import matplotlib.pyplot as plt\n", "import numpy as np" @@ -125,7 +117,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": { "id": "Ex8ka640a5xN" }, @@ -171,25 +163,11 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "id": "023602d016d8" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Teleportation circuit:\n", - "\n", - "Alice: ─────H────────@───X───────M───@───────\n", - " │ │ │ │\n", - "Bob: ────────────────X───┼───────┼───X───@───\n", - " │ │ │\n", - "Message: ───X^0.25───────@───H───M───────@───\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Visualize the teleportation circuit.\"\"\"\n", "# Gate to put the message qubit in some state to send.\n", @@ -212,20 +190,11 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": { "id": "d18db1bc5fb2" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Bloch vector of message qubit:\n", - "[ 0. -0.707 0.707]\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Display the Bloch vector of the message qubit.\"\"\"\n", "message = cirq.Circuit(gate.on(cirq.NamedQubit(\"Message\"))).final_state_vector()\n", @@ -245,20 +214,11 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": { "id": "4303441fdb1f" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Bloch vector of Bob's qubit:\n", - "[ 0. -0.707 0.707]\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Simulate the teleportation circuit and get the final state of Bob's qubit.\"\"\"\n", "# Get a simulator.\n", @@ -409,7 +369,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "id": "Fu0wP9sLG94Z" }, @@ -444,7 +404,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": { "id": "CtDX3krz87eC" }, @@ -471,27 +431,11 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": { "id": "nhbBPpf9GiHO" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " ┌───────┐ ┌────────────┐ ┌───────┐\n", - "0: ───H───@────────@───────────@───────────────────────────────────────\n", - " │ │ │\n", - "1: ───────@^0.5────┼─────H─────┼──────@─────────@──────────────────────\n", - " │ │ │ │\n", - "2: ────────────────@^0.25──────┼──────@^0.5─────┼─────H────@───────────\n", - " │ │ │\n", - "3: ────────────────────────────@^(1/8)──────────@^0.25─────@^0.5───H───\n", - " └───────┘ └────────────┘ └───────┘\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Visually check the QFT circuit.\"\"\"\n", "qubits = cirq.LineQubit.range(4)\n", @@ -519,25 +463,11 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": { "id": "725d3830c29c" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0: ───qft[norev]───\n", - " │\n", - "1: ───#2───────────\n", - " │\n", - "2: ───#3───────────\n", - " │\n", - "3: ───#4───────────\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Use the built-in QFT in Cirq.\"\"\"\n", "qft_operation = cirq.qft(*qubits, without_reverse=True)\n", @@ -556,7 +486,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": { "id": "i3Ir6kjmDqtt" }, @@ -586,7 +516,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": { "id": "5bcdd1a76fa2" }, @@ -621,7 +551,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": { "id": "d1c6a6a99bf7" }, @@ -648,27 +578,11 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": { "id": "778b0a8dc5ad" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " ┌────────┐ ┌──────────────┐ ┌────────┐\n", - "0: ──────────────────────────────@──────────────────@───────────@────────H───\n", - " │ │ │\n", - "1: ─────────────────@────────────┼───────@──────────┼──────H────@^-0.5───────\n", - " │ │ │ │\n", - "2: ───────@─────────┼──────H─────┼───────@^-0.5─────@^-0.25──────────────────\n", - " │ │ │\n", - "3: ───H───@^-0.5────@^-0.25──────@^(-1/8)────────────────────────────────────\n", - " └────────┘ └──────────────┘ └────────┘\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Visually check the inverse QFT circuit.\"\"\"\n", "qubits = cirq.LineQubit.range(4)\n", @@ -696,25 +610,11 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": { "id": "c26fb1937ea5" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0: ───qft[norev]^-1───\n", - " │\n", - "1: ───#2──────────────\n", - " │\n", - "2: ───#3──────────────\n", - " │\n", - "3: ───#4──────────────\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Use the built-in inverse QFT in Cirq.\"\"\"\n", "iqft_operation = cirq.qft(*qubits, inverse=True, without_reverse=True)\n", @@ -733,7 +633,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": { "id": "7ad3bf5b7d38" }, @@ -776,13 +676,13 @@ "id": "_15iEUy5Rk1o" }, "source": [ - "Suppose we have a unitary operator $U$ with eigenvactor $|\\psi\\rangle$ and eigenvalue $\\exp(2\\pi i \\theta)$. (Every eigenvalue of a unitary can be written this way.) Our objective is to get an $n$-bit approximation to $\\theta$. The first step is to construct the state\n", + "Suppose we have a unitary operator $U$ with eigenvector $|\\psi\\rangle$ and eigenvalue $\\exp(2\\pi i \\theta)$. (Every eigenvalue of a unitary can be written this way.) Our objective is to get an $n$-bit approximation to $\\theta$. The first step is to construct the state\n", "\n", "$$\n", "|\\Phi\\rangle = \\frac{1}{2^{n/2}}\\sum_{y=0}^{2^{n-1}} e^{2\\pi i y \\theta}|y\\rangle.\n", "$$\n", "\n", - "This looks very similar to the output of the QFT applied to the state $|2^n\\theta\\rangle$, except for the fact that $2^n\\theta$ may not be an integer. If $2^n\\theta$ *were* an integer, then we would apply the inverse QFT and measure the qubits to read off the binary representation of $2^n\\theta$. Even if $2^n\\theta$ is not an integer, we can still perform the same procedure and the result will be a sequence of bits that, with high probility, gives an $n$-bit approximation to $\\theta$. We just have to repeat the procedure a few times to be sure of the answer." + "This looks very similar to the output of the QFT applied to the state $|2^n\\theta\\rangle$, except for the fact that $2^n\\theta$ may not be an integer. If $2^n\\theta$ *were* an integer, then we would apply the inverse QFT and measure the qubits to read off the binary representation of $2^n\\theta$. Even if $2^n\\theta$ is not an integer, we can still perform the same procedure and the result will be a sequence of bits that, with high probability, gives an $n$-bit approximation to $\\theta$. We just have to repeat the procedure a few times to be sure of the answer." ] }, { @@ -791,7 +691,7 @@ "id": "sypcpUzLTxRK" }, "source": [ - "Since we've already constructed the inverse QFT, all we really have to do is figure out how to construct the state $|\\Phi\\rangle$. This is accomplished by the first part of the circuit picutred above. We begin by applying $H^{\\otimes n}$ to the state $|0\\rangle$, creating an equal superposition over all basis states:\n", + "Since we've already constructed the inverse QFT, all we really have to do is figure out how to construct the state $|\\Phi\\rangle$. This is accomplished by the first part of the circuit pictured above. We begin by applying $H^{\\otimes n}$ to the state $|0\\rangle$, creating an equal superposition over all basis states:\n", "\n", "$$\n", "H^{\\otimes n} |0\\rangle = \\frac{1}{2^{n/2}}\\sum_{y=0}^{2^n-1}|y\\rangle.\n", @@ -813,7 +713,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": { "id": "856ededbc425" }, @@ -842,25 +742,11 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": { "id": "OIN8QfUeJyI9" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0: ───H───@──────────────────────────────\n", - " │\n", - "1: ───H───┼──────────@───────────────────\n", - " │ │\n", - "2: ───H───┼──────────┼─────────@─────────\n", - " │ │ │\n", - "u: ───────Z^-0.128───Z^0.936───Z^0.468───\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Build the first part of the circuit for phase estimation.\"\"\"\n", "# Get qubits for the phase estimation circuit.\n", @@ -887,27 +773,11 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": { "id": "8KCn-gjxM2H9" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " ┌────────┐\n", - "0: ───H───@──────────H─────────@──────────@────────────────────────M('m')───\n", - " │ │ │ │\n", - "1: ───H───┼──────────@─────────@^-0.5─────┼──────H────@────────────M────────\n", - " │ │ │ │ │\n", - "2: ───H───┼──────────┼─────────@──────────@^-0.25─────@^-0.5───H───M────────\n", - " │ │ │\n", - "u: ───────Z^-0.128───Z^0.936───Z^0.468──────────────────────────────────────\n", - " └────────┘\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Build the last part of the circuit (inverse QFT) for phase estimation.\"\"\"\n", "# Do the inverse QFT.\n", @@ -924,32 +794,16 @@ "id": "smlXIG1QyPyR" }, "source": [ - "The initial state for `u_bit` is the $|0\\rangle$ state, but the phase for this state is trivial with the operator we chose. Inserting a Pauli $X$ operator at the begining of the circuit changes this to the $|1\\rangle$ state, which has the nontrivial $\\theta$ phase. " + "The initial state for `u_bit` is the $|0\\rangle$ state, but the phase for this state is trivial with the operator we chose. Inserting a Pauli $X$ operator at the beginning of the circuit changes this to the $|1\\rangle$ state, which has the nontrivial $\\theta$ phase. " ] }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": { "id": "g_rNMrkXPJ0R" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " ┌────────┐\n", - "0: ───H───@──────────H─────────@──────────@────────────────────────M('m')───\n", - " │ │ │ │\n", - "1: ───H───┼──────────@─────────@^-0.5─────┼──────H────@────────────M────────\n", - " │ │ │ │ │\n", - "2: ───H───┼──────────┼─────────@──────────@^-0.25─────@^-0.5───H───M────────\n", - " │ │ │\n", - "u: ───X───Z^-0.128───Z^0.936───Z^0.468──────────────────────────────────────\n", - " └────────┘\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Set the input state of the eigenvalue register.\"\"\"\n", "# Add gate to change initial state to |1>.\n", @@ -964,7 +818,7 @@ "id": "j2HIBKbEy7gV" }, "source": [ - "Now we can intstantiate a simulator and make measurements of the estimation qubits. Let the values of these measured qubits be $a_j \\in \\{0, 1\\}$. Then our $n$-bit approximation for $\\theta$ is given by\n", + "Now we can instantiate a simulator and make measurements of the estimation qubits. Let the values of these measured qubits be $a_j \\in \\{0, 1\\}$. Then our $n$-bit approximation for $\\theta$ is given by\n", "\n", "$$\n", "\\theta \\approx \\sum_{j=0}^n a_j2^{-j}.\n", @@ -975,19 +829,11 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": { "id": "-pE7CC_uPfq2" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[0.25 0.25 0.25 0.25 0.25 0.25 0.25 0.25 0.25 0.25]\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Simulate the circuit and convert from measured bit values to estimated θ values.\"\"\"\n", "# Simulate the circuit.\n", @@ -1005,7 +851,7 @@ "id": "PMke93CrzezN" }, "source": [ - "When `n_bits` is small, we don't get a very accurate estimate. To test the accuracy of the estimate vs. `n_bits`, let's pack all this up into a single function that lets us specify $\\theta$, the number of bits of of accuracy we want in our approximation, and the number of repetitions of the algorithm to perform. For future purposes, let's also include an argument for the gate which acts on `u_bit` at the start of the circuit to prepare the eigenstate." + "When `n_bits` is small, we don't get a very accurate estimate. To test the accuracy of the estimate vs. `n_bits`, let's pack all this up into a single function that lets us specify $\\theta$, the number of bits of accuracy we want in our approximation, and the number of repetitions of the algorithm to perform. For future purposes, let's also include an argument for the gate which acts on `u_bit` at the start of the circuit to prepare the eigenstate." ] }, { @@ -1028,7 +874,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "metadata": { "id": "t3EYxglfpgbh" }, @@ -1046,7 +892,7 @@ " # Your code here!\n", " # ...\n", " \n", - " # Gate to choose initial state for the u_bit. Placing X here chooses the |1> state.\n", + " # Gate to choose the initial state for the u_bit. Placing X here chooses the |1> state.\n", " phase_estimator.insert(0, prepare_eigenstate_gate.on(u_bit))\n", " \n", " # You code here!\n", @@ -1075,7 +921,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "metadata": { "id": "TXxJ_ZjeWFqy" }, @@ -1102,7 +948,7 @@ " # Add measurements.\n", " phase_estimator.append(cirq.measure(*qubits, key='m'))\n", "\n", - " # Gate to choose initial state for the u_bit. Placing X here chooses the |1> state.\n", + " # Gate to choose the initial state for the u_bit. Placing X here chooses the |1> state.\n", " phase_estimator.insert(0, prepare_eigenstate_gate.on(u_bit))\n", "\n", " # Code to simulate measurements\n", @@ -1126,7 +972,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": { "id": "5749cf9469da" }, @@ -1157,22 +1003,11 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "metadata": { "id": "a8abf4de37bf" }, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "\"\"\"Plot the results.\"\"\"\n", "plt.style.use(\"seaborn-whitegrid\")\n", @@ -1226,19 +1061,11 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "metadata": { "id": "3790a1ba19ac" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[0. 0.125 0.125 0.125 0.125 0.125 0.125 0. 0.125 0. ]\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Run phase estimation without starting in an eigenstate.\"\"\"\n", "# Value of theta.\n", @@ -1258,7 +1085,7 @@ "id": "wzTnTpC2oL79" }, "source": [ - "Notice that roughly half of the measurements yielded the estimate $0$ (which corresponds to the eigenvaule $1$) and roughly half yield the estimate of `theta`. This is expected because the initial state $|+\\rangle$ is an equal superposition of the two eigenstates of $U = Z^{2 \\theta}$." + "Notice that roughly half of the measurements yielded the estimate $0$ (which corresponds to the eigenvalue $1$) and roughly half yield the estimate of `theta`. This is expected because the initial state $|+\\rangle$ is an equal superposition of the two eigenstates of $U = Z^{2 \\theta}$." ] }, { @@ -1300,7 +1127,7 @@ "source": [ "### Exercise: QFT and phase estimation with adjacency constraints\n", "\n", - "Often on a real machine we can't execute two-qubit gates between qubits that are not right next to each other. You'll have noticed that the circuits we defined above involves connections between many different pairs of qubits, which will likely not all be near each other when we try to run the circuit on an actual chip. See if you can modify the examples we went through above in such a way that Cirq validates them for use on the Foxtail or Bristlecone chips." + "Often on a real machine we can't execute two-qubit gates between qubits that are not right next to each other. You'll have noticed that the circuits we defined above involves connections between many different pairs of qubits, which will likely not all be near each other when we try to run the circuit on an actual chip. See if you can modify the examples we went through above in such a way that Cirq validates them for use on the Sycamore chip." ] }, { @@ -1324,7 +1151,7 @@ "f(x) = 1\\text{ if } x = x',~~~~ f(x) = 0 \\text{ if } x \\neq x'\n", "$$ \n", "\n", - "to find such a bitsting $x'$. Grover's algorithm uses $O(\\sqrt{N}$) operations and $O(N\\, \\log N$) gates and succeeds with probability $p \\geq 2/3$." + "to find such a bitstring $x'$. Grover's algorithm uses $O(\\sqrt{N}$) operations and $O(N\\, \\log N$) gates and succeeds with probability $p \\geq 2/3$." ] }, { @@ -1340,7 +1167,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": null, "metadata": { "id": "dae0e3e0d1bf" }, @@ -1366,7 +1193,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": null, "metadata": { "id": "0425db9fa9b0" }, @@ -1398,7 +1225,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": null, "metadata": { "id": "6a8deed363e0" }, @@ -1443,19 +1270,11 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": null, "metadata": { "id": "033b376b387d" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Marked bitstring: [1, 1]\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Select a 'marked' bitstring x' at random.\"\"\"\n", "xprime = [random.randint(0, 1) for _ in range(nqubits)]\n", @@ -1473,24 +1292,11 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": null, "metadata": { "id": "gaUMhMV0aaVB" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Circuit for Grover's algorithm:\n", - "0: ─────────H───────@───H───X───────@───X───H───────M('result')───\n", - " │ │ │\n", - "1: ─────────H───────@───H───X───H───X───H───X───H───M─────────────\n", - " │\n", - "Ancilla: ───X───H───X─────────────────────────────────────────────\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Create the circuit for Grover's algorithm.\"\"\"\n", "# Make oracle (black box)\n", @@ -1513,23 +1319,11 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": null, "metadata": { "id": "18c803b9ca8b" }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Sampled results:\n", - "Counter({'11': 10})\n", - "\n", - "Most common bitstring: 11\n", - "Found a match? True\n" - ] - } - ], + "outputs": [], "source": [ "\"\"\"Simulate the circuit for Grover's algorithm and check the output.\"\"\"\n", "# Helper function.\n",