diff --git a/examples/bernstein_vazirani_tutorial.ipynb b/examples/bernstein_vazirani_tutorial.ipynb new file mode 100644 index 00000000..0e9dc981 --- /dev/null +++ b/examples/bernstein_vazirani_tutorial.ipynb @@ -0,0 +1,302 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Bernstein-Varzirani Algorithm\n", + "The Bernstein-Varzirani algorithm solves the following problem:\n", + "1. Given an n-bit secret number x\n", + "2. There is an oracle holding the secret key that one can query with a number y, and the oracle will return $x \\bullet y$, the bit-wise dot product modulo 2 of the two numbers. For example, given a 4-bit secret number $x=13$ with binary representation 1101 and $y=15$ with binary representation 1111, then $x \\bullet y =$ 3 mod 2, which is 1\n", + "3. The question is: how many oracle queries does one need to figure out x?\n", + "\n", + "With the classical approach, if we query the oracle with 1, 2(10), 4(100) and 8(1000), then we can figure out each bit of the secret key and thus we need four queries. For a general n-bit number, we need n queries. Surprisingly, in the quantum computing paradigm, the Bernstein-Varzirani algorithm needs only one measurement, regardless of the size of the secret number" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import projectq\n", + "from projectq.backends import CircuitDrawer\n", + "from projectq.ops import H, Z, All, Measure, Barrier\n", + "\n", + "from pathlib import Path" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "n = 3 #No. of qubits" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The classical approach" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def query_oracle(y):\n", + " \"\"\"\n", + " The oracle returns the bit-wise dot product modulo 2 \n", + " of the secret key and y\n", + " \"\"\"\n", + " x = 6 #secret key\n", + " s = bin(x & y).count('1') % 2\n", + " \n", + " return s" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Secret key is 6 after 3 tries\n" + ] + } + ], + "source": [ + "b = ''.join([str(query_oracle(2**(k))) for k in reversed(range(n))])\n", + "print(\"Secret key is {} after {} tries\".format(int(b, 2), n))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The quantum computing approach\n", + "There are five steps in the Bernstein-Varzirani circuit construction:\n", + "1. Initialize all qubits to 0 (This is the default value anyway)\n", + "2. Apply Hadamard transform to all qubits\n", + "3. Implement the oracle \n", + "4. Apply Hadamard transform to all qubits\n", + "5. Measure the circuit\n", + "\n", + "The workings of the Bernstein-Varzirani algorithm can only be understood by working through the mathematics. After step 2, the application of the Hadamard transform to all qubits results in\n", + "$$\\begin{align} H^{\\otimes n} |0\\rangle = \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} | y \\rangle \\end{align}$$\n", + "where $N = 2^n$\n", + "\n", + "The oracle seeks to implement the following operation in step 3:\n", + "$$\\begin{align} \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} | y \\rangle \\rightarrow \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} (-1)^{x \\bullet y} | y \\rangle \\end{align}$$\n", + "The oracle effectively multiplies each superposition state $|y \\rangle$ with -1 raised to the power of $x \\bullet y$, the bit-wise inner product modulo 2. But why does the oracle implement this operation?\n", + "\n", + "Using the identity (proof given below)\n", + "$$\\begin{align} H^{\\otimes n} |x\\rangle = \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} (-1)^{x \\bullet y} | y \\rangle \\end{align}$$\n", + "If we further apply another Hadamard transform to all qubits in step 4, then $$ H^{\\otimes n} H^{\\otimes n} |x\\rangle = H^{\\otimes n} \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} (-1)^{x \\bullet y} | y \\rangle $$\n", + "i.e. $$ |x\\rangle = H^{\\otimes n} \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} (-1)^{x \\bullet y} | y \\rangle $$\n", + "since the Hadamard transform is symmetric and unitary (meaning that the transform is its own inverse). Thus measuring the circuit in step 5 will give the secret key.\n", + "\n", + "Summarizing,\n", + "$$ H^{\\otimes n} |0\\rangle ^{\\otimes n} \\rightarrow \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} | y \\rangle \\rightarrow \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} (-1)^{x \\bullet y} | y \\rangle \\rightarrow H^{\\otimes n} \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} (-1)^{x \\bullet y} | y \\rangle = |x\\rangle$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### The oracle implementation\n", + "First note that in implementing\n", + "$$ \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} (-1)^{x \\bullet y} | y \\rangle = \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} (-1)^{(x_{n-1} y_{n-1} \\oplus \\ldots \\oplus x_0 y_0)} | y_{n-1}\\ldots y_0\\rangle $$\n", + "$$ = \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} (-1)^{x_{n-1} y_{n-1}} (-1)^{x_{n-2} y_{n-2}} \\ldots (-1)^{x_0 y_0}) | y_{n-1}\\ldots y_0\\rangle $$\n", + "the individual product ${x_{n-1} y_{n-1}, \\ldots, x_0 y_0}$ only needs to be evaluated for bits in x that are 1. \n", + "\n", + "For the bits in x that are 1, we only introduce a minus sign for the bits in y that are 1 i.e.\n", + "$ |0 \\rangle \\rightarrow |0 \\rangle$ and $ |1 \\rangle \\rightarrow -|1 \\rangle$. This is precisely what the Z gate does. Thus the oracle can be implemented as: if a bit in x is 1, apply the Z gate to the corresponding bit in y." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def make_bv_circuit(engine, n):\n", + " circuit = engine.allocate_qureg(n)\n", + " All(H) | circuit\n", + " Barrier | circuit\n", + " \n", + " # Oracle\n", + " x = 6 # secret key\n", + " for i in range(n):\n", + " if x & 1: # Only apply Z if the current bit of the secret key x is 1\n", + " Z | circuit[i]\n", + " x >>= 1 # Move the next bit to the 1 position\n", + " Barrier | circuit\n", + " \n", + " All(H) | circuit\n", + " All(Measure) | circuit\n", + " engine.flush()\n", + "\n", + " return circuit" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Draw circuit diagram" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "drawing_engine = CircuitDrawer()\n", + "main_engine = projectq.MainEngine(drawing_engine)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "circuit = make_bv_circuit(main_engine, n)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p = Path('diagram')\n", + "if not p.exists(): #if the diagram directory doesn't exist, create it\n", + " p.mkdir()\n", + "with open('diagram/bv.tex', 'w') as f:\n", + " latex = drawing_engine.get_latex() #get circuit diagram as latex\n", + " f.write(latex) \n", + "#Change the pdf scale to 1.8 from 0.8 to have better visual effect\n", + "!sed -i 's@tikzpicture\\}\\[scale=0.8@tikzpicture\\}\\[scale=1.8@g' diagram/bv.tex\n", + "!cd diagram; pdflatex bv.tex > /dev/null #convert tex to latex, piping to /dev/null to silent output \n", + "\n", + "#Wand package needed to convert pdf to image\n", + "from wand.image import Image as WImage\n", + "img = WImage(filename='diagram/bv.pdf')\n", + "img" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Measurement outcome: 110\n", + "Secret key: 6\n" + ] + } + ], + "source": [ + "main_engine = projectq.MainEngine()\n", + "circuit = make_bv_circuit(main_engine, n)\n", + "measurement = ''.join(str(int(c)) for c in reversed(circuit))\n", + "print('Measurement outcome:', measurement)\n", + "print('Secret key:', int(measurement, 2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Proof of the key identity" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\\begin{align} H^{\\otimes n} |x\\rangle = \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} (-1)^{x \\bullet y} | y \\rangle \\end{align}$$ where $ N = 2^n $ and the $ \\bullet$ operator denotes bitwise dot product modulo 2 i.e. $ x \\bullet y = x_0y_0 \\oplus x_1y_1 \\oplus \\ldots x_{N-1}y_{N-1}$ where $\\oplus$ denotes the sum modulo 2 operation or the XOR operation. We prove this identity by induction.\n", + "\n", + "Base case, n = 1:\n", + "$$ H |x_0\\rangle = \\frac{1}{\\sqrt{2}} (|0\\rangle + (-1)^{x_0}|1\\rangle) = \\frac{1}{\\sqrt{2}} \\sum_{y=0}^{1} (-1)^{x_0y} | y \\rangle$$\n", + "\n", + "Assuming n-1 (n > 1) is true i.e. $$ H^{\\otimes (n-1)} |x_{n-2} \\ldots x_0\\rangle = \\frac{1}{\\sqrt{2^{n-1}}} \\sum_{y=0}^{2^{n-1} - 1} (-1)^{(x_{n-2} \\ldots x_0) \\bullet (y_{n-2} \\ldots y_0)} | y \\rangle$$ \n", + "\n", + "$$ = \\frac{1}{\\sqrt{2^{n-1}}} \\sum_{y=0}^{2^{n-1} - 1} (-1)^{(x_{n-2} y_{n-2} \\oplus \\ldots \\oplus x_0 y_0)} | y \\rangle$$ \n", + "\n", + "where $y = y_{n-2} \\ldots y_0$ is the binary representation\n", + "\n", + "\n", + "Then $$ H^{\\otimes n} |x_{n-1} \\ldots x_0 \\rangle = \\frac{1}{\\sqrt{2}} (|0\\rangle + (-1)^{x_{n-1}}|1\\rangle) \\times \\frac{1}{\\sqrt{2^{n-1}}} \\sum_{y=0}^{2^{n-1} - 1} (-1)^{(x_{n-2} y_{n-2} \\oplus \\ldots \\oplus x_0 y_0)} | y \\rangle $$\n", + "\n", + "$$ \\begin{align} = \\frac{1}{\\sqrt{2^n}} \\sum_{y=0}^{2^{n-1} - 1} (-1)^{(x_{n-2} y_{n-2} \\oplus \\ldots \\oplus x_0 y_0)} |0\\rangle| y \\rangle + \\frac{1}{\\sqrt{2^n}} \\sum_{y=0}^{2^{n-1} - 1} (-1)^{x_{n-1}} (-1)^{(x_{n-2} y_{n-2} \\oplus \\ldots \\oplus x_0 y_0)} |1\\rangle| y \\rangle \\end{align} $$\n", + "\n", + "$$ \\begin{align} = \\frac{1}{\\sqrt{2^n}} \\sum_{y=0}^{2^{n-1} - 1} (-1)^{(x_{n-1}0 \\oplus x_{n-2}y_{n-2} \\oplus \\ldots \\oplus x_0y_0)} | y \\rangle + \\frac{1}{\\sqrt{2^n}} \\sum_{y=2^{n-1}}^{2^{n} - 1} (-1)^{(x_{n-1}1 \\oplus x_{n-2}y_{n-2}\\oplus \\ldots \\oplus x_0y_0)} | y \\rangle \\end{align}$$\n", + "\n", + "$$ = \\frac{1}{\\sqrt{2^n}} \\sum_{y=0}^{2^{n-1} - 1} (-1)^{(x_{n-1}x_{n-2} \\ldots x_0) \\bullet (0y_{n-2} \\ldots y_0)} | y \\rangle + \\frac{1}{\\sqrt{2^n}} \\sum_{y=2^{n-1}}^{2^{n} - 1} (-1)^{(x_{n-1} \\ldots x_0) \\bullet (1y_{{n}-2} \\ldots y_0)} | y \\rangle $$\n", + "\n", + "$$ = \\frac{1}{\\sqrt{2^{n}}} \\sum_{y=0}^{2^{n} - 1} (-1)^{(x_{n-1} \\ldots x_0) \\bullet (y_{n-1} \\ldots y_0)} | y \\rangle $$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "projectq", + "language": "python", + "name": "projectq" + }, + "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 +} diff --git a/examples/quantum_teleportation.ipynb b/examples/quantum_teleportation.ipynb new file mode 100644 index 00000000..80c560ab --- /dev/null +++ b/examples/quantum_teleportation.ipynb @@ -0,0 +1,314 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Quantum Teleportation\n", + "The quantum teleportation protocol was first proposed in [1]. Suppose Alice has the state $\\vert \\psi \\rangle$ and is trying to send $\\vert \\psi \\rangle$ to Bob. The no cloning theorem [2] says that $\\vert \\psi \\rangle$ cannot be sent via copying. The proposed quantum teleportation algorithm serves to \"teleport\" $\\vert \\psi \\rangle$ from Alice to Bob, meaning that Alice's copy is destroyed when $\\vert \\psi \\rangle$ has been sent to Bob. Destroy here means the destruction of information, not the physical qubit.\n", + "\n", + "This jupyter notebook explains in greater detail the implementation in teleport.py. In the quantum teleportation protocol, there are three qubits involved:\n", + "1. Qubit $\\psi$ held by Alice, to be transmitted to Bob\n", + "2. Alice's working qubit $b_1$\n", + "3. Bob's qubit $b_2$, which will hold the teleported $\\psi$\n", + "\n", + "The steps involved in the quantum teleportation protocol are as follow: \n", + "1. Entangle Alice's $b_1$ with Bob's $b_2$, creating a bell pair\n", + "2. Apply CNOT (conditional NOT) on $b_1$, with $\\psi$ as the controlling bit\n", + "3. Put $\\psi$ into superposition using the Hadamard operator\n", + "4. Alice measures $\\psi$ and $b_1$. The measured results are transmitted via classical channels to Bob\n", + "5. Depending on the measured results received, Bob will choose to do none/one/both of the X and Z unitary operations on $b_2$\n", + "\n", + "Bob's $b_2$ now holds the teleported state $\\psi$" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import projectq\n", + "from projectq.backends import CircuitDrawer\n", + "from projectq.ops import H, Rz, CNOT, X, Z, Measure\n", + "from projectq.meta import Dagger, Control\n", + "\n", + "from pathlib import Path" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The following two functions are lifted from teleport.py\n", + "The create_state() function sets up the $\\psi$ state. In the function, $b_1$ and $b_2$ are created and initialized to $\\vert 0 \\rangle$. After the H | b1 operation, $b_1 = \\frac{1}{\\sqrt{2}} \\left( \\vert 0 \\rangle + \\vert 1 \\rangle \\right)$. After the CNOT | (b1, b2) operation, b1 and b2 becomes the entangled Bell pair $\\frac{1}{\\sqrt{2}} \\left( \\vert 00 \\rangle + \\vert 11 \\rangle \\right)$" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# define our state-creation routine, which transforms a |0> to the state\n", + "# we would like to send. Bob can then try to uncompute it and, if he\n", + "# arrives back at |0>, we know that the teleportation worked.\n", + "def create_state(eng, qb):\n", + " H | qb\n", + " Rz(1.21) | qb\n", + " \n", + "def create_bell_pair(eng):\n", + " \"\"\"\n", + " Returns a Bell-pair (two qubits in state :math:`|A\\rangle \\otimes |B\n", + " \\rangle = \\frac 1{\\sqrt 2} \\left( |0\\rangle\\otimes|0\\rangle + |1\\rangle\n", + " \\otimes|1\\rangle \\right)`).\n", + "\n", + " Args:\n", + " eng (MainEngine): MainEngine from which to allocate the qubits.\n", + "\n", + " Returns:\n", + " bell_pair (tuple): The Bell-pair.\n", + " \"\"\"\n", + " b1 = eng.allocate_qubit()\n", + " b2 = eng.allocate_qubit()\n", + "\n", + " H | b1\n", + " CNOT | (b1, b2)\n", + "\n", + " return b1, b2" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def make_teleportation_circuit(eng, verbose=True):\n", + " # Step 1: make a Bell-pair\n", + " b1, b2 = create_bell_pair(eng) \n", + " \n", + " # Alice creates a nice state to send\n", + " psi = eng.allocate_qubit()\n", + " if verbose:\n", + " print(\"Alice is creating her state from scratch, i.e., |0>.\")\n", + " create_state(eng, psi) \n", + " \n", + " # Implements step 2 of the protocol\n", + " CNOT | (psi, b1)\n", + " if verbose:\n", + " print(\"Alice entangled her qubit with her share of the Bell-pair.\")\n", + "\n", + " # Step 3 of the protocol, putting psi into superposition\n", + " H | psi \n", + " \n", + " # Step 4 of the protocol: measure psi and b1, whose outcomes\n", + " # which will be communicated via classical channels to Bob\n", + " Measure | psi\n", + " Measure | b1 \n", + " \n", + " msg_to_bob = [int(psi), int(b1)]\n", + " if verbose:\n", + " print(\"Alice is sending the message {} to Bob.\".format(msg_to_bob)) \n", + "\n", + " # Sstep 5 of the protocol. After receiving the measured results, \n", + " # Bob will proceed to apply the necessary operations\n", + " with Control(eng, b1):\n", + " X | b2\n", + " with Control(eng, psi):\n", + " Z | b2 \n", + "\n", + " # Now Bob's b2 holds the psi state\n", + " return psi, b1, b2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Visualize the quantum teleportation circuit\n", + "Contains the same circuit drawing function as teleport_circuit.py. Additional code serves to draw the circuit in jupyter notebook" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "drawing_engine = CircuitDrawer()\n", + "locations = {0: 1, 1: 2, 2: 0}\n", + "drawing_engine.set_qubit_locations(locations)\n", + "eng = projectq.MainEngine(drawing_engine)\n", + "ψ, b1, b2 = make_teleportation_circuit(eng, False)\n", + "eng.flush()\n", + "\n", + "p = Path('diagram')\n", + "if not p.exists(): #if the diagram directory doesn't exist, create it\n", + " p.mkdir()\n", + "with open('diagram/teleport.tex', 'w') as f:\n", + " latex = drawing_engine.get_latex() #get circuit diagram as latex\n", + " f.write(latex) \n", + "#Change the pdf scale to 1.8 from 0.8 to have better visual effect\n", + "!sed -i 's@tikzpicture\\}\\[scale=0.8@tikzpicture\\}\\[scale=2.8@g' diagram/teleport.tex\n", + "!cd diagram; pdflatex teleport.tex > /dev/null #convert tex to latex, piping to /dev/null to silent output \n", + "\n", + "#Wand package needed to convert pdf to image\n", + "from wand.image import Image as WImage\n", + "img = WImage(filename='diagram/teleport.pdf')\n", + "img" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "#Uncompute b2 so that b2 returns to a computational state and can be safely deleted, \n", + "#otherwise an error will be thrown\n", + "with Dagger(eng):\n", + " create_state(eng, b2)\n", + "del b2\n", + "eng.flush() " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run the quantum teleportation circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Alice is creating her state from scratch, i.e., |0>.\n", + "Alice entangled her qubit with her share of the Bell-pair.\n", + "Alice is sending the message [0, 0] to Bob.\n" + ] + } + ], + "source": [ + "main_eng = projectq.MainEngine()\n", + "ψ, b1, b2 = make_teleportation_circuit(eng)\n", + "\n", + "#Verify that psi has indeed been teleported to b2\n", + "with Dagger(eng):\n", + " create_state(eng, b2)\n", + "del b2\n", + "eng.flush() " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that after getting $\\psi, b_1, b_2$ from calling make_teleportation_circuit(eng), we still need to verify that $b_2$ is in the teleported state $\\psi$. Using ProjectQ's Dagger construct, we uncompute $b_2$ by reversing the create state operation. If the teleportation is successful, then the uncompute operation should return $b_2$ to its original $\\vert 0 \\rangle$ state. Therefore deleting $b_2$ should go smoothly. If the teleportation is unsuccessful, then the supposed uncompute operation will not return $b_2$ to its original $\\vert 0 \\rangle$ state. As explained in simulator_tutorial.ipynb, deletion will throw an error." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Underlying mathematics" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In step 1 of the protocol, Alice's $b_1$ and Bob's $b_2$ entangled states are described by $\\frac{1}{\\sqrt{2}} \\left( \\vert 00 \\rangle + \\vert 11 \\rangle \\right)$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Suppose $\\psi$ is in the arbitrary state $\\psi = \\alpha \\vert 0 \\rangle + \\beta \\vert 1 \\rangle$ after calling create_state(). In step 2 of the protocol, after applying CNOT on $b_1$ with $\\psi$ as the controlling bit,\n", + "\n", + "The joint state of $\\psi$ and $b_1$ is now described by \n", + "$$ \\frac{1}{\\sqrt{2}} \\left[ \\alpha \\vert 0 \\rangle \\vert 00 \\rangle + \\alpha \\vert 0 \\rangle \\vert 11 \\rangle + \\beta \\vert 1\\rangle \\vert 10 \\rangle + \\beta \\vert 1 \\rangle \\vert 01 \\rangle \\right]$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In step 3 of the protocol, after applying the Hadamard operation on $\\psi$, $\\psi \\rightarrow \\frac{1}{\\sqrt{2}} \\left[ \\alpha \\left( \\vert 0 \\rangle + \\vert 1 \\rangle \\right) + \\beta \\left( \\vert 0 \\rangle - \\vert 1 \\rangle \\right) \\right]$ \n", + "\n", + "The full state (of $\\psi$, $b_1$ and $b_2$) now becomes\n", + "$$ \\frac{1}{\\sqrt{2}} \\left[ \\alpha \\left( \\vert 0 \\rangle + \\vert 1 \\rangle \\right) \\vert 00 \\rangle + \\alpha \\left( \\vert 0 \\rangle + \\vert 1 \\rangle \\right) \\vert 11 \\rangle + \\beta \\left( \\vert 0 \\rangle - \\vert 1 \\rangle \\right) \\vert 10 \\rangle + \\beta \\left( \\vert 0 \\rangle - \\vert 1 \\rangle \\right) \\vert \\rangle 01 \\rangle \\right]$$\n", + "\n", + "$$ = \\frac{1}{\\sqrt{2}} \\left[ \\alpha \\vert 000 \\rangle + \\alpha \\vert 100 \\rangle + \\alpha \\vert 011 \\rangle + \\alpha \\vert 111 \\rangle + \\beta \\vert 010 \\rangle - \\beta \\vert 110 \\rangle + \\beta \\vert 001 \\rangle - \\beta \\vert 101 \\rangle \\right] $$\n", + "\n", + "$$ = \\frac{1}{{2}} \\left[ \\left(\\alpha \\vert 000 \\rangle + \\beta \\vert 001 \\rangle \\right) + \\left(\\alpha \\vert 011 \\rangle + \\beta \\vert 010 \\rangle \\right) + \\left(\\alpha \\vert 100 \\rangle - \\beta \\vert 101 \\rangle \\right) + \\left(\\alpha \\vert 111 \\rangle - \\beta \\vert 110 \\rangle \\right) \\right]$$\n", + "\n", + "$$ = \\frac{1}{{2}} \\left[ \\vert 00 \\rangle \\left(\\alpha \\vert 0 \\rangle + \\beta \\vert 1 \\rangle \\right) + \\vert 01 \\rangle \\left( \\beta \\vert 0 \\rangle + \\alpha \\vert 1 \\rangle \\right) + \\vert 10 \\rangle \\left( \\alpha \\vert 0 \\rangle - \\beta \\vert 1 \\rangle \\right) + \\vert 11 \\rangle \\left( \\alpha \\vert 1 \\rangle - \\beta \\vert 0 \\rangle \\right) \\right]$$\n", + "\n", + "$$ = \\frac{1}{{2}} \\left[ \\vert 00 \\rangle \\vert \\psi \\rangle + \\vert 01 \\rangle X \\vert \\psi \\rangle + \\vert 10 \\rangle Z \\vert \\psi \\rangle + \\vert 11 \\rangle XZ \\vert \\psi \\rangle \\right]$$\n", + "\n", + "In step 4 of the protocol, the measured $\\psi$ and $b_1$ will be one of the four possibilities: $\\{\\vert 00 \\rangle, \\vert 01 \\rangle, \\vert 10 \\rangle, \\vert 11 \\rangle \\}$. The measured results are transmitted to Bob via classical channels.\n", + "\n", + "We see that Bob is getting $\\psi$ up to some unitary transform. For instance, if $\\psi$ and Alice's $b_1$ are measured to be $\\vert 01 \\rangle$, then Bob is getting $X \\vert \\psi \\rangle$. In step 5 of the protocol, Bob will proceed to apply the following operations depending on what he receives from Alice:\n", + "\n", + "1. $\\vert 00 \\rangle$. Bob does nothing and gets $\\psi$\n", + "2. $\\vert 01 \\rangle$. Bob applies the X operator and gets $\\psi$\n", + "3. $\\vert 10 \\rangle$. Bob applies the Z operator and gets $\\psi$\n", + "4. $\\vert 11 \\rangle$. Bob applies the ZX operator and gets $\\psi$\n", + "\n", + "Both X and Z are unitary and symmetrical, meaning that applying these operations twice will result in identity and hence the above steps." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# References\n", + "\n", + "1. Charles H. Bennett, Gilles Brassard, Claude Crépeau, Richard Jozsa, Asher Peres, and William K. Wootters Phys. Rev. Lett. 70, 1895 – Published 29 March 1993\n", + "\n", + "2. William K Wootters and Wojciech H Zurek. A single quantum cannot be cloned. Nature, 299(5886):802–803, 1982" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "projectq", + "language": "python", + "name": "projectq" + }, + "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 +}