Created
September 13, 2020 11:58
-
-
Save csferrie/fd97d7fc037110af21b5a26c7f74609e to your computer and use it in GitHub Desktop.
Superdense coding and teleportation in Cirq
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"nbformat": 4, | |
"nbformat_minor": 0, | |
"metadata": { | |
"colab": { | |
"name": "Superdense coding and teleportation in Cirq", | |
"provenance": [], | |
"collapsed_sections": [], | |
"authorship_tag": "ABX9TyPbmxRn1Y4EacORjavzzM3G", | |
"include_colab_link": true | |
}, | |
"kernelspec": { | |
"name": "python3", | |
"display_name": "Python 3" | |
} | |
}, | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "view-in-github", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"<a href=\"https://colab.research.google.com/gist/csferrie/fd97d7fc037110af21b5a26c7f74609e/superdense-coding-and-teleportation-in-cirq.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "xV7VUIMwH2IT", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"# Superdense coding and teleportation in Cirq\n", | |
"\n", | |
"This exercise is part of [Lab 6](https://medium.com/@csferrie/superdense-coding-and-quantum-teleportation-in-three-quantum-programming-languages-3fe7032d1dbc) of [Introduction to Quantum Computing](https://medium.com/@csferrie/introduction-to-quantum-computing-df9e1182a831).\n", | |
"\n", | |
"This notebook provides implementation of superdense coding and teleportation in the [Cirq](https://cirq.readthedocs.io/en/stable/) quantum programming language." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "zp0yynx1I9Jl", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"# Cirq installation\n", | |
"\n", | |
"The first step is to install cirq. Installation instructions are available in the documentation for Cirq here: https://cirq.readthedocs.io/en/stable/index.html." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "MFG2OUCoyJY1", | |
"colab_type": "code", | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 34 | |
}, | |
"outputId": "8a51cc1b-3e0e-4ac1-91e5-57c54a577536" | |
}, | |
"source": [ | |
"# install cirq\n", | |
"!pip install cirq --quiet" | |
], | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": [ | |
"\u001b[K |████████████████████████████████| 1.4MB 2.6MB/s \n", | |
"\u001b[?25h" | |
], | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "M7uLB5v1JtHm", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"Obviously we need to import cirq. But we will also need numpy later." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "zRiG_m_fTIRG", | |
"colab_type": "code", | |
"colab": {} | |
}, | |
"source": [ | |
"import cirq\n", | |
"import numpy as np" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "r1NMu4QBTTV2", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"# Superdense coding\n", | |
"\n", | |
"[Superdense coding](https://en.wikipedia.org/wiki/Superdense_coding) is a protocol that allows the tranmission of two classical bits of information using 1 qubit of information. \n", | |
"\n", | |
"This, the simplest implementation in Cirq, accompanies the [lecture](https://medium.com/@csferrie/my-first-quantum-protocol-de336d290322) on the same topic.\n", | |
"\n", | |
"Let's get started. The first thing Alice and Bob need to do is create entanglement.\n", | |
"\n", | |
"" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "lCK97MrEWMjn", | |
"colab_type": "code", | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 68 | |
}, | |
"outputId": "ef4f782a-270e-4e4a-cdd8-f37f0895702a" | |
}, | |
"source": [ | |
"# create two qubits\n", | |
"alice = cirq.NamedQubit('alice')\n", | |
"bob = cirq.NamedQubit('bob')\n", | |
"\n", | |
"# create cirquit\n", | |
"superdense = cirq.Circuit()\n", | |
"\n", | |
"# add your gates (aka \"moments\")\n", | |
"superdense.append([\n", | |
" cirq.H(alice),\n", | |
" cirq.CNOT(alice,bob)\n", | |
" ])\n", | |
"\n", | |
"print(superdense)" | |
], | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": [ | |
"alice: ───H───@───\n", | |
" │\n", | |
"bob: ─────────X───\n" | |
], | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "CFm4NQNbVMAa", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"Now Alice needs to encode her message. There are four possibilities. \n", | |
"\n", | |
"If Alice wants to send\n", | |
"* 00, she does nothing;\n", | |
"* 01, she performs an $X$ gate;\n", | |
"* 10, she performs a $Z$ gate;\n", | |
"* 11, she performs $XZ$.\n", | |
"\n", | |
"Let's say Alice choses 11. \n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "sCAKLdh3V26d", | |
"colab_type": "code", | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 68 | |
}, | |
"outputId": "f14bdc17-a6e9-422b-d4cf-ebd2ddc4bbb8" | |
}, | |
"source": [ | |
"superdense.append([\n", | |
" cirq.X(alice),\n", | |
" cirq.Z(alice)\n", | |
" ])\n", | |
"\n", | |
"print(superdense)" | |
], | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": [ | |
"alice: ───H───@───Z───\n", | |
" │\n", | |
"bob: ─────────X───────\n" | |
], | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "tsEySC0hWVN0", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"Now Alice sends her qubit to Bob. Bob unentangles them." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "4fg_HryHWdJN", | |
"colab_type": "code", | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 68 | |
}, | |
"outputId": "56474866-7035-473e-c656-23c8da4b2751" | |
}, | |
"source": [ | |
"superdense.append([\n", | |
" cirq.CNOT(alice,bob), \n", | |
" cirq.H(alice)\n", | |
" ])\n", | |
"\n", | |
"print(superdense)" | |
], | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": [ | |
"alice: ───H───@───Z───@───H───\n", | |
" │ │\n", | |
"bob: ─────────X───────X───────\n" | |
], | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "R2CSMU5gXQGk", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"Finally Bob measures both qubits." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "72XXxbakXTW6", | |
"colab_type": "code", | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 68 | |
}, | |
"outputId": "d1d3631f-a0b3-4b7a-b9ec-0100cce39998" | |
}, | |
"source": [ | |
"superdense.append(cirq.measure(alice, bob, key='received'))\n", | |
"\n", | |
"print(superdense)" | |
], | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": [ | |
"alice: ───H───@───Z───@───H───M('received')───\n", | |
" │ │ │\n", | |
"bob: ─────────X───────X───────M───────────────\n" | |
], | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "otFJsni1YnMW", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"Let's simulate this circuit." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "QiBXRNvKYCFg", | |
"colab_type": "code", | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 34 | |
}, | |
"outputId": "b758bae9-8a6c-40b1-bcfe-cd279c9e490f" | |
}, | |
"source": [ | |
"simulator = cirq.Simulator()\n", | |
"message = simulator.run(superdense, repetitions=1)\n", | |
"\n", | |
"print(message)" | |
], | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": [ | |
"received=1, 0\n" | |
], | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "jVofPW1XuIoP", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"Huzzah! It works. Now you try to create a better implementation that doesn't involve hard-coding Alice's message in." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"colab_type": "text", | |
"id": "-5vVz9psB-2l" | |
}, | |
"source": [ | |
"# Teleportation\n", | |
"\n", | |
"[Quantum teleportation](https://en.wikipedia.org/wiki/Quantum_teleportation) is a protocol that allows the tranmission of 1 qubit of information using two classical bits of information.\n", | |
"\n", | |
"This, the simplest implementation in cirq, accompanies the [lecture](https://medium.com/@csferrie/my-first-quantum-protocol-de336d290322) on the same topic.\n", | |
"\n", | |
"\n", | |
"\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "guo2WRncDRa1", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"The first thing we'll do is create the state Alcie wants to teleport. Let's pick a \"random\" state. Here I've chose a $Y$-axis rotation of $\\pi/4$. " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"colab_type": "code", | |
"id": "_uBy17t7CS_e", | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 34 | |
}, | |
"outputId": "0ba023eb-0ab5-4344-b6d6-f8d7d5843b36" | |
}, | |
"source": [ | |
"msg = cirq.NamedQubit('msg')\n", | |
"\n", | |
"teleportation = cirq.Circuit()\n", | |
"\n", | |
"teleportation.append(cirq.ry(np.pi/4)(msg))\n", | |
"\n", | |
"print(teleportation)" | |
], | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": [ | |
"msg: ───Ry(0.25π)───\n" | |
], | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "zNyyhOKzbemY", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"Let's take a look at the state and compare it to the state when the protocol is complete later." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "OPPFg2XZbarl", | |
"colab_type": "code", | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 34 | |
}, | |
"outputId": "7a579495-b0b7-499a-c031-653233420fb7" | |
}, | |
"source": [ | |
"simulator = cirq.Simulator()\n", | |
"\n", | |
"alice_message = simulator.simulate(teleportation)\n", | |
"\n", | |
"print(alice_message.final_state)" | |
], | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": [ | |
"[0.9238795 +0.j 0.38268343+0.j]\n" | |
], | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "N898apnLiG9c", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"Alice and Bob need to entangle their qubits. This is done with the $H$ and $CNOT$ gates." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "HpdwhUQBb_82", | |
"colab_type": "code", | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 102 | |
}, | |
"outputId": "9e848391-b9fd-48b8-8fab-31f84f10a8ad" | |
}, | |
"source": [ | |
"alice = cirq.NamedQubit('alice')\n", | |
"bob = cirq.NamedQubit('bob')\n", | |
"\n", | |
"teleportation.append([\n", | |
" cirq.H(alice),\n", | |
" cirq.CNOT(alice, bob)\n", | |
" ])\n", | |
"\n", | |
"print(teleportation)" | |
], | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": [ | |
"alice: ───H───────────@───\n", | |
" │\n", | |
"bob: ─────────────────X───\n", | |
"\n", | |
"msg: ─────Ry(0.25π)───────\n" | |
], | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "roS4qY3sAsh_", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"Alice needs to perform an \"entangled\" measurement. She can do this by running the standard $H + CNOT$ circuit in reverse." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "Hw8Rcz8kcOjz", | |
"colab_type": "code", | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 102 | |
}, | |
"outputId": "5c08de0e-37ac-49e9-e013-f9db73fa25e1" | |
}, | |
"source": [ | |
"teleportation.append([\n", | |
" cirq.CNOT(msg, alice),\n", | |
" cirq.H(msg)\n", | |
" ])\n", | |
"\n", | |
"print(teleportation)" | |
], | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": [ | |
"alice: ───H───────────@───X───────\n", | |
" │ │\n", | |
"bob: ─────────────────X───┼───────\n", | |
" │\n", | |
"msg: ─────Ry(0.25π)───────@───H───\n" | |
], | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "c_JZhWI1A-5I", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"Alice measures her two qubits. In cirq we can control on these registers which will assumed to be classical after the measurement." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "_mstAC3BcjV3", | |
"colab_type": "code", | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 102 | |
}, | |
"outputId": "a2cf03c6-a633-4bee-fd4e-d5d4075a9da1" | |
}, | |
"source": [ | |
"teleportation.append(cirq.measure(msg, alice))\n", | |
"\n", | |
"print(teleportation)" | |
], | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": [ | |
"alice: ───H───────────@───X───────M───\n", | |
" │ │ │\n", | |
"bob: ─────────────────X───┼───────┼───\n", | |
" │ │\n", | |
"msg: ─────Ry(0.25π)───────@───H───M───\n" | |
], | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "jaE40zTMBRdm", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"Assuming Bob now has received the two bits from Alice's measurement, he performs the conditional operations $X$ and $Z$." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "BB-RquG6c2co", | |
"colab_type": "code", | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 102 | |
}, | |
"outputId": "28e3e394-c5dc-44b6-a3e2-b039e12b4e59" | |
}, | |
"source": [ | |
"teleportation.append([\n", | |
" cirq.CNOT(alice, bob),\n", | |
" cirq.CZ(msg, bob)\n", | |
" ])\n", | |
"\n", | |
"print(teleportation)" | |
], | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": [ | |
"alice: ───H───────────@───X───────M───@───────\n", | |
" │ │ │ │\n", | |
"bob: ─────────────────X───┼───────┼───X───@───\n", | |
" │ │ │\n", | |
"msg: ─────Ry(0.25π)───────@───H───M───────@───\n" | |
], | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "tIW5Wn9LBbZQ", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"In principle, that is it! Let's run the simulation again to see if Alice's state has been teleported." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "ZvKsTw4YdT1x", | |
"colab_type": "code", | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 34 | |
}, | |
"outputId": "5d4911b1-8ded-4169-9eca-523a5cb739a9" | |
}, | |
"source": [ | |
"bob_received = simulator.simulate(teleportation)\n", | |
"print(bob_received.final_state[[1,3]]) # the state is a 3-qubit state, you need to play around to find the correct indices of Bob's qubit" | |
], | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": [ | |
"[0.92387944+0.j 0.38268343-0.j]\n" | |
], | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "2i3dkPcHBh2b", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"Excellent! Now it's your turn. Here we wrote an ugly script if it's put all together. Why don't you create your own functions to perform teleportation of any state?" | |
] | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment