From 8e7b275f9b6b2478cf499fc68de0f836923a3c47 Mon Sep 17 00:00:00 2001 From: Cassandra Granade Date: 2022年6月13日 19:00:25 +0000 Subject: [PATCH 1/6] Update devcontainer to latest QDK version. --- .devcontainer/Dockerfile | 44 ++++++++++++++++----------------- .devcontainer/devcontainer.json | 20 +++++++-------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 8e3efa2..d85e182 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,22 +1,22 @@ -# This Dockerfile is used by the GitHub Action in -# .github/workflows/build-container.yml to build the Docker image used for -# Visual Studio Code remote development, Visual Studio Online. -FROM mcr.microsoft.com/quantum/iqsharp-base:0.17.2105143879 - -ENV IQSHARP_HOSTING_ENV=QSHARP_BOOK_DEVCONTAINER - -USER root - -# Install additional system packages from apt. -RUN apt-get -y update && \ - apt-get -y install \ - g++ && \ - apt-get clean && rm -rf /var/lib/apt/lists/ - -RUN pip install cython \ - numpy \ - matplotlib \ - scipy && \ - pip install qutip - -USER ${USER} +# This Dockerfile is used by the GitHub Action in +# .github/workflows/build-container.yml to build the Docker image used for +# Visual Studio Code remote development, and for GitHub Codespaces. +FROM mcr.microsoft.com/quantum/iqsharp-base:0.24.210930 + +ENV IQSHARP_HOSTING_ENV=QSHARP_BOOK_DEVCONTAINER + +USER root + +# Install additional system packages from apt. +RUN apt-get -y update && \ + apt-get -y install \ + g++ && \ + apt-get clean && rm -rf /var/lib/apt/lists/ + +RUN pip install cython \ + numpy \ + matplotlib \ + scipy && \ + pip install qutip + +USER ${USER} diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 18234ee..e5038c1 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,10 +1,10 @@ -{ - "image": "sckaiser/learn-qc-with-python-and-qsharp:latest", - "remoteEnv": { - "IQSHARP_HOSTING_ENV": "QSHARP_BOOK_DEVCONTAINER" - }, - "extensions": [ - "quantum.quantum-devkit-vscode", - "ms-python.python" - ] -} +{ + "dockerFile": "./Dockerfile", + "remoteEnv": { + "IQSHARP_HOSTING_ENV": "QSHARP_BOOK_DEVCONTAINER" + }, + "extensions": [ + "quantum.quantum-devkit-vscode", + "ms-python.python" + ] +} From f9369caf3cb62df004c7b3b565510335e48129d3 Mon Sep 17 00:00:00 2001 From: Cassandra Granade Date: 2022年6月14日 03:14:50 +0000 Subject: [PATCH 2/6] Rerun notebooks inside container. --- .github/workflows/README.md | 10 +- .github/workflows/build-devcontainer.yml | 56 +- Dockerfile | 44 +- apxb/apxb-exercise-solutions.ipynb | 632 +++---- ch03/ch03-exercise-solutions.ipynb | 676 ++++---- ch04/ch04-exercise-solutions.ipynb | 402 ++--- ch04/chsh.py | 162 +- ch05/ch05-exercise-solutions.ipynb | 532 +++--- ch05/chsh.py | 154 +- ch06/ch06-exercise-solutions.ipynb | 1116 ++++++------- ch06/interface.py | 154 +- ch06/simulator.py | 264 +-- ch06/teleport.py | 76 +- ch07/BiasedQrng/BiasedQrng.csproj | 18 +- ch07/BiasedQrng/Operation.qs | 98 +- ch07/BiasedQrng/README.md | 20 +- ch07/ClassicalHello/ClassicalHello.csproj | 18 +- ch07/ClassicalHello/EntryPoint.qs | 30 +- ch07/ClassicalHello/Operation.qs | 32 +- ch07/ClassicalHello/README.md | 20 +- ch07/Qrng/Operation.qs | 64 +- ch07/Qrng/Qrng.csproj | 18 +- ch07/Qrng/README.md | 20 +- ch07/ch07-exercise-solutions.ipynb | 25 +- ch07/chapter-07.ipynb | 41 +- ch08/Algorithm.qs | 86 +- ch08/DeutschJozsa.ipynb | 29 +- ch08/Oracles.qs | 56 +- ch08/ch08-exercise-solutions.ipynb | 23 +- ch09/ch09-exercise-solutions.ipynb | 14 +- ch09/host.ipynb | 29 +- ch09/host.py | 116 +- ch09/operations.qs | 216 +-- ch09/qsharp-interop.py | 52 +- ch10/ch10-exercise-solutions.ipynb | 25 +- ch10/host.ipynb | 12 +- ch10/host.py | 70 +- ch10/operations.qs | 320 ++-- ch11/GroverSearch.ipynb | 89 +- ch11/ResourceEstimation.ipynb | 105 +- ch11/ch11-exercise-solutions.ipynb | 25 +- ch11/operations.qs | 200 +-- ch11/plot_resources_vs_size.py | 50 +- ch12/IntegerFactorization.ipynb | 104 +- ch12/ch12-exercise-solutions.ipynb | 1832 +-------------------- ch12/operations.qs | 348 ++-- environment.yml | 24 +- 47 files changed, 3411 insertions(+), 5096 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 90ffd1f..1986bfa 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -1,5 +1,5 @@ -# GitHub Actions Configuration - -The files in this folder are used to configure GitHub Actions for use with the code samples in this repository. -For example, `build-devcontainer.yml` provides GitHub with instructions on how to prebuild and deploy these samples so that it is quicker for you to get started learning quantum computing. -If you're interested in how these actions work, please read more on the [GitHub Actions documentation site](https://help.github.com/en/actions). +# GitHub Actions Configuration + +The files in this folder are used to configure GitHub Actions for use with the code samples in this repository. +For example, `build-devcontainer.yml` provides GitHub with instructions on how to prebuild and deploy these samples so that it is quicker for you to get started learning quantum computing. +If you're interested in how these actions work, please read more on the [GitHub Actions documentation site](https://help.github.com/en/actions). diff --git a/.github/workflows/build-devcontainer.yml b/.github/workflows/build-devcontainer.yml index f763465..0c6bda1 100644 --- a/.github/workflows/build-devcontainer.yml +++ b/.github/workflows/build-devcontainer.yml @@ -1,28 +1,28 @@ -## -# build-devcontainer.yml: GitHub Actions configuration for building sample -# Docker images. -## -# Copyright (c) Sarah Kaiser and Chris Granade. -# Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. -# Book ISBN 9781617296130. -# Code licensed under the MIT License. -## - -on: - - push -name: Prebuild Docker images - -jobs: - devcontainer: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - uses: elgohr/Publish-Docker-Github-Action@master - with: - name: sckaiser/learn-qc-with-python-and-qsharp - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - dockerfile: .devcontainer/Dockerfile - snapshot: true +## +# build-devcontainer.yml: GitHub Actions configuration for building sample +# Docker images. +## +# Copyright (c) Sarah Kaiser and Chris Granade. +# Code sample from the book "Learn Quantum Computing with Python and Q#" by +# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Book ISBN 9781617296130. +# Code licensed under the MIT License. +## + +on: + - push +name: Prebuild Docker images + +jobs: + devcontainer: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - uses: elgohr/Publish-Docker-Github-Action@master + with: + name: sckaiser/learn-qc-with-python-and-qsharp + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + dockerfile: .devcontainer/Dockerfile + snapshot: true diff --git a/Dockerfile b/Dockerfile index cf40c91..8aea058 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,22 @@ -FROM mcr.microsoft.com/quantum/iqsharp-base:0.17.2105143879 - -ENV IQSHARP_HOSTING_ENV=QSHARP_BOOK_DOCKERFILE - -USER root - -# Install additional system packages from apt. -RUN apt-get -y update && \ - apt-get -y install \ - g++ && \ - apt-get clean && rm -rf /var/lib/apt/lists/ - -RUN pip install cython \ - numpy \ - matplotlib \ - scipy && \ - pip install qutip - -COPY . ${HOME} -RUN chown -R ${USER} ${HOME} - -USER ${USER} +FROM mcr.microsoft.com/quantum/iqsharp-base:0.17.2105143879 + +ENV IQSHARP_HOSTING_ENV=QSHARP_BOOK_DOCKERFILE + +USER root + +# Install additional system packages from apt. +RUN apt-get -y update && \ + apt-get -y install \ + g++ && \ + apt-get clean && rm -rf /var/lib/apt/lists/ + +RUN pip install cython \ + numpy \ + matplotlib \ + scipy && \ + pip install qutip + +COPY . ${HOME} +RUN chown -R ${USER} ${HOME} + +USER ${USER} diff --git a/apxb/apxb-exercise-solutions.ipynb b/apxb/apxb-exercise-solutions.ipynb index 14e0e5b..528027e 100644 --- a/apxb/apxb-exercise-solutions.ipynb +++ b/apxb/apxb-exercise-solutions.ipynb @@ -1,316 +1,316 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Appendix B Exercise Solutions\n", - "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", - "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", - "> Book ISBN 9781617296130.\n", - "> Code licensed under the MIT License." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "### Preamble" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "### Exercise B.1 " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**What would 25 meters West and 110 meters North be in feet?**" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[-82. ],\n", - " [360.8]])" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "directions_in_meters = np.array([[-25], [110]])\n", - "directions_in_feet = 3.28 * directions_in_meters\n", - "directions_in_feet" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise B.2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Which of the following functions are linear?**\n", - "\n", - "- $f(x) = 2x$\n", - "- $f(x) = x^2$\n", - "- $f(x) = 2^x$" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Recall that a function $f$ is linear if and only if for all scalars $a$ and $b,ドル $f(ax + by) = af(x) + bf(y)$.\n", - "Let's check this condition for each of the three functions above:\n", - "\n", - "- $f(ax + by) = 2(ax + by) = 2ax + 2by = a \\times 2x + b \\times 2y = af(x) + bf(y),ドル thus this function is linear.\n", - "- $f(ax + by) = (ax + by)^2 = a^2 x^2 + 2abxy + b^2 y^2,ドル but $af(x) + bf(y) = ax^2 + by^2$. Since $a \\ne a^2$ for all $a,ドル and since the second expression is missing the 2ドルabxy$ term, you can conclude that this function is **not** linear.\n", - "- $f(ax + by) = 2^{ax + by} = 2^{ax} \\times 2^{by},ドル but $af(x) + bf(y) = a2^x + b2^y$. These two expressions aren't the same, so you can conclude that this function is **not** linear." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise B.3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Suppose that you have a linear function $g$ such that $g([[1], [0]]) = [[2.3], [-3.1]]$ and $g([[0], [1]]) = [[-5.2], [0.7]]$.\n", - "Compute $g([[2], [-2]])$.**" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[15. ],\n", - " [-7.6]])" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "g_horizontal = np.array([[2.3], [-3.1]])\n", - "g_vertical = np.array([[-5.2], [0.7]])\n", - "\n", - "2 * g_horizontal + (-2) * g_vertical" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise B.4" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Let $X$ be the matrix $[[0, 1], [1, 0]],ドル and let $\\vec{y}$ be the vector $[[2], [3]]$.\n", - "Using NumPy, compute $X\\vec{y}$ and $XX$.**" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "X = np.array([\n", - " [0, 1],\n", - " [1, 0]\n", - "])\n", - "y = np.array([\n", - " [2],\n", - " [3]\n", - "])" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[3],\n", - " [2]])" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "X @ y" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[1, 0],\n", - " [0, 1]])" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "X @ X" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise B.5" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Given a vector $[[2], [3]],ドル find a vector that points in the same direction but with length 1.**\n", - "\n", - "*HINT*: You can either do this by using an inner product, or the `np.linalg.norm` function." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "v = np.array([\n", - " [2],\n", - " [3]\n", - "])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can try both ways suggested by the hint above to confirm that you get the same answer from each." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[0.5547002 ],\n", - " [0.83205029]])" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v / np.sqrt(v.transpose() @ v)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[0.5547002 ],\n", - " [0.83205029]])" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "v / np.linalg.norm(v)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.8" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Appendix B Exercise Solutions\n", + "----\n", + "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", + "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Book ISBN 9781617296130.\n", + "> Code licensed under the MIT License." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### Preamble" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### Exercise B.1 " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**What would 25 meters West and 110 meters North be in feet?**" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[-82. ],\n", + " [360.8]])" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "directions_in_meters = np.array([[-25], [110]])\n", + "directions_in_feet = 3.28 * directions_in_meters\n", + "directions_in_feet" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise B.2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Which of the following functions are linear?**\n", + "\n", + "- $f(x) = 2x$\n", + "- $f(x) = x^2$\n", + "- $f(x) = 2^x$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Recall that a function $f$ is linear if and only if for all scalars $a$ and $b,ドル $f(ax + by) = af(x) + bf(y)$.\n", + "Let's check this condition for each of the three functions above:\n", + "\n", + "- $f(ax + by) = 2(ax + by) = 2ax + 2by = a \\times 2x + b \\times 2y = af(x) + bf(y),ドル thus this function is linear.\n", + "- $f(ax + by) = (ax + by)^2 = a^2 x^2 + 2abxy + b^2 y^2,ドル but $af(x) + bf(y) = ax^2 + by^2$. Since $a \\ne a^2$ for all $a,ドル and since the second expression is missing the 2ドルabxy$ term, you can conclude that this function is **not** linear.\n", + "- $f(ax + by) = 2^{ax + by} = 2^{ax} \\times 2^{by},ドル but $af(x) + bf(y) = a2^x + b2^y$. These two expressions aren't the same, so you can conclude that this function is **not** linear." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise B.3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Suppose that you have a linear function $g$ such that $g([[1], [0]]) = [[2.3], [-3.1]]$ and $g([[0], [1]]) = [[-5.2], [0.7]]$.\n", + "Compute $g([[2], [-2]])$.**" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[15. ],\n", + " [-7.6]])" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "g_horizontal = np.array([[2.3], [-3.1]])\n", + "g_vertical = np.array([[-5.2], [0.7]])\n", + "\n", + "2 * g_horizontal + (-2) * g_vertical" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise B.4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Let $X$ be the matrix $[[0, 1], [1, 0]],ドル and let $\\vec{y}$ be the vector $[[2], [3]]$.\n", + "Using NumPy, compute $X\\vec{y}$ and $XX$.**" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "X = np.array([\n", + " [0, 1],\n", + " [1, 0]\n", + "])\n", + "y = np.array([\n", + " [2],\n", + " [3]\n", + "])" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[3],\n", + " [2]])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "X @ y" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 0],\n", + " [0, 1]])" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "X @ X" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise B.5" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Given a vector $[[2], [3]],ドル find a vector that points in the same direction but with length 1.**\n", + "\n", + "*HINT*: You can either do this by using an inner product, or the `np.linalg.norm` function." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "v = np.array([\n", + " [2],\n", + " [3]\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can try both ways suggested by the hint above to confirm that you get the same answer from each." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0.5547002 ],\n", + " [0.83205029]])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v / np.sqrt(v.transpose() @ v)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0.5547002 ],\n", + " [0.83205029]])" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v / np.linalg.norm(v)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/ch03/ch03-exercise-solutions.ipynb b/ch03/ch03-exercise-solutions.ipynb index 67bd9d9..e5ff84f 100644 --- a/ch03/ch03-exercise-solutions.ipynb +++ b/ch03/ch03-exercise-solutions.ipynb @@ -1,338 +1,338 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 3 Exercise Solutions\n", - "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", - "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", - "> Book ISBN 9781617296130.\n", - "> Code licensed under the MIT License." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Preamble" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 3.1 " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**In Chapter 2, we saw that unitary matrices play the same role in quantum computing that _truth tables_ play in classical computing.\n", - "We can use that to figure out what the matrix X has to look like in order to represent the quantum NOT operation, `x`.\n", - "Let's start by making a table of what the matrix X has to do to each input state in order to represent what the `x` instruction does:**\n", - "\n", - "| Input | Output |\n", - "|---|---|\n", - "| \\|0⟩ | \\|1⟩\n", - "| \\|1⟩ | \\|0⟩\n", - "\n", - "\n", - "**This table tells us that if we multiply the matrix X by the vector |0⟩, we need to get |1⟩, and similarly that X|1⟩ = |0⟩.\n", - "Either by using NumPy or by hand, check that the matrix**\n", - "\n", - "\\begin{align}\n", - "X = \\left(\\begin{matrix}\n", - " 0 & 1 \\\\\n", - " 1 & 0\n", - "\\end{matrix}\\right)\n", - "\\end{align}\n", - "\n", - "**matches what we have in our truth table above.**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can start by defining two variables, `ket0` and `ket1`, to store the vectors representing |0⟩ and |1⟩, respectively." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket0 = np.array([\n", - " [1],\n", - " [0]\n", - "])\n", - "ket1 = np.array([\n", - " [0],\n", - " [1]\n", - "])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we can define a variable to store the matrix $X$." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "X = np.array([\n", - " [0, 1],\n", - " [1, 0]\n", - "])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, we can verify that `X @ ket0` is the same as `ket1` and vice versa:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "X @ ket0" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "X @ ket1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise 3.2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Try using what we learned about vectors in the previous chapter to verify that |0⟩ = (|\\+⟩ + |−⟩) / √2, either by hand or using Python.**\n", - "\n", - "*HINT*: recall that |+⟩ = (|0⟩ + |1⟩) / √2 and that |−⟩ = (|0⟩ − |1⟩) / √2." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As before,it's helpful to start by defining variables to represent the vectors |+⟩ and |−⟩." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket_plus = np.array([\n", - " [1],\n", - " [1]\n", - "]) / np.sqrt(2)\n", - "ket_minus = np.array([\n", - " [1],\n", - " [-1]\n", - "]) / np.sqrt(2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using these new variables, it's easy to verify that $|0\\rangle = (|+\\rangle + |-\\rangle) / \\sqrt{2}$." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "(ket_plus + ket_minus) / np.sqrt(2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise 3.3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "
    \n", - "
  • Calculate what the probability of getting the measurement outcome |−⟩ when measuring the |0⟩ state in the |−⟩ direction.\n", - "
  • Also calculate what the probability of getting the |−⟩ measurement outcome with the input state of |1⟩.\n", - "
\n", - "
" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket0 = np.array([\n", - " [1],\n", - " [0]\n", - "])\n", - "ket1 = np.array([\n", - " [0],\n", - " [1]\n", - "])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket_plus = np.array([\n", - " [1],\n", - " [1]\n", - "]) / np.sqrt(2)\n", - "ket_minus = np.array([\n", - " [1],\n", - " [-1]\n", - "]) / np.sqrt(2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With these variables defined, it's easy to compute Born's rule, $\\Pr(- | 0) = |\\langle - | 0 \\rangle|^2$ by computing the inner product of $|-\\rangle$ with $|0\\rangle$ and taking the absolute value squared of the result." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.abs(ket_minus.conj().transpose() @ ket0) ** 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Similarly, we can compute $\\Pr(- | 1)$ using the same technique." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.abs(ket_minus.conj().transpose() @ ket1) ** 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise 3.4" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**If you had the ciphertext `10100101` and the key `00100110`, what was the message that was originally sent?**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ciphertext = [bit == '1' for bit in '10100101']\n", - "key = [bit == '1' for bit in '00100110']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plaintext = [cipher_bit ^ key_bit for (cipher_bit, key_bit) in zip(ciphertext, key)]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\"\".join(\"1\" if bit else \"0\" for bit in plaintext)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.8" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 3 Exercise Solutions\n", + "----\n", + "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", + "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Book ISBN 9781617296130.\n", + "> Code licensed under the MIT License." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Preamble" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 3.1 " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**In Chapter 2, we saw that unitary matrices play the same role in quantum computing that _truth tables_ play in classical computing.\n", + "We can use that to figure out what the matrix X has to look like in order to represent the quantum NOT operation, `x`.\n", + "Let's start by making a table of what the matrix X has to do to each input state in order to represent what the `x` instruction does:**\n", + "\n", + "| Input | Output |\n", + "|---|---|\n", + "| \\|0⟩ | \\|1⟩\n", + "| \\|1⟩ | \\|0⟩\n", + "\n", + "\n", + "**This table tells us that if we multiply the matrix X by the vector |0⟩, we need to get |1⟩, and similarly that X|1⟩ = |0⟩.\n", + "Either by using NumPy or by hand, check that the matrix**\n", + "\n", + "\\begin{align}\n", + "X = \\left(\\begin{matrix}\n", + " 0 & 1 \\\\\n", + " 1 & 0\n", + "\\end{matrix}\\right)\n", + "\\end{align}\n", + "\n", + "**matches what we have in our truth table above.**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can start by defining two variables, `ket0` and `ket1`, to store the vectors representing |0⟩ and |1⟩, respectively." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket0 = np.array([\n", + " [1],\n", + " [0]\n", + "])\n", + "ket1 = np.array([\n", + " [0],\n", + " [1]\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we can define a variable to store the matrix $X$." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X = np.array([\n", + " [0, 1],\n", + " [1, 0]\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we can verify that `X @ ket0` is the same as `ket1` and vice versa:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X @ ket0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X @ ket1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise 3.2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Try using what we learned about vectors in the previous chapter to verify that |0⟩ = (|\\+⟩ + |−⟩) / √2, either by hand or using Python.**\n", + "\n", + "*HINT*: recall that |+⟩ = (|0⟩ + |1⟩) / √2 and that |−⟩ = (|0⟩ − |1⟩) / √2." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As before,it's helpful to start by defining variables to represent the vectors |+⟩ and |−⟩." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket_plus = np.array([\n", + " [1],\n", + " [1]\n", + "]) / np.sqrt(2)\n", + "ket_minus = np.array([\n", + " [1],\n", + " [-1]\n", + "]) / np.sqrt(2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using these new variables, it's easy to verify that $|0\\rangle = (|+\\rangle + |-\\rangle) / \\sqrt{2}$." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(ket_plus + ket_minus) / np.sqrt(2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise 3.3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "
    \n", + "
  • Calculate what the probability of getting the measurement outcome |−⟩ when measuring the |0⟩ state in the |−⟩ direction.\n", + "
  • Also calculate what the probability of getting the |−⟩ measurement outcome with the input state of |1⟩.\n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket0 = np.array([\n", + " [1],\n", + " [0]\n", + "])\n", + "ket1 = np.array([\n", + " [0],\n", + " [1]\n", + "])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket_plus = np.array([\n", + " [1],\n", + " [1]\n", + "]) / np.sqrt(2)\n", + "ket_minus = np.array([\n", + " [1],\n", + " [-1]\n", + "]) / np.sqrt(2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With these variables defined, it's easy to compute Born's rule, $\\Pr(- | 0) = |\\langle - | 0 \\rangle|^2$ by computing the inner product of $|-\\rangle$ with $|0\\rangle$ and taking the absolute value squared of the result." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.abs(ket_minus.conj().transpose() @ ket0) ** 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly, we can compute $\\Pr(- | 1)$ using the same technique." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.abs(ket_minus.conj().transpose() @ ket1) ** 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise 3.4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**If you had the ciphertext `10100101` and the key `00100110`, what was the message that was originally sent?**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ciphertext = [bit == '1' for bit in '10100101']\n", + "key = [bit == '1' for bit in '00100110']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plaintext = [cipher_bit ^ key_bit for (cipher_bit, key_bit) in zip(ciphertext, key)]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\"\".join(\"1\" if bit else \"0\" for bit in plaintext)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/ch04/ch04-exercise-solutions.ipynb b/ch04/ch04-exercise-solutions.ipynb index b5506f8..255193a 100644 --- a/ch04/ch04-exercise-solutions.ipynb +++ b/ch04/ch04-exercise-solutions.ipynb @@ -1,201 +1,201 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 4 Exercise Solutions\n", - "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", - "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", - "> Book ISBN 9781617296130.\n", - "> Code licensed under the MIT License." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Preamble" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import qutip as qt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 4.1 " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Since the referee is purely classical, we'll model them as using classical random number generators.\n", - "This leaves open the possibility, though, that you and Eve could cheat by guessing the referee's questions.\n", - "A possible improvement might be to use the QRNGs from Chapter 2.\n", - "Modify the code sample in [`chsh.py`](./chsh.py) so that the referee can ask questions of you and Eve by measuring a qubit that starts off in the $\\left|+\\right\\rangle$ state.**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The key to this exercise is replacing `random_bit`:\n", - "\n", - "```python\n", - "def random_bit() -> int:\n", - " return random.randint(0, 1)\n", - "```\n", - "\n", - "You can use what you learned in Chapter 2 to replace this by a QRNG:\n", - "\n", - "```python\n", - "def random_bit(device: QuantumDevice) -> int:\n", - " with device.using_qubit() as q:\n", - " q.h()\n", - " return int(q.measure())\n", - "```\n", - "\n", - "The referee will then need to allocate a new quantum device to use in generating their random bits:\n", - "\n", - "```python\n", - "def referee(strategy: Callable[[], Strategy]) -> bool:\n", - " device = Simulator(capacity=1)\n", - " you, eve = strategy()\n", - " your_input, eve_input = random_bit(device), random_bit(device)\n", - " # ...\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise 4.2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**How would you prepare a $\\left|+0\\right\\rangle$ state?\n", - "First, what vector would you use to represent the two-qubit state $\\left|+0\\right\\rangle = \\left|+\\right\\rangle \\otimes \\left|0\\right\\rangle$?\n", - "You have an initial two qubit register in the $\\left|00\\right\\rangle$ state.\n", - "What operation should you apply to get the state you want?**\n", - "\n", - "*HINT*: try (H ⊗ 1) if you are stuck!" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this exercise, you can start by writing out the vector representations of $|+\\rangle$ and $|0\\rangle$ as QuTiP `Qobj` instances:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket0 = qt.Qobj([\n", - " [1],\n", - " [0]\n", - "])\n", - "ket_plus = qt.Qobj([\n", - " [1],\n", - " [1]\n", - "]) / np.sqrt(2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can then find the two-qubit state $|+0\\rangle = |{+}\\rangle \\otimes |0\\rangle$ using `qt.tensor`:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "qt.tensor(ket_plus, ket0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using the hint above, you can verify that this is what you get if you apply the Hadamard operation (represented by the unitary matrix returned by `qt.qip.operations.hadamard_transform`) to the first qubit of a two-qubit register. Note that as mentioned in the hint, you'll need to act on the state of the second qubit with identity matrix to represent doing nothing. The identity matrix can be obtained using the QuTiP function `qt.qeye(2)`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "U = qt.tensor(qt.qip.operations.hadamard_transform(), qt.qeye(2))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "You can then verify that applying the Hadamard operation to the first qubit does what you expect to the state of the two-qubit register." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "U * qt.tensor(ket0, ket0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Since this agrees with the output of `qt.tensor(ket_plus, ket0)`, you've confirmed that you can use the Hadamard operation on the first qubit in a two-qubit register to prepare $|+0\\rangle = |+\\rangle \\otimes |0\\rangle$" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.8" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 4 Exercise Solutions\n", + "----\n", + "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", + "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Book ISBN 9781617296130.\n", + "> Code licensed under the MIT License." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Preamble" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import qutip as qt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 4.1 " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Since the referee is purely classical, we'll model them as using classical random number generators.\n", + "This leaves open the possibility, though, that you and Eve could cheat by guessing the referee's questions.\n", + "A possible improvement might be to use the QRNGs from Chapter 2.\n", + "Modify the code sample in [`chsh.py`](./chsh.py) so that the referee can ask questions of you and Eve by measuring a qubit that starts off in the $\\left|+\\right\\rangle$ state.**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The key to this exercise is replacing `random_bit`:\n", + "\n", + "```python\n", + "def random_bit() -> int:\n", + " return random.randint(0, 1)\n", + "```\n", + "\n", + "You can use what you learned in Chapter 2 to replace this by a QRNG:\n", + "\n", + "```python\n", + "def random_bit(device: QuantumDevice) -> int:\n", + " with device.using_qubit() as q:\n", + " q.h()\n", + " return int(q.measure())\n", + "```\n", + "\n", + "The referee will then need to allocate a new quantum device to use in generating their random bits:\n", + "\n", + "```python\n", + "def referee(strategy: Callable[[], Strategy]) -> bool:\n", + " device = Simulator(capacity=1)\n", + " you, eve = strategy()\n", + " your_input, eve_input = random_bit(device), random_bit(device)\n", + " # ...\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise 4.2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**How would you prepare a $\\left|+0\\right\\rangle$ state?\n", + "First, what vector would you use to represent the two-qubit state $\\left|+0\\right\\rangle = \\left|+\\right\\rangle \\otimes \\left|0\\right\\rangle$?\n", + "You have an initial two qubit register in the $\\left|00\\right\\rangle$ state.\n", + "What operation should you apply to get the state you want?**\n", + "\n", + "*HINT*: try (H ⊗ 1) if you are stuck!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this exercise, you can start by writing out the vector representations of $|+\\rangle$ and $|0\\rangle$ as QuTiP `Qobj` instances:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket0 = qt.Qobj([\n", + " [1],\n", + " [0]\n", + "])\n", + "ket_plus = qt.Qobj([\n", + " [1],\n", + " [1]\n", + "]) / np.sqrt(2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can then find the two-qubit state $|+0\\rangle = |{+}\\rangle \\otimes |0\\rangle$ using `qt.tensor`:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "qt.tensor(ket_plus, ket0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using the hint above, you can verify that this is what you get if you apply the Hadamard operation (represented by the unitary matrix returned by `qt.qip.operations.hadamard_transform`) to the first qubit of a two-qubit register. Note that as mentioned in the hint, you'll need to act on the state of the second qubit with identity matrix to represent doing nothing. The identity matrix can be obtained using the QuTiP function `qt.qeye(2)`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "U = qt.tensor(qt.qip.operations.hadamard_transform(), qt.qeye(2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can then verify that applying the Hadamard operation to the first qubit does what you expect to the state of the two-qubit register." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "U * qt.tensor(ket0, ket0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since this agrees with the output of `qt.tensor(ket_plus, ket0)`, you've confirmed that you can use the Hadamard operation on the first qubit in a two-qubit register to prepare $|+0\\rangle = |+\\rangle \\otimes |0\\rangle$" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/ch04/chsh.py b/ch04/chsh.py index 5b69b11..ce1c25d 100644 --- a/ch04/chsh.py +++ b/ch04/chsh.py @@ -1,81 +1,81 @@ -#!/bin/env python -# -*- coding: utf-8 -*- -## -# chsh.py: Implements the CHSH nonlocal game using the multi-qubit simulator -# in simulator.py with the simulator interface defined in interface.py. -## -# Copyright (c) Sarah Kaiser and Chris Granade. -# Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. -# Book ISBN 9781617296130. -# Code licensed under the MIT License. -## - -#NOTE: This file is only part of the CHSH sample that will be developed over -# chapters 4 and 5. For the complete, finished example please see the code in -# the `ch05` directory. - -import random -from functools import partial -from typing import Tuple, Callable -import numpy as np - -from interface import QuantumDevice, Qubit -from simulator import Simulator - -Strategy = Tuple[Callable[[int], int], Callable[[int], int]] - -def random_bit() -> int: - return random.randint(0, 1) - -def referee(strategy: Callable[[], Strategy]) -> bool: - you, eve = strategy() - your_input, eve_input = random_bit(), random_bit() - parity = 0 if you(your_input) == eve(eve_input) else 1 - return parity == (your_input and eve_input) - -def est_win_probability(strategy: Callable[[], Strategy], - n_games: int = 1000) -> float: - return sum( - referee(strategy) - for idx_game in range(n_games) - ) / n_games - -def constant_strategy() -> Strategy: - return ( - lambda your_input: 0, - lambda eve_input: 0 - ) - -import qutip as qt -def quantum_strategy(initial_state: qt.Qobj) -> Strategy: - shared_system = Simulator(capacity=2) - shared_system.register_state = initial_state - your_qubit = shared_system.allocate_qubit() - eve_qubit = shared_system.allocate_qubit() - - shared_system.register_state = qt.bell_state() - your_angles = [90 * np.pi / 180, 0] - eve_angles = [45 * np.pi / 180, 135 * np.pi / 180] - - def you(your_input: int) -> int: - your_qubit.ry(your_angles[your_input]) - return your_qubit.measure() - - def eve(eve_input: int) -> int: - eve_qubit.ry(eve_angles[eve_input]) - return eve_qubit.measure() - - return you, eve - -if __name__ == "__main__": - constant_pr = est_win_probability(constant_strategy, 100) - print(f"Constant strategy won {constant_pr:0.1%} of the time.") - - initial_state = qt.Qobj([[1], [0], [0], [1]]) / np.sqrt(2) - quantum_pr = est_win_probability( - partial(quantum_strategy, initial_state), - 100 - ) - print(f"Quantum strategy won {quantum_pr:0.1%} of the time " \ - f"with initial state:\n{initial_state}.") +#!/bin/env python +# -*- coding: utf-8 -*- +## +# chsh.py: Implements the CHSH nonlocal game using the multi-qubit simulator +# in simulator.py with the simulator interface defined in interface.py. +## +# Copyright (c) Sarah Kaiser and Chris Granade. +# Code sample from the book "Learn Quantum Computing with Python and Q#" by +# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Book ISBN 9781617296130. +# Code licensed under the MIT License. +## + +#NOTE: This file is only part of the CHSH sample that will be developed over +# chapters 4 and 5. For the complete, finished example please see the code in +# the `ch05` directory. + +import random +from functools import partial +from typing import Tuple, Callable +import numpy as np + +from interface import QuantumDevice, Qubit +from simulator import Simulator + +Strategy = Tuple[Callable[[int], int], Callable[[int], int]] + +def random_bit() -> int: + return random.randint(0, 1) + +def referee(strategy: Callable[[], Strategy]) -> bool: + you, eve = strategy() + your_input, eve_input = random_bit(), random_bit() + parity = 0 if you(your_input) == eve(eve_input) else 1 + return parity == (your_input and eve_input) + +def est_win_probability(strategy: Callable[[], Strategy], + n_games: int = 1000) -> float: + return sum( + referee(strategy) + for idx_game in range(n_games) + ) / n_games + +def constant_strategy() -> Strategy: + return ( + lambda your_input: 0, + lambda eve_input: 0 + ) + +import qutip as qt +def quantum_strategy(initial_state: qt.Qobj) -> Strategy: + shared_system = Simulator(capacity=2) + shared_system.register_state = initial_state + your_qubit = shared_system.allocate_qubit() + eve_qubit = shared_system.allocate_qubit() + + shared_system.register_state = qt.bell_state() + your_angles = [90 * np.pi / 180, 0] + eve_angles = [45 * np.pi / 180, 135 * np.pi / 180] + + def you(your_input: int) -> int: + your_qubit.ry(your_angles[your_input]) + return your_qubit.measure() + + def eve(eve_input: int) -> int: + eve_qubit.ry(eve_angles[eve_input]) + return eve_qubit.measure() + + return you, eve + +if __name__ == "__main__": + constant_pr = est_win_probability(constant_strategy, 100) + print(f"Constant strategy won {constant_pr:0.1%} of the time.") + + initial_state = qt.Qobj([[1], [0], [0], [1]]) / np.sqrt(2) + quantum_pr = est_win_probability( + partial(quantum_strategy, initial_state), + 100 + ) + print(f"Quantum strategy won {quantum_pr:0.1%} of the time " \ + f"with initial state:\n{initial_state}.") diff --git a/ch05/ch05-exercise-solutions.ipynb b/ch05/ch05-exercise-solutions.ipynb index 7289d39..4985b41 100644 --- a/ch05/ch05-exercise-solutions.ipynb +++ b/ch05/ch05-exercise-solutions.ipynb @@ -1,266 +1,266 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 5 Exercise Solutions\n", - "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", - "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", - "> Book ISBN 9781617296130.\n", - "> Code licensed under the MIT License." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Preamble" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import qutip as qt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise 5.1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**How would you create a `Qobj` to represent the |1⟩ state? How about the |+⟩ or $\\left|-\\right\\rangle$ state? If you need to check back to _Simulating qubits in code_ section of Chapter 2 for what vectors represent those states.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket1 = qt.Qobj([\n", - " [0],\n", - " [1]\n", - "])\n", - "ket1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket_plus = qt.Qobj([\n", - " [1],\n", - " [1]\n", - "]) / np.sqrt(2)\n", - "ket_plus" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket_minus = qt.Qobj([\n", - " [1],\n", - " [-1]\n", - "]) / np.sqrt(2)\n", - "ket_minus" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise 5.2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**How could you use the `qt.basis` function to create a two qubit register in the |10⟩ state?\n", - "How could you create the $\\left|001\\right\\rangle$ state? \n", - "Remember that the second argument to `qt.basis` is an index to the computational basis states we saw earlier.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket001 = qt.tensor([qt.basis(2, label) for label in (0, 0, 1)])\n", - "ket001" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise 5.3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**In the example where our two qubits start off in the $\\left|++\\right\\rangle$ state, suppose we measured the second qubit instead.\n", - "Check that no matter what result we get, nothing happens to the state of the first qubit.**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "It's easiest to consider this in two cases, but first let's start by writing out $|++\\rangle$ as a vector." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "qt.tensor(ket_plus, ket_plus)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This vector has a non-zero amplitude on all four computational basis states $|00\\rangle,ドル $|01\\rangle,ドル $|10\\rangle,ドル and $|11\\rangle$.\n", - "In the case that measuring the second qubit gives us a \"0\" result, we need to filter out the amplitudes that are inconsistent with that result (in particular, the amplitudes of $|01\\rangle$ and $|11\\rangle,ドル represented by the second and fourth rows, respectively)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "zero_case = qt.Qobj([\n", - " [0.5],\n", - " [0.0],\n", - " [0.5],\n", - " [0.0]\n", - "]).unit()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Above, we used the `unit` method to renormalize (that is, to make the length of the state vector equal to 1) so that the measurement probabilities still sum to one." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "zero_case" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We note that this is equivalent to $|+0\\rangle$:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket0 = qt.Qobj([\n", - " [1],\n", - " [0]\n", - "])\n", - "\n", - "qt.tensor(ket_plus, ket0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Similarly, in the \"1\" case, we need to filter out the first and third rows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "one_case = qt.Qobj([\n", - " [0.0],\n", - " [0.5],\n", - " [0.0],\n", - " [0.5]\n", - "]).unit()\n", - "one_case" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "qt.tensor(ket_plus, ket1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In both cases, the state of the first qubit after measuring was still $|+\\rangle,ドル confirming that measuring the second qubit had no effect on the state of the first qubit in this case.\n", - "Note that this may not have been the case if the two qubits started off in an *entangled state*." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.8" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 5 Exercise Solutions\n", + "----\n", + "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", + "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Book ISBN 9781617296130.\n", + "> Code licensed under the MIT License." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Preamble" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import qutip as qt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise 5.1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**How would you create a `Qobj` to represent the |1⟩ state? How about the |+⟩ or $\\left|-\\right\\rangle$ state? If you need to check back to _Simulating qubits in code_ section of Chapter 2 for what vectors represent those states.**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket1 = qt.Qobj([\n", + " [0],\n", + " [1]\n", + "])\n", + "ket1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket_plus = qt.Qobj([\n", + " [1],\n", + " [1]\n", + "]) / np.sqrt(2)\n", + "ket_plus" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket_minus = qt.Qobj([\n", + " [1],\n", + " [-1]\n", + "]) / np.sqrt(2)\n", + "ket_minus" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise 5.2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**How could you use the `qt.basis` function to create a two qubit register in the |10⟩ state?\n", + "How could you create the $\\left|001\\right\\rangle$ state? \n", + "Remember that the second argument to `qt.basis` is an index to the computational basis states we saw earlier.**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket001 = qt.tensor([qt.basis(2, label) for label in (0, 0, 1)])\n", + "ket001" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise 5.3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**In the example where our two qubits start off in the $\\left|++\\right\\rangle$ state, suppose we measured the second qubit instead.\n", + "Check that no matter what result we get, nothing happens to the state of the first qubit.**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It's easiest to consider this in two cases, but first let's start by writing out $|++\\rangle$ as a vector." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "qt.tensor(ket_plus, ket_plus)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This vector has a non-zero amplitude on all four computational basis states $|00\\rangle,ドル $|01\\rangle,ドル $|10\\rangle,ドル and $|11\\rangle$.\n", + "In the case that measuring the second qubit gives us a \"0\" result, we need to filter out the amplitudes that are inconsistent with that result (in particular, the amplitudes of $|01\\rangle$ and $|11\\rangle,ドル represented by the second and fourth rows, respectively)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "zero_case = qt.Qobj([\n", + " [0.5],\n", + " [0.0],\n", + " [0.5],\n", + " [0.0]\n", + "]).unit()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Above, we used the `unit` method to renormalize (that is, to make the length of the state vector equal to 1) so that the measurement probabilities still sum to one." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "zero_case" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We note that this is equivalent to $|+0\\rangle$:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket0 = qt.Qobj([\n", + " [1],\n", + " [0]\n", + "])\n", + "\n", + "qt.tensor(ket_plus, ket0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly, in the \"1\" case, we need to filter out the first and third rows:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "one_case = qt.Qobj([\n", + " [0.0],\n", + " [0.5],\n", + " [0.0],\n", + " [0.5]\n", + "]).unit()\n", + "one_case" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "qt.tensor(ket_plus, ket1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In both cases, the state of the first qubit after measuring was still $|+\\rangle,ドル confirming that measuring the second qubit had no effect on the state of the first qubit in this case.\n", + "Note that this may not have been the case if the two qubits started off in an *entangled state*." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/ch05/chsh.py b/ch05/chsh.py index e1c92ec..ed8ce98 100644 --- a/ch05/chsh.py +++ b/ch05/chsh.py @@ -1,77 +1,77 @@ -#!/bin/env python -# -*- coding: utf-8 -*- -## -# chsh.py: Implements the CHSH nonlocal game using the multi-qubit simulator -# in simulator.py with the simulator interface defined in interface.py. -## -# Copyright (c) Sarah Kaiser and Chris Granade. -# Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. -# Book ISBN 9781617296130. -# Code licensed under the MIT License. -## - -import random -from functools import partial -from typing import Tuple, Callable -import numpy as np - -from interface import QuantumDevice, Qubit -from simulator import Simulator - -Strategy = Tuple[Callable[[int], int], Callable[[int], int]] - -def random_bit() -> int: - return random.randint(0, 1) - -def referee(strategy: Callable[[], Strategy]) -> bool: - you, eve = strategy() - your_input, eve_input = random_bit(), random_bit() - parity = 0 if you(your_input) == eve(eve_input) else 1 - return parity == (your_input and eve_input) - -def est_win_probability(strategy: Callable[[], Strategy], - n_games: int = 1000) -> float: - return sum( - referee(strategy) - for idx_game in range(n_games) - ) / n_games - -def constant_strategy() -> Strategy: - return ( - lambda your_input: 0, - lambda eve_input: 0 - ) - -import qutip as qt -def quantum_strategy(initial_state: qt.Qobj) -> Strategy: - shared_system = Simulator(capacity=2) - shared_system.register_state = initial_state - your_qubit = shared_system.allocate_qubit() - eve_qubit = shared_system.allocate_qubit() - - shared_system.register_state = qt.bell_state() - your_angles = [90 * np.pi / 180, 0] - eve_angles = [45 * np.pi / 180, 135 * np.pi / 180] - - def you(your_input: int) -> int: - your_qubit.ry(your_angles[your_input]) - return your_qubit.measure() - - def eve(eve_input: int) -> int: - eve_qubit.ry(eve_angles[eve_input]) - return eve_qubit.measure() - - return you, eve - -if __name__ == "__main__": - constant_pr = est_win_probability(constant_strategy, 100) - print(f"Constant strategy won {constant_pr:0.1%} of the time.") - - initial_state = qt.Qobj([[1], [0], [0], [1]]) / np.sqrt(2) - quantum_pr = est_win_probability( - partial(quantum_strategy, initial_state), - 100 - ) - print(f"Quantum strategy won {quantum_pr:0.1%} of the time " \ - f"with initial state:\n{initial_state}.") +#!/bin/env python +# -*- coding: utf-8 -*- +## +# chsh.py: Implements the CHSH nonlocal game using the multi-qubit simulator +# in simulator.py with the simulator interface defined in interface.py. +## +# Copyright (c) Sarah Kaiser and Chris Granade. +# Code sample from the book "Learn Quantum Computing with Python and Q#" by +# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Book ISBN 9781617296130. +# Code licensed under the MIT License. +## + +import random +from functools import partial +from typing import Tuple, Callable +import numpy as np + +from interface import QuantumDevice, Qubit +from simulator import Simulator + +Strategy = Tuple[Callable[[int], int], Callable[[int], int]] + +def random_bit() -> int: + return random.randint(0, 1) + +def referee(strategy: Callable[[], Strategy]) -> bool: + you, eve = strategy() + your_input, eve_input = random_bit(), random_bit() + parity = 0 if you(your_input) == eve(eve_input) else 1 + return parity == (your_input and eve_input) + +def est_win_probability(strategy: Callable[[], Strategy], + n_games: int = 1000) -> float: + return sum( + referee(strategy) + for idx_game in range(n_games) + ) / n_games + +def constant_strategy() -> Strategy: + return ( + lambda your_input: 0, + lambda eve_input: 0 + ) + +import qutip as qt +def quantum_strategy(initial_state: qt.Qobj) -> Strategy: + shared_system = Simulator(capacity=2) + shared_system.register_state = initial_state + your_qubit = shared_system.allocate_qubit() + eve_qubit = shared_system.allocate_qubit() + + shared_system.register_state = qt.bell_state() + your_angles = [90 * np.pi / 180, 0] + eve_angles = [45 * np.pi / 180, 135 * np.pi / 180] + + def you(your_input: int) -> int: + your_qubit.ry(your_angles[your_input]) + return your_qubit.measure() + + def eve(eve_input: int) -> int: + eve_qubit.ry(eve_angles[eve_input]) + return eve_qubit.measure() + + return you, eve + +if __name__ == "__main__": + constant_pr = est_win_probability(constant_strategy, 100) + print(f"Constant strategy won {constant_pr:0.1%} of the time.") + + initial_state = qt.Qobj([[1], [0], [0], [1]]) / np.sqrt(2) + quantum_pr = est_win_probability( + partial(quantum_strategy, initial_state), + 100 + ) + print(f"Quantum strategy won {quantum_pr:0.1%} of the time " \ + f"with initial state:\n{initial_state}.") diff --git a/ch06/ch06-exercise-solutions.ipynb b/ch06/ch06-exercise-solutions.ipynb index bfee939..48fb1d8 100644 --- a/ch06/ch06-exercise-solutions.ipynb +++ b/ch06/ch06-exercise-solutions.ipynb @@ -1,558 +1,558 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 6 Exercise Solutions\n", - "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", - "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", - "> Book ISBN 9781617296130.\n", - "> Code licensed under the MIT License." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Preamble" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import qutip as qt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 6.1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Say you have a register with 3 qubits, in the state |01+⟩. Using QuTiP, write out this state, and then swap the second and third qubits so your register is in the |0+1⟩ state.**\n", - "\n", - "*HINT*: since nothing will happen to the first qubit, make sure to tensor an identity matrix to `qt.swap` to build up the correct operation for your register." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket0 = qt.basis(2, 0)\n", - "ket1 = qt.basis(2, 1)\n", - "ket_plus = qt.Qobj([\n", - " [1],\n", - " [1]\n", - "]) / np.sqrt(2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "initial_state = qt.tensor(ket0, ket1, ket_plus)\n", - "initial_state" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "qt.tensor(qt.qeye(2), qt.qip.operations.swap()) * initial_state" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "qt.tensor(ket0, ket_plus, ket1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise 6.2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Suppose you prepare a qubit in the |−⟩ state and apply a `z` rotation.\n", - "If you measure along the X axis, what would you get?\n", - "What would you measure if you apply two `z` rotations?\n", - "If you had to implement those same two rotations with `rz`, what angles would you use?**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Recall that the `z` operation is represented by the unitary matrix returned by `qt.sigmaz()`.\n", - "Thus, you can figure out what `z` does to a qubit in the $|-\\rangle$ state by using that matrix:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket_minus = qt.Qobj([\n", - " [1],\n", - " [-1]\n", - "]) / np.sqrt(2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "qt.sigmaz() * ket_minus" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We recognize this being the state vector $|+\\rangle,ドル so that we'll always get a \"0\" result when measuring along the X-axis." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Applying a second `z` instruction takes us back to $|-\\rangle,ドル however:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "qt.sigmaz() * qt.sigmaz() * ket_minus" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If you wanted to use an `rz` instruction instead of `z`, you would need a rotation of $\\pi$:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "qt.qip.operations.rz(np.pi) * ket_minus" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice that this is different from $|+\\rangle$ only by a global phase of $-i$." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "qt.qip.operations.rz(np.pi) * ket_minus / -1j" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise 6.3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Use the `qt.sigmay()` function to make a table similar to the one for the `z` instruction, but for the `y` instruction.**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The \"truth table\" in the main body for the `z` instruction listed what the `z` instruction does for qubits in each of the input states |0⟩, |1⟩, |+⟩, and |−⟩.\n", - "While that's overcomplete in the sense that you can infer what `z` does from its action on the |0⟩ or |1⟩ states alone (or on the |+⟩ and |−⟩ states alone), it's helpful to keep in mind, so let's write out the same here for `y`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket0 = qt.basis(2, 0)\n", - "ket1 = qt.basis(2, 1)\n", - "ket_plus = qt.Qobj([\n", - " [1],\n", - " [1]\n", - "]) / np.sqrt(2)\n", - "ket_minus = qt.Qobj([\n", - " [1],\n", - " [-1]\n", - "]) / np.sqrt(2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "qt.sigmay() * ket0" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "qt.sigmay() * ket1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "qt.sigmay() * ket_plus" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "qt.sigmay() * ket_minus" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using these four results, you can complete now the table:\n", - "\n", - "| Input | Output |\n", - "|---|---|\n", - "| \\|0⟩ | i\\|0⟩ |\n", - "| \\|1⟩ | −i\\|1⟩ |\n", - "| \\|+⟩ | −i\\|−⟩ |\n", - "| \\|−⟩ | i\\|+⟩ |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise 6.4" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**We've only checked that one measurement probability is still the same, but maybe the probabilities have changed for X or Y measurements.\n", - "To fully check that the global phase doesn't change anything, prepare the same state and rotation as in Listing 5.10 and check that the probabilities of measuring the state along the X or Y axis aren't changed by applying an `rz` instruction.**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Recall that the state $|\\psi\\rangle$ was prepared by an `rz` instruction acting on a qubit in the |0⟩ state." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "ket0 = qt.basis(2, 0)\n", - "ket1 = qt.basis(2, 1)\n", - "ket_plus = qt.Qobj([\n", - " [1],\n", - " [1]\n", - "]).unit()\n", - "ket_psi = qt.qip.operations.rz(np.pi / 3) * ket0\n", - "ket_psi" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To confirm that this state is indistinguishable from the |0⟩ state before applying a global phase, we can check that the overlap with the |+⟩ and $(|0\\rangle + i|1\\rangle) / \\sqrt{2}$ states is left the same (namely, that measurement probabilities are left at 50/50):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.abs((ket_plus.dag() * ket_psi)[0, 0]) ** 2" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "np.abs(((ket0 + 1j * ket1).unit().dag() * ket_psi)[0, 0]) ** 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise 6.5" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**The $\\left(\\left|00\\right\\rangle + \\left|11\\right\\rangle\\right) / \\sqrt{2}$ state that we've seen a few times now isn't the only example of an entangled state.\n", - "In fact, if you pick a two-qubit state at random, it is almost certainly going to be entangled.\n", - "Just as the computational basis $\\left\\{\\left|00\\right\\rangle, \\left|01\\right\\rangle, \\left|10\\right\\rangle, \\left|11\\right\\rangle\\right\\}$ is a particularly useful set of unentangled states, there's a set of four particular entangled states known as the _Bell basis_ after physicist John Stewart Bell.**\n", - "\n", - "| Name | Expansion in computational basis |\n", - "|---|---|\n", - "| \\|β00⟩ | (\\|00⟩ + \\|11⟩) / √2 |\n", - "| \\|β01⟩ | (\\|00⟩ − \\|11⟩) / √2 |\n", - "| \\|β10⟩ | (\\|01⟩ + \\|10⟩) / √2 |\n", - "| \\|β11⟩ | (\\|01⟩ − \\|10⟩) / √2 |\n", - "\n", - "**Using what you've learned about the `cnot` instruction and the Pauli instructions (`x`, `y`, and `z`), write programs to prepare each of the four Bell states in the table above.**\n", - "\n", - "*HINT*: Table 5.2 should be very helpful in this exercise." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For this exercise, let's use the shiny new simulator that you put together during this Chapter!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import simulator" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "device = simulator.Simulator(capacity=2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Recall that we can use the `h` and `cnot` instructions together to prepare a two-qubit register in a Bell pair." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "with device.using_register(2) as (left, right):\n", - " left.h()\n", - " left.cnot(right)\n", - " device.dump()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To get the other three Bell basis states, we can use Pauli instructions on the first qubit alone." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "with device.using_register(2) as (left, right):\n", - " left.h()\n", - " left.cnot(right)\n", - " \n", - " left.x()\n", - " \n", - " device.dump()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "with device.using_register(2) as (left, right):\n", - " left.h()\n", - " left.cnot(right)\n", - " \n", - " left.z()\n", - " \n", - " device.dump()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "with device.using_register(2) as (left, right):\n", - " left.h()\n", - " left.cnot(right)\n", - " \n", - " left.x()\n", - " left.z()\n", - " \n", - " device.dump()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that you could also have applied your Pauli instructions to the second qubit as well; this is a unique symmetry of the Bell basis states, and one of the things that makes them really neat to work with." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "with device.using_register(2) as (left, right):\n", - " left.h()\n", - " left.cnot(right)\n", - " \n", - " right.x()\n", - " right.z()\n", - " \n", - " device.dump()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "----\n", - "### Exercise 6.6" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Try changing your operation or Eve's operation to convince yourself that you only get a |000⟩ state at the end if you undo the same operation that Eve applied to her qubit.**" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import simulator\n", - "from teleport import teleport" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sim = simulator.Simulator(capacity=3)\n", - "with sim.using_register(3) as (msg, here, there):\n", - " msg.ry(0.123)\n", - " teleport(msg, here, there)\n", - "\n", - " there.h()\n", - " sim.dump() " - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.8" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 6 Exercise Solutions\n", + "----\n", + "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", + "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Book ISBN 9781617296130.\n", + "> Code licensed under the MIT License." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Preamble" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import qutip as qt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Exercise 6.1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Say you have a register with 3 qubits, in the state |01+⟩. Using QuTiP, write out this state, and then swap the second and third qubits so your register is in the |0+1⟩ state.**\n", + "\n", + "*HINT*: since nothing will happen to the first qubit, make sure to tensor an identity matrix to `qt.swap` to build up the correct operation for your register." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket0 = qt.basis(2, 0)\n", + "ket1 = qt.basis(2, 1)\n", + "ket_plus = qt.Qobj([\n", + " [1],\n", + " [1]\n", + "]) / np.sqrt(2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "initial_state = qt.tensor(ket0, ket1, ket_plus)\n", + "initial_state" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "qt.tensor(qt.qeye(2), qt.qip.operations.swap()) * initial_state" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "qt.tensor(ket0, ket_plus, ket1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise 6.2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Suppose you prepare a qubit in the |−⟩ state and apply a `z` rotation.\n", + "If you measure along the X axis, what would you get?\n", + "What would you measure if you apply two `z` rotations?\n", + "If you had to implement those same two rotations with `rz`, what angles would you use?**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Recall that the `z` operation is represented by the unitary matrix returned by `qt.sigmaz()`.\n", + "Thus, you can figure out what `z` does to a qubit in the $|-\\rangle$ state by using that matrix:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket_minus = qt.Qobj([\n", + " [1],\n", + " [-1]\n", + "]) / np.sqrt(2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "qt.sigmaz() * ket_minus" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We recognize this being the state vector $|+\\rangle,ドル so that we'll always get a \"0\" result when measuring along the X-axis." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Applying a second `z` instruction takes us back to $|-\\rangle,ドル however:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "qt.sigmaz() * qt.sigmaz() * ket_minus" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you wanted to use an `rz` instruction instead of `z`, you would need a rotation of $\\pi$:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "qt.qip.operations.rz(np.pi) * ket_minus" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that this is different from $|+\\rangle$ only by a global phase of $-i$." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "qt.qip.operations.rz(np.pi) * ket_minus / -1j" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise 6.3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Use the `qt.sigmay()` function to make a table similar to the one for the `z` instruction, but for the `y` instruction.**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The \"truth table\" in the main body for the `z` instruction listed what the `z` instruction does for qubits in each of the input states |0⟩, |1⟩, |+⟩, and |−⟩.\n", + "While that's overcomplete in the sense that you can infer what `z` does from its action on the |0⟩ or |1⟩ states alone (or on the |+⟩ and |−⟩ states alone), it's helpful to keep in mind, so let's write out the same here for `y`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket0 = qt.basis(2, 0)\n", + "ket1 = qt.basis(2, 1)\n", + "ket_plus = qt.Qobj([\n", + " [1],\n", + " [1]\n", + "]) / np.sqrt(2)\n", + "ket_minus = qt.Qobj([\n", + " [1],\n", + " [-1]\n", + "]) / np.sqrt(2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "qt.sigmay() * ket0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "qt.sigmay() * ket1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "qt.sigmay() * ket_plus" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "qt.sigmay() * ket_minus" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using these four results, you can complete now the table:\n", + "\n", + "| Input | Output |\n", + "|---|---|\n", + "| \\|0⟩ | i\\|0⟩ |\n", + "| \\|1⟩ | −i\\|1⟩ |\n", + "| \\|+⟩ | −i\\|−⟩ |\n", + "| \\|−⟩ | i\\|+⟩ |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise 6.4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**We've only checked that one measurement probability is still the same, but maybe the probabilities have changed for X or Y measurements.\n", + "To fully check that the global phase doesn't change anything, prepare the same state and rotation as in Listing 5.10 and check that the probabilities of measuring the state along the X or Y axis aren't changed by applying an `rz` instruction.**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Recall that the state $|\\psi\\rangle$ was prepared by an `rz` instruction acting on a qubit in the |0⟩ state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ket0 = qt.basis(2, 0)\n", + "ket1 = qt.basis(2, 1)\n", + "ket_plus = qt.Qobj([\n", + " [1],\n", + " [1]\n", + "]).unit()\n", + "ket_psi = qt.qip.operations.rz(np.pi / 3) * ket0\n", + "ket_psi" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To confirm that this state is indistinguishable from the |0⟩ state before applying a global phase, we can check that the overlap with the |+⟩ and $(|0\\rangle + i|1\\rangle) / \\sqrt{2}$ states is left the same (namely, that measurement probabilities are left at 50/50):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.abs((ket_plus.dag() * ket_psi)[0, 0]) ** 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "np.abs(((ket0 + 1j * ket1).unit().dag() * ket_psi)[0, 0]) ** 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise 6.5" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**The $\\left(\\left|00\\right\\rangle + \\left|11\\right\\rangle\\right) / \\sqrt{2}$ state that we've seen a few times now isn't the only example of an entangled state.\n", + "In fact, if you pick a two-qubit state at random, it is almost certainly going to be entangled.\n", + "Just as the computational basis $\\left\\{\\left|00\\right\\rangle, \\left|01\\right\\rangle, \\left|10\\right\\rangle, \\left|11\\right\\rangle\\right\\}$ is a particularly useful set of unentangled states, there's a set of four particular entangled states known as the _Bell basis_ after physicist John Stewart Bell.**\n", + "\n", + "| Name | Expansion in computational basis |\n", + "|---|---|\n", + "| \\|β00⟩ | (\\|00⟩ + \\|11⟩) / √2 |\n", + "| \\|β01⟩ | (\\|00⟩ − \\|11⟩) / √2 |\n", + "| \\|β10⟩ | (\\|01⟩ + \\|10⟩) / √2 |\n", + "| \\|β11⟩ | (\\|01⟩ − \\|10⟩) / √2 |\n", + "\n", + "**Using what you've learned about the `cnot` instruction and the Pauli instructions (`x`, `y`, and `z`), write programs to prepare each of the four Bell states in the table above.**\n", + "\n", + "*HINT*: Table 5.2 should be very helpful in this exercise." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this exercise, let's use the shiny new simulator that you put together during this Chapter!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import simulator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "device = simulator.Simulator(capacity=2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Recall that we can use the `h` and `cnot` instructions together to prepare a two-qubit register in a Bell pair." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with device.using_register(2) as (left, right):\n", + " left.h()\n", + " left.cnot(right)\n", + " device.dump()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To get the other three Bell basis states, we can use Pauli instructions on the first qubit alone." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with device.using_register(2) as (left, right):\n", + " left.h()\n", + " left.cnot(right)\n", + " \n", + " left.x()\n", + " \n", + " device.dump()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with device.using_register(2) as (left, right):\n", + " left.h()\n", + " left.cnot(right)\n", + " \n", + " left.z()\n", + " \n", + " device.dump()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with device.using_register(2) as (left, right):\n", + " left.h()\n", + " left.cnot(right)\n", + " \n", + " left.x()\n", + " left.z()\n", + " \n", + " device.dump()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that you could also have applied your Pauli instructions to the second qubit as well; this is a unique symmetry of the Bell basis states, and one of the things that makes them really neat to work with." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with device.using_register(2) as (left, right):\n", + " left.h()\n", + " left.cnot(right)\n", + " \n", + " right.x()\n", + " right.z()\n", + " \n", + " device.dump()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "----\n", + "### Exercise 6.6" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Try changing your operation or Eve's operation to convince yourself that you only get a |000⟩ state at the end if you undo the same operation that Eve applied to her qubit.**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import simulator\n", + "from teleport import teleport" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sim = simulator.Simulator(capacity=3)\n", + "with sim.using_register(3) as (msg, here, there):\n", + " msg.ry(0.123)\n", + " teleport(msg, here, there)\n", + "\n", + " there.h()\n", + " sim.dump() " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/ch06/interface.py b/ch06/interface.py index 0c165a7..db1cc53 100644 --- a/ch06/interface.py +++ b/ch06/interface.py @@ -1,77 +1,77 @@ -#!/bin/env python -# -*- coding: utf-8 -*- -## -# interface.py: Contains classes that define the interface to the qubit -# simulator in simulator.py. -## -# Copyright (c) Sarah Kaiser and Chris Granade. -# Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. -# Book ISBN 9781617296130. -# Code licensed under the MIT License. -## - -from abc import ABCMeta, abstractmethod -from contextlib import contextmanager - -class Qubit(metaclass=ABCMeta): - - @abstractmethod - def swap(self, swap_target: "Qubit"): pass - - @abstractmethod - def cnot(self, cnot_target: "Qubit"): pass - - @abstractmethod - def h(self): pass - - @abstractmethod - def x(self): pass - - @abstractmethod - def y(self): pass - - @abstractmethod - def z(self): pass - - @abstractmethod - def ry(self, angle: float): pass - - @abstractmethod - def measure(self) -> bool: pass - - @abstractmethod - def reset(self): pass - - -class QuantumDevice(metaclass=ABCMeta): - @abstractmethod - def allocate_qubit(self) -> Qubit: - pass - - @abstractmethod - def deallocate_qubit(self, qubit: Qubit): - pass - - @contextmanager - def using_qubit(self): - qubit = self.allocate_qubit() - try: - yield qubit - finally: - qubit.reset() - self.deallocate_qubit(qubit) - - - @contextmanager - def using_register(self, n_qubits=1): - qubits = [ - self.allocate_qubit() - for idx in range(n_qubits) - ] - try: - yield qubits - finally: - for qubit in qubits: - qubit.reset() - self.deallocate_qubit(qubit) +#!/bin/env python +# -*- coding: utf-8 -*- +## +# interface.py: Contains classes that define the interface to the qubit +# simulator in simulator.py. +## +# Copyright (c) Sarah Kaiser and Chris Granade. +# Code sample from the book "Learn Quantum Computing with Python and Q#" by +# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Book ISBN 9781617296130. +# Code licensed under the MIT License. +## + +from abc import ABCMeta, abstractmethod +from contextlib import contextmanager + +class Qubit(metaclass=ABCMeta): + + @abstractmethod + def swap(self, swap_target: "Qubit"): pass + + @abstractmethod + def cnot(self, cnot_target: "Qubit"): pass + + @abstractmethod + def h(self): pass + + @abstractmethod + def x(self): pass + + @abstractmethod + def y(self): pass + + @abstractmethod + def z(self): pass + + @abstractmethod + def ry(self, angle: float): pass + + @abstractmethod + def measure(self) -> bool: pass + + @abstractmethod + def reset(self): pass + + +class QuantumDevice(metaclass=ABCMeta): + @abstractmethod + def allocate_qubit(self) -> Qubit: + pass + + @abstractmethod + def deallocate_qubit(self, qubit: Qubit): + pass + + @contextmanager + def using_qubit(self): + qubit = self.allocate_qubit() + try: + yield qubit + finally: + qubit.reset() + self.deallocate_qubit(qubit) + + + @contextmanager + def using_register(self, n_qubits=1): + qubits = [ + self.allocate_qubit() + for idx in range(n_qubits) + ] + try: + yield qubits + finally: + for qubit in qubits: + qubit.reset() + self.deallocate_qubit(qubit) diff --git a/ch06/simulator.py b/ch06/simulator.py index c7bb682..5a637c4 100644 --- a/ch06/simulator.py +++ b/ch06/simulator.py @@ -1,132 +1,132 @@ -#!/bin/env python -# -*- coding: utf-8 -*- -## -# simulator.py: Defines a class that implements a multi-qubit simulator. -## -# Copyright (c) Sarah Kaiser and Chris Granade. -# Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. -# Book ISBN 9781617296130. -# Code licensed under the MIT License. -## - -from interface import QuantumDevice, Qubit -import qutip as qt -from qutip.qip.operations import hadamard_transform -import numpy as np -from typing import List - -KET_0 = qt.basis(2, 0) -H = hadamard_transform() - -class SimulatedQubit(Qubit): - qubit_id: int - parent: "Simulator" - - def __init__(self, parent_simulator: "Simulator", id: int): - self.qubit_id = id - self.parent = parent_simulator - - def h(self) -> None: - self.parent._apply(H, [self.qubit_id]) - - def measure(self) -> bool: - projectors = [ - qt.circuit.gate_expand_1toN( - qt.basis(2, outcome) * qt.basis(2, outcome).dag(), - self.parent.capacity, - self.qubit_id - ) - for outcome in (0, 1) - ] - post_measurement_states = [ - projector * self.parent.register_state - for projector in projectors - ] - probabilities = [ - post_measurement_state.norm() ** 2 - for post_measurement_state in post_measurement_states - ] - sample = np.random.choice([0, 1], p=probabilities) - self.parent.register_state = post_measurement_states[sample].unit() - return int(sample) - - def reset(self) -> None: - if self.measure(): self.x() - - def swap(self, target: Qubit) -> None: - self.parent._apply( - qt.swap(), - [self.qubit_id, target.qubit_id] - ) - - def cnot(self, target: Qubit) -> None: - self.parent._apply( - qt.cnot(), - [self.qubit_id, target.qubit_id] - ) - - def rx(self, theta: float) -> None: - self.parent._apply(qt.rx(theta), [self.qubit_id]) - - def ry(self, theta: float) -> None: - self.parent._apply(qt.ry(theta), [self.qubit_id]) - - def rz(self, theta: float) -> None: - self.parent._apply(qt.rz(theta), [self.qubit_id]) - - def x(self) -> None: - self.parent._apply(qt.sigmax(), [self.qubit_id]) - - def y(self) -> None: - self.parent._apply(qt.sigmay(), [self.qubit_id]) - - def z(self) -> None: - self.parent._apply(qt.sigmaz(), [self.qubit_id]) - -class Simulator(QuantumDevice): - capacity: int - available_qubits: List[SimulatedQubit] - register_state: qt.Qobj - def __init__(self, capacity=3): - self.capacity = capacity - self.available_qubits = [ - SimulatedQubit(self, idx) - for idx in range(capacity) - ] - self._sort_available() - self.register_state = qt.tensor( - *[ - qt.basis(2, 0) - for _ in range(capacity) - ] - ) - def _sort_available(self) -> None: - self.available_qubits = list(sorted( - self.available_qubits, - key=lambda qubit: qubit.qubit_id, - reverse=True - )) - - def allocate_qubit(self) -> SimulatedQubit: - if self.available_qubits: - return self.available_qubits.pop() - - def deallocate_qubit(self, qubit: SimulatedQubit): - self.available_qubits.append(qubit) - self._sort_available() - - def _apply(self, unitary: qt.Qobj, ids: List[int]): - if len(ids) == 1: - matrix = qt.circuit.gate_expand_1toN(unitary, - self.capacity, ids[0]) - elif len(ids) == 2: - matrix = qt.circuit.gate_expand_2toN(unitary, - self.capacity, *ids) - else: - raise ValueError("Only one- or two-qubit unitary matrices supported.") - - self.register_state = matrix * self.register_state - - def dump(self) -> None: - print(self.register_state) +#!/bin/env python +# -*- coding: utf-8 -*- +## +# simulator.py: Defines a class that implements a multi-qubit simulator. +## +# Copyright (c) Sarah Kaiser and Chris Granade. +# Code sample from the book "Learn Quantum Computing with Python and Q#" by +# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Book ISBN 9781617296130. +# Code licensed under the MIT License. +## + +from interface import QuantumDevice, Qubit +import qutip as qt +from qutip.qip.operations import hadamard_transform +import numpy as np +from typing import List + +KET_0 = qt.basis(2, 0) +H = hadamard_transform() + +class SimulatedQubit(Qubit): + qubit_id: int + parent: "Simulator" + + def __init__(self, parent_simulator: "Simulator", id: int): + self.qubit_id = id + self.parent = parent_simulator + + def h(self) -> None: + self.parent._apply(H, [self.qubit_id]) + + def measure(self) -> bool: + projectors = [ + qt.circuit.gate_expand_1toN( + qt.basis(2, outcome) * qt.basis(2, outcome).dag(), + self.parent.capacity, + self.qubit_id + ) + for outcome in (0, 1) + ] + post_measurement_states = [ + projector * self.parent.register_state + for projector in projectors + ] + probabilities = [ + post_measurement_state.norm() ** 2 + for post_measurement_state in post_measurement_states + ] + sample = np.random.choice([0, 1], p=probabilities) + self.parent.register_state = post_measurement_states[sample].unit() + return int(sample) + + def reset(self) -> None: + if self.measure(): self.x() + + def swap(self, target: Qubit) -> None: + self.parent._apply( + qt.swap(), + [self.qubit_id, target.qubit_id] + ) + + def cnot(self, target: Qubit) -> None: + self.parent._apply( + qt.cnot(), + [self.qubit_id, target.qubit_id] + ) + + def rx(self, theta: float) -> None: + self.parent._apply(qt.rx(theta), [self.qubit_id]) + + def ry(self, theta: float) -> None: + self.parent._apply(qt.ry(theta), [self.qubit_id]) + + def rz(self, theta: float) -> None: + self.parent._apply(qt.rz(theta), [self.qubit_id]) + + def x(self) -> None: + self.parent._apply(qt.sigmax(), [self.qubit_id]) + + def y(self) -> None: + self.parent._apply(qt.sigmay(), [self.qubit_id]) + + def z(self) -> None: + self.parent._apply(qt.sigmaz(), [self.qubit_id]) + +class Simulator(QuantumDevice): + capacity: int + available_qubits: List[SimulatedQubit] + register_state: qt.Qobj + def __init__(self, capacity=3): + self.capacity = capacity + self.available_qubits = [ + SimulatedQubit(self, idx) + for idx in range(capacity) + ] + self._sort_available() + self.register_state = qt.tensor( + *[ + qt.basis(2, 0) + for _ in range(capacity) + ] + ) + def _sort_available(self) -> None: + self.available_qubits = list(sorted( + self.available_qubits, + key=lambda qubit: qubit.qubit_id, + reverse=True + )) + + def allocate_qubit(self) -> SimulatedQubit: + if self.available_qubits: + return self.available_qubits.pop() + + def deallocate_qubit(self, qubit: SimulatedQubit): + self.available_qubits.append(qubit) + self._sort_available() + + def _apply(self, unitary: qt.Qobj, ids: List[int]): + if len(ids) == 1: + matrix = qt.circuit.gate_expand_1toN(unitary, + self.capacity, ids[0]) + elif len(ids) == 2: + matrix = qt.circuit.gate_expand_2toN(unitary, + self.capacity, *ids) + else: + raise ValueError("Only one- or two-qubit unitary matrices supported.") + + self.register_state = matrix * self.register_state + + def dump(self) -> None: + print(self.register_state) diff --git a/ch06/teleport.py b/ch06/teleport.py index c673b32..d75cf0e 100644 --- a/ch06/teleport.py +++ b/ch06/teleport.py @@ -1,38 +1,38 @@ -#!/bin/env python -# -*- coding: utf-8 -*- -## -# teleport.py: Implements a quantum teleportation program using the simulator -# in simulator.py with the interface defined in interface.py. -## -# Copyright (c) Sarah Kaiser and Chris Granade. -# Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. -# Book ISBN 9781617296130. -# Code licensed under the MIT License. -## - -from interface import QuantumDevice, Qubit -from simulator import Simulator - -def teleport(msg: Qubit, here: Qubit, there: Qubit) -> None: - here.h() - here.cnot(there) - - # ... - msg.cnot(here) - msg.h() - - if msg.measure(): there.z() - if here.measure(): there.x() - - msg.reset() - here.reset() - -if __name__ == "__main__": - sim = Simulator(capacity=3) - with sim.using_register(3) as (msg, here, there): - msg.ry(0.123) - teleport(msg, here, there) - - there.ry(-0.123) - sim.dump() +#!/bin/env python +# -*- coding: utf-8 -*- +## +# teleport.py: Implements a quantum teleportation program using the simulator +# in simulator.py with the interface defined in interface.py. +## +# Copyright (c) Sarah Kaiser and Chris Granade. +# Code sample from the book "Learn Quantum Computing with Python and Q#" by +# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Book ISBN 9781617296130. +# Code licensed under the MIT License. +## + +from interface import QuantumDevice, Qubit +from simulator import Simulator + +def teleport(msg: Qubit, here: Qubit, there: Qubit) -> None: + here.h() + here.cnot(there) + + # ... + msg.cnot(here) + msg.h() + + if msg.measure(): there.z() + if here.measure(): there.x() + + msg.reset() + here.reset() + +if __name__ == "__main__": + sim = Simulator(capacity=3) + with sim.using_register(3) as (msg, here, there): + msg.ry(0.123) + teleport(msg, here, there) + + there.ry(-0.123) + sim.dump() diff --git a/ch07/BiasedQrng/BiasedQrng.csproj b/ch07/BiasedQrng/BiasedQrng.csproj index b496e26..bada07c 100644 --- a/ch07/BiasedQrng/BiasedQrng.csproj +++ b/ch07/BiasedQrng/BiasedQrng.csproj @@ -1,9 +1,9 @@ - - - - Exe - netcoreapp3.1 - x64 - - - + + + + Exe + net6.0 + x64 + + + diff --git a/ch07/BiasedQrng/Operation.qs b/ch07/BiasedQrng/Operation.qs index 9880afb..d2bce69 100644 --- a/ch07/BiasedQrng/Operation.qs +++ b/ch07/BiasedQrng/Operation.qs @@ -1,49 +1,49 @@ -// Operation.qs: Sample code for a biased quantum random number generator -// (Chapter 7). -// -// Copyright (c) Sarah Kaiser and Chris Granade. -// Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. -// Book ISBN 9781617296130. -// Code licensed under the MIT License. - -namespace Qrng { - open Microsoft.Quantum.Intrinsic; - - open Microsoft.Quantum.Math; - open Microsoft.Quantum.Measurement; - - operation PrepareBiasedCoin(winProbability : Double, qubit : Qubit) - : Unit { - let rotationAngle = 2.0 * ArcCos( - Sqrt(1.0 - winProbability)); - Ry(rotationAngle, qubit); - } - - operation GetNextRandomBit(statePreparation : (Qubit => Unit)) - : Result { - use qubit = Qubit(); - statePreparation(qubit); - return MResetZ(qubit); - } - - operation PlayMorganasGame(winProbability : Double) : Unit { - mutable nRounds = 0; - mutable done = false; - let prep = PrepareBiasedCoin( - winProbability, _); - repeat { - set nRounds = nRounds + 1; - set done = (GetNextRandomBit(prep) == Zero); - } - until done; - - Message($"It took Lancelot {nRounds} turns to get home."); - } - - @EntryPoint() - operation RunPlayMorganasGame() : Unit { - PlayMorganasGame(0.95); - } - -} +// Operation.qs: Sample code for a biased quantum random number generator +// (Chapter 7). +// +// Copyright (c) Sarah Kaiser and Chris Granade. +// Code sample from the book "Learn Quantum Computing with Python and Q#" by +// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Book ISBN 9781617296130. +// Code licensed under the MIT License. + +namespace Qrng { + open Microsoft.Quantum.Intrinsic; + + open Microsoft.Quantum.Math; + open Microsoft.Quantum.Measurement; + + operation PrepareBiasedCoin(winProbability : Double, qubit : Qubit) + : Unit { + let rotationAngle = 2.0 * ArcCos( + Sqrt(1.0 - winProbability)); + Ry(rotationAngle, qubit); + } + + operation GetNextRandomBit(statePreparation : (Qubit => Unit)) + : Result { + use qubit = Qubit(); + statePreparation(qubit); + return MResetZ(qubit); + } + + operation PlayMorganasGame(winProbability : Double) : Unit { + mutable nRounds = 0; + mutable done = false; + let prep = PrepareBiasedCoin( + winProbability, _); + repeat { + set nRounds = nRounds + 1; + set done = (GetNextRandomBit(prep) == Zero); + } + until done; + + Message($"It took Lancelot {nRounds} turns to get home."); + } + + @EntryPoint() + operation RunPlayMorganasGame() : Unit { + PlayMorganasGame(0.95); + } + +} diff --git a/ch07/BiasedQrng/README.md b/ch07/BiasedQrng/README.md index 5cd41f0..2e207f8 100644 --- a/ch07/BiasedQrng/README.md +++ b/ch07/BiasedQrng/README.md @@ -1,10 +1,10 @@ -# Biased QRNG as a Standalone Q# Application - -This sample shows how to use the **BiasedQrng** program from Chapter 7 as a Q# standalone application, rather than as a Jupyter Notebok. - -To run this program using the .NET Core SDK: - -```dotnetcli -cd BiasedQrng -dotnet run -``` +# Biased QRNG as a Standalone Q# Application + +This sample shows how to use the **BiasedQrng** program from Chapter 7 as a Q# standalone application, rather than as a Jupyter Notebok. + +To run this program using the .NET Core SDK: + +```dotnetcli +cd BiasedQrng +dotnet run +``` diff --git a/ch07/ClassicalHello/ClassicalHello.csproj b/ch07/ClassicalHello/ClassicalHello.csproj index b496e26..bada07c 100644 --- a/ch07/ClassicalHello/ClassicalHello.csproj +++ b/ch07/ClassicalHello/ClassicalHello.csproj @@ -1,9 +1,9 @@ - - - - Exe - netcoreapp3.1 - x64 - - - + + + + Exe + net6.0 + x64 + + + diff --git a/ch07/ClassicalHello/EntryPoint.qs b/ch07/ClassicalHello/EntryPoint.qs index 45c7376..3722b89 100644 --- a/ch07/ClassicalHello/EntryPoint.qs +++ b/ch07/ClassicalHello/EntryPoint.qs @@ -1,15 +1,15 @@ -// Operation.qs: Demo of the Message function used to make a HelloWorld program -// (Chapter 7). -// -// Copyright (c) Sarah Kaiser and Chris Granade. -// Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. -// Book ISBN 9781617296130. -// Code licensed under the MIT License. - -namespace ClassicalHello { - @EntryPoint() - operation RunHelloWorld() : Unit { - HelloWorld(); - } -} +// Operation.qs: Demo of the Message function used to make a HelloWorld program +// (Chapter 7). +// +// Copyright (c) Sarah Kaiser and Chris Granade. +// Code sample from the book "Learn Quantum Computing with Python and Q#" by +// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Book ISBN 9781617296130. +// Code licensed under the MIT License. + +namespace ClassicalHello { + @EntryPoint() + operation RunHelloWorld() : Unit { + HelloWorld(); + } +} diff --git a/ch07/ClassicalHello/Operation.qs b/ch07/ClassicalHello/Operation.qs index 5cbf698..ac3e508 100644 --- a/ch07/ClassicalHello/Operation.qs +++ b/ch07/ClassicalHello/Operation.qs @@ -1,16 +1,16 @@ -// Operation.qs: Demo of the Message function used to make a HelloWorld program -// (Chapter 7). -// -// Copyright (c) Sarah Kaiser and Chris Granade. -// Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. -// Book ISBN 9781617296130. -// Code licensed under the MIT License. - -namespace ClassicalHello { - open Microsoft.Quantum.Intrinsic; - - function HelloWorld() : Unit { - Message("Hello, classical world!"); - } -} +// Operation.qs: Demo of the Message function used to make a HelloWorld program +// (Chapter 7). +// +// Copyright (c) Sarah Kaiser and Chris Granade. +// Code sample from the book "Learn Quantum Computing with Python and Q#" by +// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Book ISBN 9781617296130. +// Code licensed under the MIT License. + +namespace ClassicalHello { + open Microsoft.Quantum.Intrinsic; + + function HelloWorld() : Unit { + Message("Hello, classical world!"); + } +} diff --git a/ch07/ClassicalHello/README.md b/ch07/ClassicalHello/README.md index bcc69e1..342a3d2 100644 --- a/ch07/ClassicalHello/README.md +++ b/ch07/ClassicalHello/README.md @@ -1,10 +1,10 @@ -# Hello, World! as a Standalone Q# Application - -This sample shows how to use the **ClassicalHello** program from Chapter 7 as a Q# standalone application, rather than as a Jupyter Notebook. - -To run this program using the .NET Core SDK: - -```dotnetcli -cd ClassicalHello -dotnet run -``` +# Hello, World! as a Standalone Q# Application + +This sample shows how to use the **ClassicalHello** program from Chapter 7 as a Q# standalone application, rather than as a Jupyter Notebook. + +To run this program using the .NET Core SDK: + +```dotnetcli +cd ClassicalHello +dotnet run +``` diff --git a/ch07/Qrng/Operation.qs b/ch07/Qrng/Operation.qs index 5fef457..1cecb06 100644 --- a/ch07/Qrng/Operation.qs +++ b/ch07/Qrng/Operation.qs @@ -1,32 +1,32 @@ -// Operation.qs: Sample code for a quantum random number generator (Chapter 7). -// -// Copyright (c) Sarah Kaiser and Chris Granade. -// Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. -// Book ISBN 9781617296130. -// Code licensed under the MIT License. - -namespace Qrng { - open Microsoft.Quantum.Intrinsic; - - operation GetNextRandomBit() : Result { - use qubit = Qubit(); - H(qubit); - return M(qubit); - } - - @EntryPoint() - operation PlayMorganasGame() : Unit { - mutable nRounds = 0; - mutable done = false; - repeat { - set nRounds = nRounds + 1; - set done = - (GetNextRandomBit() == Zero); - } - until done; - - Message($"It took Lancelot {nRounds} turns to get home."); - } - -} +// Operation.qs: Sample code for a quantum random number generator (Chapter 7). +// +// Copyright (c) Sarah Kaiser and Chris Granade. +// Code sample from the book "Learn Quantum Computing with Python and Q#" by +// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Book ISBN 9781617296130. +// Code licensed under the MIT License. + +namespace Qrng { + open Microsoft.Quantum.Intrinsic; + + operation GetNextRandomBit() : Result { + use qubit = Qubit(); + H(qubit); + return M(qubit); + } + + @EntryPoint() + operation PlayMorganasGame() : Unit { + mutable nRounds = 0; + mutable done = false; + repeat { + set nRounds = nRounds + 1; + set done = + (GetNextRandomBit() == Zero); + } + until done; + + Message($"It took Lancelot {nRounds} turns to get home."); + } + +} diff --git a/ch07/Qrng/Qrng.csproj b/ch07/Qrng/Qrng.csproj index b496e26..bada07c 100644 --- a/ch07/Qrng/Qrng.csproj +++ b/ch07/Qrng/Qrng.csproj @@ -1,9 +1,9 @@ - - - - Exe - netcoreapp3.1 - x64 - - - + + + + Exe + net6.0 + x64 + + + diff --git a/ch07/Qrng/README.md b/ch07/Qrng/README.md index 0947489..a66f4eb 100644 --- a/ch07/Qrng/README.md +++ b/ch07/Qrng/README.md @@ -1,10 +1,10 @@ -# QRNG as a Standalone Q# Application - -This sample shows how to use the **Qrng** program from Chapter 7 as a Q# standalone application, rather than as a Jupyter Notebook. - -To run this program using the .NET Core SDK: - -```dotnetcli -cd Qrng -dotnet run -``` +# QRNG as a Standalone Q# Application + +This sample shows how to use the **Qrng** program from Chapter 7 as a Q# standalone application, rather than as a Jupyter Notebook. + +To run this program using the .NET Core SDK: + +```dotnetcli +cd Qrng +dotnet run +``` diff --git a/ch07/ch07-exercise-solutions.ipynb b/ch07/ch07-exercise-solutions.ipynb index 3502752..b3c430d 100644 --- a/ch07/ch07-exercise-solutions.ipynb +++ b/ch07/ch07-exercise-solutions.ipynb @@ -220,21 +220,21 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { - "application/json": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.17.2105143879\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v3.1\"}]}", + "application/x-qsharp-data": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.24.210930\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v6.0\"}]}", "text/html": [ - "
ComponentVersion
iqsharp0.17.2105143879
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v3.1
" + "
ComponentVersion
iqsharp0.24.210930
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v6.0
" ], "text/plain": [ - "Component Version\r\n", - "------------ ------------------------\r\n", - "iqsharp 0.17.2105143879\r\n", - "Jupyter Core 1.5.0.0\r\n", - ".NET Runtime .NETCoreApp,Version=v3.1\r\n" + "Component Version\n", + "------------ ------------------------\n", + "iqsharp 0.24.210930\n", + "Jupyter Core 1.5.0.0\n", + ".NET Runtime .NETCoreApp,Version=v6.0\n" ] }, "metadata": {}, @@ -244,6 +244,13 @@ "source": [ "%version" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -256,7 +263,7 @@ "file_extension": ".qs", "mimetype": "text/x-qsharp", "name": "qsharp", - "version": "0.14" + "version": "0.24" } }, "nbformat": 4, diff --git a/ch07/chapter-07.ipynb b/ch07/chapter-07.ipynb index 48bcbbc..2138679 100644 --- a/ch07/chapter-07.ipynb +++ b/ch07/chapter-07.ipynb @@ -28,7 +28,7 @@ "outputs": [ { "data": { - "application/json": "[\"HelloWorld\"]", + "application/x-qsharp-data": "[\"HelloWorld\"]", "text/html": [ "" ], @@ -56,12 +56,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "Hello, classical world!\r\n" + "Hello, classical world!\n" ] }, { "data": { - "application/json": "{\"@type\":\"tuple\"}", + "application/x-qsharp-data": "{\"@type\":\"tuple\"}", "text/plain": [ "()" ] @@ -89,7 +89,7 @@ "outputs": [ { "data": { - "application/json": "[\"GetNextRandomBit\",\"PlayMorganasGame\"]", + "application/x-qsharp-data": "[\"GetNextRandomBit\",\"PlayMorganasGame\"]", "text/html": [ "" ], @@ -132,12 +132,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "It took Lancelot 1 turns to get home.\r\n" + "It took Lancelot 1 turns to get home.\n" ] }, { "data": { - "application/json": "{\"@type\":\"tuple\"}", + "application/x-qsharp-data": "{\"@type\":\"tuple\"}", "text/plain": [ "()" ] @@ -165,7 +165,7 @@ "outputs": [ { "data": { - "application/json": "[\"PrepareBiasedCoin\",\"GetNextRandomBit\",\"PlayMorganasGame\"]", + "application/x-qsharp-data": "[\"PrepareBiasedCoin\",\"GetNextRandomBit\",\"PlayMorganasGame\"]", "text/html": [ "" ], @@ -237,12 +237,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "It took Lancelot 419 turns to get home.\r\n" + "It took Lancelot 565 turns to get home.\n" ] }, { "data": { - "application/json": "{\"@type\":\"tuple\"}", + "application/x-qsharp-data": "{\"@type\":\"tuple\"}", "text/plain": [ "()" ] @@ -270,16 +270,16 @@ "outputs": [ { "data": { - "application/json": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.17.2105143879\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v3.1\"}]}", + "application/x-qsharp-data": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.24.210930\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v6.0\"}]}", "text/html": [ - "
ComponentVersion
iqsharp0.17.2105143879
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v3.1
" + "
ComponentVersion
iqsharp0.24.210930
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v6.0
" ], "text/plain": [ - "Component Version\r\n", - "------------ ------------------------\r\n", - "iqsharp 0.17.2105143879\r\n", - "Jupyter Core 1.5.0.0\r\n", - ".NET Runtime .NETCoreApp,Version=v3.1\r\n" + "Component Version\n", + "------------ ------------------------\n", + "iqsharp 0.24.210930\n", + "Jupyter Core 1.5.0.0\n", + ".NET Runtime .NETCoreApp,Version=v6.0\n" ] }, "metadata": {}, @@ -289,6 +289,13 @@ "source": [ "%version" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -301,7 +308,7 @@ "file_extension": ".qs", "mimetype": "text/x-qsharp", "name": "qsharp", - "version": "0.14" + "version": "0.24" } }, "nbformat": 4, diff --git a/ch08/Algorithm.qs b/ch08/Algorithm.qs index e4a1719..ed772b9 100644 --- a/ch08/Algorithm.qs +++ b/ch08/Algorithm.qs @@ -1,43 +1,43 @@ -// Algorithm.qs: Sample code for Deutsch Jozsa algorithm (Chapter 8). -// -// Copyright (c) Sarah Kaiser and Chris Granade. -// Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. -// Book ISBN 9781617296130. -// Code licensed under the MIT License. - -namespace DeutschJozsa { - open Microsoft.Quantum.Intrinsic; - open Microsoft.Quantum.Measurement; - open Microsoft.Quantum.Diagnostics; - - operation CheckIfOracleIsBalanced(oracle : ((Qubit, Qubit) => Unit)) - : Bool { - use control = Qubit(); - use target = Qubit(); - - H(control); - X(target); - H(target); - - oracle(control, target); - - H(target); - X(target); - - return MResetX(control) == One; - } - - operation RunDeutschJozsaAlgorithm() : Unit { - Fact(not CheckIfOracleIsBalanced(ApplyZeroOracle), - "Test failed for zero oracle."); - Fact(not CheckIfOracleIsBalanced(ApplyOneOracle), - "Test failed for one oracle."); - Fact(CheckIfOracleIsBalanced(ApplyIdOracle), - "Test failed for id oracle."); - Fact(CheckIfOracleIsBalanced(ApplyNotOracle), - "Test failed for not oracle."); - - Message("All tests passed!"); - } -} +// Algorithm.qs: Sample code for Deutsch Jozsa algorithm (Chapter 8). +// +// Copyright (c) Sarah Kaiser and Chris Granade. +// Code sample from the book "Learn Quantum Computing with Python and Q#" by +// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Book ISBN 9781617296130. +// Code licensed under the MIT License. + +namespace DeutschJozsa { + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Measurement; + open Microsoft.Quantum.Diagnostics; + + operation CheckIfOracleIsBalanced(oracle : ((Qubit, Qubit) => Unit)) + : Bool { + use control = Qubit(); + use target = Qubit(); + + H(control); + X(target); + H(target); + + oracle(control, target); + + H(target); + X(target); + + return MResetX(control) == One; + } + + operation RunDeutschJozsaAlgorithm() : Unit { + Fact(not CheckIfOracleIsBalanced(ApplyZeroOracle), + "Test failed for zero oracle."); + Fact(not CheckIfOracleIsBalanced(ApplyOneOracle), + "Test failed for one oracle."); + Fact(CheckIfOracleIsBalanced(ApplyIdOracle), + "Test failed for id oracle."); + Fact(CheckIfOracleIsBalanced(ApplyNotOracle), + "Test failed for not oracle."); + + Message("All tests passed!"); + } +} diff --git a/ch08/DeutschJozsa.ipynb b/ch08/DeutschJozsa.ipynb index 99df158..3803d65 100644 --- a/ch08/DeutschJozsa.ipynb +++ b/ch08/DeutschJozsa.ipynb @@ -17,7 +17,7 @@ "outputs": [ { "data": { - "application/json": "[\"RunDeutschJozsaAlgorithm\"]", + "application/x-qsharp-data": "[\"RunDeutschJozsaAlgorithm\"]", "text/html": [ "" ], @@ -53,12 +53,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "All tests passed!\r\n" + "All tests passed!\n" ] }, { "data": { - "application/json": "{\"@type\":\"tuple\"}", + "application/x-qsharp-data": "{\"@type\":\"tuple\"}", "text/plain": [ "()" ] @@ -79,16 +79,16 @@ "outputs": [ { "data": { - "application/json": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.17.2105143879\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v3.1\"}]}", + "application/x-qsharp-data": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.24.210930\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v6.0\"}]}", "text/html": [ - "
ComponentVersion
iqsharp0.17.2105143879
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v3.1
" + "
ComponentVersion
iqsharp0.24.210930
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v6.0
" ], "text/plain": [ - "Component Version\r\n", - "------------ ------------------------\r\n", - "iqsharp 0.17.2105143879\r\n", - "Jupyter Core 1.5.0.0\r\n", - ".NET Runtime .NETCoreApp,Version=v3.1\r\n" + "Component Version\n", + "------------ ------------------------\n", + "iqsharp 0.24.210930\n", + "Jupyter Core 1.5.0.0\n", + ".NET Runtime .NETCoreApp,Version=v6.0\n" ] }, "metadata": {}, @@ -98,6 +98,13 @@ "source": [ "%version" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -110,7 +117,7 @@ "file_extension": ".qs", "mimetype": "text/x-qsharp", "name": "qsharp", - "version": "0.14" + "version": "0.24" } }, "nbformat": 4, diff --git a/ch08/Oracles.qs b/ch08/Oracles.qs index d4801ce..a45fac7 100644 --- a/ch08/Oracles.qs +++ b/ch08/Oracles.qs @@ -1,29 +1,29 @@ -// Oracles.qs: Sample code for oracles used in the one bit version of the -// Deutsch Jozsa algorithim (Chapter 8). -// -// Copyright (c) Sarah Kaiser and Chris Granade. -// Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. -// Book ISBN 9781617296130. -// Code licensed under the MIT License. - -namespace DeutschJozsa { - open Microsoft.Quantum.Intrinsic; - - operation ApplyZeroOracle(control : Qubit, target : Qubit) : Unit { - } - - operation ApplyOneOracle(control : Qubit, target : Qubit) : Unit { - X(target); - } - - operation ApplyIdOracle(control : Qubit, target : Qubit) : Unit { - CNOT(control, target); - } - - operation ApplyNotOracle(control : Qubit, target : Qubit) : Unit { - X(control); - CNOT(control, target); - X(control); - } +// Oracles.qs: Sample code for oracles used in the one bit version of the +// Deutsch Jozsa algorithim (Chapter 8). +// +// Copyright (c) Sarah Kaiser and Chris Granade. +// Code sample from the book "Learn Quantum Computing with Python and Q#" by +// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Book ISBN 9781617296130. +// Code licensed under the MIT License. + +namespace DeutschJozsa { + open Microsoft.Quantum.Intrinsic; + + operation ApplyZeroOracle(control : Qubit, target : Qubit) : Unit { + } + + operation ApplyOneOracle(control : Qubit, target : Qubit) : Unit { + X(target); + } + + operation ApplyIdOracle(control : Qubit, target : Qubit) : Unit { + CNOT(control, target); + } + + operation ApplyNotOracle(control : Qubit, target : Qubit) : Unit { + X(control); + CNOT(control, target); + X(control); + } } \ No newline at end of file diff --git a/ch08/ch08-exercise-solutions.ipynb b/ch08/ch08-exercise-solutions.ipynb index cefadc4..62ad839 100644 --- a/ch08/ch08-exercise-solutions.ipynb +++ b/ch08/ch08-exercise-solutions.ipynb @@ -55,16 +55,16 @@ "outputs": [ { "data": { - "application/json": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.17.2105143879\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v3.1\"}]}", + "application/x-qsharp-data": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.24.210930\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v6.0\"}]}", "text/html": [ - "
ComponentVersion
iqsharp0.17.2105143879
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v3.1
" + "
ComponentVersion
iqsharp0.24.210930
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v6.0
" ], "text/plain": [ - "Component Version\r\n", - "------------ ------------------------\r\n", - "iqsharp 0.17.2105143879\r\n", - "Jupyter Core 1.5.0.0\r\n", - ".NET Runtime .NETCoreApp,Version=v3.1\r\n" + "Component Version\n", + "------------ ------------------------\n", + "iqsharp 0.24.210930\n", + "Jupyter Core 1.5.0.0\n", + ".NET Runtime .NETCoreApp,Version=v6.0\n" ] }, "metadata": {}, @@ -74,6 +74,13 @@ "source": [ "%version" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -86,7 +93,7 @@ "file_extension": ".qs", "mimetype": "text/x-qsharp", "name": "qsharp", - "version": "0.14" + "version": "0.24" } }, "nbformat": 4, diff --git a/ch09/ch09-exercise-solutions.ipynb b/ch09/ch09-exercise-solutions.ipynb index c04be0d..fcb8f8a 100644 --- a/ch09/ch09-exercise-solutions.ipynb +++ b/ch09/ch09-exercise-solutions.ipynb @@ -591,19 +591,19 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "{'iqsharp': LooseVersion ('0.17.2105143879'),\n", + "{'iqsharp': LooseVersion ('0.24.210930'),\n", " 'Jupyter Core': LooseVersion ('1.5.0.0'),\n", - " '.NET Runtime': LooseVersion ('.NETCoreApp,Version=v3.1'),\n", - " 'qsharp': LooseVersion ('0.17.2105.143879')}" + " '.NET Runtime': LooseVersion ('.NETCoreApp,Version=v6.0'),\n", + " 'qsharp': LooseVersion ('0.24.210930')}" ] }, - "execution_count": 29, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } @@ -615,7 +615,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -629,7 +629,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.10" + "version": "3.7.13" } }, "nbformat": 4, diff --git a/ch09/host.ipynb b/ch09/host.ipynb index dff58a4..e6747ef 100644 --- a/ch09/host.ipynb +++ b/ch09/host.ipynb @@ -24,15 +24,15 @@ "name": "stdout", "output_type": "stream", "text": [ - "Pssst the hidden angle is 4.592779466918025, good luck!\n", - "The hidden angle you think was [4.5875249]!\n", - "Pssst the hidden angle is 2.263224791872852, good luck!\n", - "The hidden angle you think was [2.27486485]!\n" + "Pssst the hidden angle is 1.7443058899536954, good luck!\n", + "The hidden angle you think was [1.75061279]!\n", + "Pssst the hidden angle is 2.3045789938647823, good luck!\n", + "The hidden angle you think was [2.30430371]!\n" ] }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -44,7 +44,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -78,10 +78,10 @@ { "data": { "text/plain": [ - "{'iqsharp': LooseVersion ('0.17.2105143879'),\n", + "{'iqsharp': LooseVersion ('0.24.210930'),\n", " 'Jupyter Core': LooseVersion ('1.5.0.0'),\n", - " '.NET Runtime': LooseVersion ('.NETCoreApp,Version=v3.1'),\n", - " 'qsharp': LooseVersion ('0.17.2105.143879')}" + " '.NET Runtime': LooseVersion ('.NETCoreApp,Version=v6.0'),\n", + " 'qsharp': LooseVersion ('0.24.210930')}" ] }, "execution_count": 2, @@ -92,11 +92,18 @@ "source": [ "qsharp.component_versions()" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -110,7 +117,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.10" + "version": "3.7.13" } }, "nbformat": 4, diff --git a/ch09/host.py b/ch09/host.py index 033f04e..8ae14a4 100644 --- a/ch09/host.py +++ b/ch09/host.py @@ -1,58 +1,58 @@ -#!/bin/env python -# -*- coding: utf-8 -*- -## -# host.py: Runs the host program for the phase estimation quantum algorithm. -## -# Copyright (c) Sarah Kaiser and Chris Granade. -# Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. -# Book ISBN 9781617296130. -# Code licensed under the MIT License. -## - -import qsharp -from PhaseEstimation import RunGame, RunGameUsingControlledRotations - -from typing import Any -import scipy.optimize as optimization -import numpy as np - -BIGGEST_ANGLE = 2 * np.pi - -def run_game_at_scales(scales: np.ndarray, - n_measurements_per_scale: int = 100, - control: bool = False - ) -> Any: - hidden_angle = np.random.random() * BIGGEST_ANGLE - print(f"Pssst the hidden angle is {hidden_angle}, good luck!") - return ( - RunGameUsingControlledRotations - if control else RunGame - ).simulate( - hiddenAngle=hidden_angle, - nMeasurementsPerScale=n_measurements_per_scale, - scales=list(scales) - ) - -if __name__ == "__main__": - import matplotlib.pyplot as plt - scales = np.linspace(0, 2, 101) - for control in (False, True): - data = run_game_at_scales(scales, control=control) - - def rotation_model(scale, angle): - return np.sin(angle * scale / 2) ** 2 - angle_guess, est_error = optimization.curve_fit( - rotation_model, scales, data, BIGGEST_ANGLE / 2, - bounds=[0, BIGGEST_ANGLE] - ) - print(f"The hidden angle you think was {angle_guess}!") - - plt.figure() - plt.plot(scales, data, 'o') - plt.title("Probability of Lancelot measuring One at each scale") - plt.xlabel("Lancelot's input scale value") - plt.ylabel("Lancelot's probability of measuring a One") - plt.plot(scales, rotation_model(scales, angle_guess)) - - plt.show() +#!/bin/env python +# -*- coding: utf-8 -*- +## +# host.py: Runs the host program for the phase estimation quantum algorithm. +## +# Copyright (c) Sarah Kaiser and Chris Granade. +# Code sample from the book "Learn Quantum Computing with Python and Q#" by +# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Book ISBN 9781617296130. +# Code licensed under the MIT License. +## + +import qsharp +from PhaseEstimation import RunGame, RunGameUsingControlledRotations + +from typing import Any +import scipy.optimize as optimization +import numpy as np + +BIGGEST_ANGLE = 2 * np.pi + +def run_game_at_scales(scales: np.ndarray, + n_measurements_per_scale: int = 100, + control: bool = False + ) -> Any: + hidden_angle = np.random.random() * BIGGEST_ANGLE + print(f"Pssst the hidden angle is {hidden_angle}, good luck!") + return ( + RunGameUsingControlledRotations + if control else RunGame + ).simulate( + hiddenAngle=hidden_angle, + nMeasurementsPerScale=n_measurements_per_scale, + scales=list(scales) + ) + +if __name__ == "__main__": + import matplotlib.pyplot as plt + scales = np.linspace(0, 2, 101) + for control in (False, True): + data = run_game_at_scales(scales, control=control) + + def rotation_model(scale, angle): + return np.sin(angle * scale / 2) ** 2 + angle_guess, est_error = optimization.curve_fit( + rotation_model, scales, data, BIGGEST_ANGLE / 2, + bounds=[0, BIGGEST_ANGLE] + ) + print(f"The hidden angle you think was {angle_guess}!") + + plt.figure() + plt.plot(scales, data, 'o') + plt.title("Probability of Lancelot measuring One at each scale") + plt.xlabel("Lancelot's input scale value") + plt.ylabel("Lancelot's probability of measuring a One") + plt.plot(scales, rotation_model(scales, angle_guess)) + + plt.show() diff --git a/ch09/operations.qs b/ch09/operations.qs index d70b2e0..c71afd5 100644 --- a/ch09/operations.qs +++ b/ch09/operations.qs @@ -1,108 +1,108 @@ -// operations.qs: Sample code for Phase Estimation (Chapter 9). -// -// Copyright (c) Sarah Kaiser and Chris Granade. -// Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. -// Book ISBN 9781617296130. -// Code licensed under the MIT License. - -namespace PhaseEstimation { - open Microsoft.Quantum.Intrinsic; - open Microsoft.Quantum.Convert as Convert; - open Microsoft.Quantum.Measurement as Meas; - open Microsoft.Quantum.Arrays as Arrays; - - operation ApplyScaledRotation( - angle : Double, scale : Double, - target : Qubit) - : Unit is Adj + Ctl { - R1(angle * scale, target); - } - - newtype ScalableOperation = ( - Apply: ((Double, Qubit) => Unit is Adj + Ctl) - ); - - function HiddenRotation(hiddenAngle : Double) - : ScalableOperation { - return ScalableOperation( - ApplyScaledRotation(hiddenAngle, _, _) - ); - } - - operation EstimateProbabilityAtScale( - scale : Double, - nMeasurements : Int, - op : ScalableOperation) - : Double { - mutable nOnes = 0; - for idx in 0..nMeasurements - 1 { - use target = Qubit(); - within { - H(target); - } apply { - op::Apply(scale, target); - } - set nOnes += Meas.MResetZ(target) == One - ? 1 | 0; - } - return Convert.IntAsDouble(nOnes) / - Convert.IntAsDouble(nMeasurements); - } - - operation RunGame( - hiddenAngle : Double, scales : Double[], nMeasurementsPerScale : Int - ) : Double[] { - let hiddenRotation = HiddenRotation(hiddenAngle); - return Arrays.ForEach( - EstimateProbabilityAtScale( - _, - nMeasurementsPerScale, - hiddenRotation - ), - scales - ); - } - - operation EstimateProbabilityAtScaleUsingControlledRotations( - target : Qubit, - scale : Double, - nMeasurements : Int, - op : ScalableOperation) - : Double { - mutable nOnes = 0; - for idx in 0..nMeasurements - 1 { - use control = Qubit(); - within { - H(control); - } apply { - Controlled op::Apply( - [control], - (scale, target) - ); - } - set nOnes += Meas.MResetZ(control) == One - ? 1 | 0; - } - return Convert.IntAsDouble(nOnes) / - Convert.IntAsDouble(nMeasurements); - } - - operation RunGameUsingControlledRotations( - hiddenAngle : Double, - scales : Double[], - nMeasurementsPerScale : Int) - : Double[] { - let hiddenRotation = HiddenRotation(hiddenAngle); - use target = Qubit(); - X(target); - let measurements = Arrays.ForEach( - EstimateProbabilityAtScaleUsingControlledRotations( - target, _, nMeasurementsPerScale, hiddenRotation - ), - scales - ); - X(target); - return measurements; - } -} +// operations.qs: Sample code for Phase Estimation (Chapter 9). +// +// Copyright (c) Sarah Kaiser and Chris Granade. +// Code sample from the book "Learn Quantum Computing with Python and Q#" by +// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Book ISBN 9781617296130. +// Code licensed under the MIT License. + +namespace PhaseEstimation { + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Convert as Convert; + open Microsoft.Quantum.Measurement as Meas; + open Microsoft.Quantum.Arrays as Arrays; + + operation ApplyScaledRotation( + angle : Double, scale : Double, + target : Qubit) + : Unit is Adj + Ctl { + R1(angle * scale, target); + } + + newtype ScalableOperation = ( + Apply: ((Double, Qubit) => Unit is Adj + Ctl) + ); + + function HiddenRotation(hiddenAngle : Double) + : ScalableOperation { + return ScalableOperation( + ApplyScaledRotation(hiddenAngle, _, _) + ); + } + + operation EstimateProbabilityAtScale( + scale : Double, + nMeasurements : Int, + op : ScalableOperation) + : Double { + mutable nOnes = 0; + for idx in 0..nMeasurements - 1 { + use target = Qubit(); + within { + H(target); + } apply { + op::Apply(scale, target); + } + set nOnes += Meas.MResetZ(target) == One + ? 1 | 0; + } + return Convert.IntAsDouble(nOnes) / + Convert.IntAsDouble(nMeasurements); + } + + operation RunGame( + hiddenAngle : Double, scales : Double[], nMeasurementsPerScale : Int + ) : Double[] { + let hiddenRotation = HiddenRotation(hiddenAngle); + return Arrays.ForEach( + EstimateProbabilityAtScale( + _, + nMeasurementsPerScale, + hiddenRotation + ), + scales + ); + } + + operation EstimateProbabilityAtScaleUsingControlledRotations( + target : Qubit, + scale : Double, + nMeasurements : Int, + op : ScalableOperation) + : Double { + mutable nOnes = 0; + for idx in 0..nMeasurements - 1 { + use control = Qubit(); + within { + H(control); + } apply { + Controlled op::Apply( + [control], + (scale, target) + ); + } + set nOnes += Meas.MResetZ(control) == One + ? 1 | 0; + } + return Convert.IntAsDouble(nOnes) / + Convert.IntAsDouble(nMeasurements); + } + + operation RunGameUsingControlledRotations( + hiddenAngle : Double, + scales : Double[], + nMeasurementsPerScale : Int) + : Double[] { + let hiddenRotation = HiddenRotation(hiddenAngle); + use target = Qubit(); + X(target); + let measurements = Arrays.ForEach( + EstimateProbabilityAtScaleUsingControlledRotations( + target, _, nMeasurementsPerScale, hiddenRotation + ), + scales + ); + X(target); + return measurements; + } +} diff --git a/ch09/qsharp-interop.py b/ch09/qsharp-interop.py index 08b6b19..62c58d2 100644 --- a/ch09/qsharp-interop.py +++ b/ch09/qsharp-interop.py @@ -1,26 +1,26 @@ -#!/bin/env python -# -*- coding: utf-8 -*- -## -# qsharp-interop.py: Demo showing how Q# code can be run from a Python host. -## -# Copyright (c) Sarah Kaiser and Chris Granade. -# Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. -# Book ISBN 9781617296130. -# Code licensed under the MIT License. -## - -import qsharp - -prepare_qubit = qsharp.compile(""" // <2> - open Microsoft.Quantum.Diagnostics; // <3> - - operation PrepareQubit(): Unit { // <4> - using (qubit = Qubit()) { - DumpMachine(); - } - } - """) - -if __name__ == "__main__": - prepare_qubit.simulate() +#!/bin/env python +# -*- coding: utf-8 -*- +## +# qsharp-interop.py: Demo showing how Q# code can be run from a Python host. +## +# Copyright (c) Sarah Kaiser and Chris Granade. +# Code sample from the book "Learn Quantum Computing with Python and Q#" by +# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Book ISBN 9781617296130. +# Code licensed under the MIT License. +## + +import qsharp + +prepare_qubit = qsharp.compile(""" // <2> + open Microsoft.Quantum.Diagnostics; // <3> + + operation PrepareQubit(): Unit { // <4> + using (qubit = Qubit()) { + DumpMachine(); + } + } + """) + +if __name__ == "__main__": + prepare_qubit.simulate() diff --git a/ch10/ch10-exercise-solutions.ipynb b/ch10/ch10-exercise-solutions.ipynb index 6fc2f7a..5664c47 100644 --- a/ch10/ch10-exercise-solutions.ipynb +++ b/ch10/ch10-exercise-solutions.ipynb @@ -618,26 +618,21 @@ }, { "cell_type": "code", - "execution_count": 1, - "metadata": {}, + "execution_count": 21, + "metadata": { + "scrolled": true + }, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Preparing Q# environment...\n" - ] - }, { "data": { "text/plain": [ - "{'iqsharp': LooseVersion ('0.17.2105143879'),\n", + "{'iqsharp': LooseVersion ('0.24.210930'),\n", " 'Jupyter Core': LooseVersion ('1.5.0.0'),\n", - " '.NET Runtime': LooseVersion ('.NETCoreApp,Version=v3.1'),\n", - " 'qsharp': LooseVersion ('0.17.2105.143879')}" + " '.NET Runtime': LooseVersion ('.NETCoreApp,Version=v6.0'),\n", + " 'qsharp': LooseVersion ('0.24.210930')}" ] }, - "execution_count": 1, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -649,7 +644,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -663,7 +658,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.10" + "version": "3.7.13" } }, "nbformat": 4, diff --git a/ch10/host.ipynb b/ch10/host.ipynb index e441c9a..480f9ef 100644 --- a/ch10/host.ipynb +++ b/ch10/host.ipynb @@ -85,7 +85,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -118,10 +118,10 @@ { "data": { "text/plain": [ - "{'iqsharp': LooseVersion ('0.15.2101125897'),\n", + "{'iqsharp': LooseVersion ('0.24.210930'),\n", " 'Jupyter Core': LooseVersion ('1.5.0.0'),\n", - " '.NET Runtime': LooseVersion ('.NETCoreApp,Version=v3.1'),\n", - " 'qsharp': LooseVersion ('0.15.2101.125897')}" + " '.NET Runtime': LooseVersion ('.NETCoreApp,Version=v6.0'),\n", + " 'qsharp': LooseVersion ('0.24.210930')}" ] }, "execution_count": 2, @@ -136,7 +136,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -150,7 +150,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.10" + "version": "3.7.13" } }, "nbformat": 4, diff --git a/ch10/host.py b/ch10/host.py index be95443..0d0d720 100644 --- a/ch10/host.py +++ b/ch10/host.py @@ -1,35 +1,35 @@ -#!/bin/env python -# -*- coding: utf-8 -*- -## -# host.py: Host program for the Hamiltonian simulation example (Chapter 9). -## -# Copyright (c) Sarah Kaiser and Chris Granade. -# Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. -# Book ISBN 9781617296130. -# Code licensed under the MIT License. -## - -import qsharp -import HamiltonianSimulation as H2Simulation - -bond_lengths = H2Simulation.H2BondLengths.simulate() - -def estimate_energy(bond_index: float, - n_measurements_per_scale: int = 3 - ) -> float: - print(f"Estimating energy for bond length of {bond_lengths[bond_index]} Å.") - return min([H2Simulation.EstimateH2Energy.simulate(idxBondLength=bond_index) - for _ in range(n_measurements_per_scale)]) - -if __name__ == "__main__": - import matplotlib.pyplot as plt - - print(f"Number of bond lengths: {len(bond_lengths)}.\n") - energies = [estimate_energy(i) for i in range(len(bond_lengths))] - plt.figure() - plt.plot(bond_lengths, energies, 'o') - plt.title('Energy levels of H2 as a function of bond length') - plt.xlabel('Bond length (Å)') - plt.ylabel('Ground state energy (Hartree)') - plt.show() +#!/bin/env python +# -*- coding: utf-8 -*- +## +# host.py: Host program for the Hamiltonian simulation example (Chapter 9). +## +# Copyright (c) Sarah Kaiser and Chris Granade. +# Code sample from the book "Learn Quantum Computing with Python and Q#" by +# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Book ISBN 9781617296130. +# Code licensed under the MIT License. +## + +import qsharp +import HamiltonianSimulation as H2Simulation + +bond_lengths = H2Simulation.H2BondLengths.simulate() + +def estimate_energy(bond_index: float, + n_measurements_per_scale: int = 3 + ) -> float: + print(f"Estimating energy for bond length of {bond_lengths[bond_index]} Å.") + return min([H2Simulation.EstimateH2Energy.simulate(idxBondLength=bond_index) + for _ in range(n_measurements_per_scale)]) + +if __name__ == "__main__": + import matplotlib.pyplot as plt + + print(f"Number of bond lengths: {len(bond_lengths)}.\n") + energies = [estimate_energy(i) for i in range(len(bond_lengths))] + plt.figure() + plt.plot(bond_lengths, energies, 'o') + plt.title('Energy levels of H2 as a function of bond length') + plt.xlabel('Bond length (Å)') + plt.ylabel('Ground state energy (Hartree)') + plt.show() diff --git a/ch10/operations.qs b/ch10/operations.qs index c536862..c7e8fc6 100644 --- a/ch10/operations.qs +++ b/ch10/operations.qs @@ -1,160 +1,160 @@ -// operations.qs: Sample code for Hamiltonian simulation (Chapter 10). -// -// Copyright (c) Sarah Kaiser and Chris Granade. -// Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. -// Book ISBN 9781617296130. -// Code licensed under the MIT License. -// -// Adapted from the QDK samples repo here: -// https://github.com/microsoft/Quantum/tree/master/samples/simulation - - -namespace HamiltonianSimulation { - open Microsoft.Quantum.Intrinsic; - open Microsoft.Quantum.Canon; - open Microsoft.Quantum.Simulation; - open Microsoft.Quantum.Characterization; - - - function H2BondLengths() : Double[] { - return [0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, - 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, - 1.05, 1.1, 1.15, 1.2, 1.25, 1.3, 1.35, 1.4, 1.45, 1.5, - 1.55, 1.6, 1.65, 1.7, 1.75, 1.8, 1.85, 1.9, 1.95, 2.0, - 2.05, 2.1, 2.15, 2.2, 2.25, 2.3, 2.35, 2.4, 2.45, 2.5, - 2.55, 2.6, 2.65, 2.7, 2.75, 2.8, 2.85]; - } - - function H2Coeff(idxBondLength : Int) : Double[] { - return [ - [0.5678, -1.4508, 0.6799, 0.0791, 0.0791], - [0.5449, -1.287, 0.6719, 0.0798, 0.0798], - [0.5215, -1.1458, 0.6631, 0.0806, 0.0806], - [0.4982, -1.0226, 0.6537, 0.0815, 0.0815], - [0.4754, -0.9145, 0.6438, 0.0825, 0.0825], - [0.4534, -0.8194, 0.6336, 0.0835, 0.0835], - [0.4325, -0.7355, 0.6233, 0.0846, 0.0846], - [0.4125, -0.6612, 0.6129, 0.0858, 0.0858], - [0.3937, -0.595, 0.6025, 0.087, 0.087], - [0.376, -0.5358, 0.5921, 0.0883, 0.0883], - [0.3593, -0.4826, 0.5818, 0.0896, 0.0896], - [0.3435, -0.4347, 0.5716, 0.091, 0.091], - [0.3288, -0.3915, 0.5616, 0.0925, 0.0925], - [0.3149, -0.3523, 0.5518, 0.0939, 0.0939], - [0.3018, -0.3168, 0.5421, 0.0954, 0.0954], - [0.2895, -0.2845, 0.5327, 0.097, 0.097], - [0.2779, -0.255, 0.5235, 0.0986, 0.0986], - [0.2669, -0.2282, 0.5146, 0.1002, 0.1002], - [0.2565, -0.2036, 0.5059, 0.1018, 0.1018], - [0.2467, -0.181, 0.4974, 0.1034, 0.1034], - [0.2374, -0.1603, 0.4892, 0.105, 0.105], - [0.2286, -0.1413, 0.4812, 0.1067, 0.1067], - [0.2203, -0.1238, 0.4735, 0.1083, 0.1083], - [0.2123, -0.1077, 0.466, 0.11, 0.11], - [0.2048, -0.0929, 0.4588, 0.1116, 0.1116], - [0.1976, -0.0792, 0.4518, 0.1133, 0.1133], - [0.1908, -0.0666, 0.4451, 0.1149, 0.1149], - [0.1843, -0.0549, 0.4386, 0.1165, 0.1165], - [0.1782, -0.0442, 0.4323, 0.1181, 0.1181], - [0.1723, -0.0342, 0.4262, 0.1196, 0.1196], - [0.1667, -0.0251, 0.4204, 0.1211, 0.1211], - [0.1615, -0.0166, 0.4148, 0.1226, 0.1226], - [0.1565, -0.0088, 0.4094, 0.1241, 0.1241], - [0.1517, -0.0015, 0.4042, 0.1256, 0.1256], - [0.1472, 0.0052, 0.3992, 0.127, 0.127], - [0.143, 0.0114, 0.3944, 0.1284, 0.1284], - [0.139, 0.0171, 0.3898, 0.1297, 0.1297], - [0.1352, 0.0223, 0.3853, 0.131, 0.131], - [0.1316, 0.0272, 0.3811, 0.1323, 0.1323], - [0.1282, 0.0317, 0.3769, 0.1335, 0.1335], - [0.1251, 0.0359, 0.373, 0.1347, 0.1347], - [0.1221, 0.0397, 0.3692, 0.1359, 0.1359], - [0.1193, 0.0432, 0.3655, 0.137, 0.137], - [0.1167, 0.0465, 0.362, 0.1381, 0.1381], - [0.1142, 0.0495, 0.3586, 0.1392, 0.1392], - [0.1119, 0.0523, 0.3553, 0.1402, 0.1402], - [0.1098, 0.0549, 0.3521, 0.1412, 0.1412], - [0.1078, 0.0572, 0.3491, 0.1422, 0.1422], - [0.1059, 0.0594, 0.3461, 0.1432, 0.1432], - [0.1042, 0.0614, 0.3433, 0.1441, 0.1441], - [0.1026, 0.0632, 0.3406, 0.145, 0.145], - [0.1011, 0.0649, 0.3379, 0.1458, 0.1458], - [0.0997, 0.0665, 0.3354, 0.1467, 0.1467], - [0.0984, 0.0679, 0.3329, 0.1475, 0.1475] - ][idxBondLength]; - } - - function H2IdentityCoeff(idxBond : Int) : Double { - return [ - 2.8489, 2.1868, 1.7252, 1.3827, 1.1182, - 0.9083, 0.7381, 0.5979, 0.4808, 0.3819, - 0.2976, 0.2252, 0.1626, 0.1083, 0.0609, - 0.0193, -0.0172, -0.0493, -0.0778, -0.1029, - -0.1253, -0.1452, -0.1629, -0.1786, -0.1927, - -0.2053, -0.2165, -0.2265, -0.2355, -0.2436, - -0.2508, -0.2573, -0.2632, -0.2684, -0.2731, - -0.2774, -0.2812, -0.2847, -0.2879, -0.2908, - -0.2934, -0.2958, -0.298, -0.3, -0.3018, - -0.3035, -0.3051, -0.3066, -0.3079, -0.3092, - -0.3104, -0.3115, -0.3125, -0.3135 - ][idxBond]; - } - - function H2Terms(idxHamiltonian : Int) - : (Pauli[], Int[]) { - return [ - ([PauliZ], [0]), - ([PauliZ], [1]), - ([PauliZ, PauliZ], [0, 1]), - ([PauliY, PauliY], [0, 1]), - ([PauliX, PauliX], [0, 1]) - ][idxHamiltonian]; - } - - operation PrepareInitalState(q : Qubit[]) - : Unit { - X(q[0]); - } - - operation EvolveUnderHamiltonianTerm( - idxBondLength : Int, - idxTerm : Int, - stepSize : Double, - qubits : Qubit[]) - : Unit is Adj + Ctl { - let (pauliString, idxQubits) = - H2Terms(idxTerm); - let coeff = - (H2Coeff(idxBondLength))[idxTerm]; - let op = Exp(pauliString, - stepSize * coeff, _); - (RestrictedToSubregisterCA(op, idxQubits)) - (qubits); - } - - operation EvolveUnderHamiltonian( - idxBondLength : Int, - trotterStepSize : Double, - qubits : Qubit[]) - : Unit is Adj + Ctl { - let trotterOrder = 1; - let op = EvolveUnderHamiltonianTerm( - idxBondLength, _, _, _); - (DecomposedIntoTimeStepsCA ((5, op), trotterOrder)) - (trotterStepSize, qubits); - } - - operation EstimateH2Energy(idxBondLength : Int) - : Double { - let nQubits = 2; - let trotterStepSize = 1.0; - let trotterStep = EvolveUnderHamiltonian( - idxBondLength, trotterStepSize, _); - let estPhase = EstimateEnergy(nQubits, - PrepareInitalState, trotterStep, - RobustPhaseEstimation(6, _, _)); - return estPhase / trotterStepSize - + H2IdentityCoeff(idxBondLength); - } -} +// operations.qs: Sample code for Hamiltonian simulation (Chapter 10). +// +// Copyright (c) Sarah Kaiser and Chris Granade. +// Code sample from the book "Learn Quantum Computing with Python and Q#" by +// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Book ISBN 9781617296130. +// Code licensed under the MIT License. +// +// Adapted from the QDK samples repo here: +// https://github.com/microsoft/Quantum/tree/master/samples/simulation + + +namespace HamiltonianSimulation { + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Canon; + open Microsoft.Quantum.Simulation; + open Microsoft.Quantum.Characterization; + + + function H2BondLengths() : Double[] { + return [0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, + 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, + 1.05, 1.1, 1.15, 1.2, 1.25, 1.3, 1.35, 1.4, 1.45, 1.5, + 1.55, 1.6, 1.65, 1.7, 1.75, 1.8, 1.85, 1.9, 1.95, 2.0, + 2.05, 2.1, 2.15, 2.2, 2.25, 2.3, 2.35, 2.4, 2.45, 2.5, + 2.55, 2.6, 2.65, 2.7, 2.75, 2.8, 2.85]; + } + + function H2Coeff(idxBondLength : Int) : Double[] { + return [ + [0.5678, -1.4508, 0.6799, 0.0791, 0.0791], + [0.5449, -1.287, 0.6719, 0.0798, 0.0798], + [0.5215, -1.1458, 0.6631, 0.0806, 0.0806], + [0.4982, -1.0226, 0.6537, 0.0815, 0.0815], + [0.4754, -0.9145, 0.6438, 0.0825, 0.0825], + [0.4534, -0.8194, 0.6336, 0.0835, 0.0835], + [0.4325, -0.7355, 0.6233, 0.0846, 0.0846], + [0.4125, -0.6612, 0.6129, 0.0858, 0.0858], + [0.3937, -0.595, 0.6025, 0.087, 0.087], + [0.376, -0.5358, 0.5921, 0.0883, 0.0883], + [0.3593, -0.4826, 0.5818, 0.0896, 0.0896], + [0.3435, -0.4347, 0.5716, 0.091, 0.091], + [0.3288, -0.3915, 0.5616, 0.0925, 0.0925], + [0.3149, -0.3523, 0.5518, 0.0939, 0.0939], + [0.3018, -0.3168, 0.5421, 0.0954, 0.0954], + [0.2895, -0.2845, 0.5327, 0.097, 0.097], + [0.2779, -0.255, 0.5235, 0.0986, 0.0986], + [0.2669, -0.2282, 0.5146, 0.1002, 0.1002], + [0.2565, -0.2036, 0.5059, 0.1018, 0.1018], + [0.2467, -0.181, 0.4974, 0.1034, 0.1034], + [0.2374, -0.1603, 0.4892, 0.105, 0.105], + [0.2286, -0.1413, 0.4812, 0.1067, 0.1067], + [0.2203, -0.1238, 0.4735, 0.1083, 0.1083], + [0.2123, -0.1077, 0.466, 0.11, 0.11], + [0.2048, -0.0929, 0.4588, 0.1116, 0.1116], + [0.1976, -0.0792, 0.4518, 0.1133, 0.1133], + [0.1908, -0.0666, 0.4451, 0.1149, 0.1149], + [0.1843, -0.0549, 0.4386, 0.1165, 0.1165], + [0.1782, -0.0442, 0.4323, 0.1181, 0.1181], + [0.1723, -0.0342, 0.4262, 0.1196, 0.1196], + [0.1667, -0.0251, 0.4204, 0.1211, 0.1211], + [0.1615, -0.0166, 0.4148, 0.1226, 0.1226], + [0.1565, -0.0088, 0.4094, 0.1241, 0.1241], + [0.1517, -0.0015, 0.4042, 0.1256, 0.1256], + [0.1472, 0.0052, 0.3992, 0.127, 0.127], + [0.143, 0.0114, 0.3944, 0.1284, 0.1284], + [0.139, 0.0171, 0.3898, 0.1297, 0.1297], + [0.1352, 0.0223, 0.3853, 0.131, 0.131], + [0.1316, 0.0272, 0.3811, 0.1323, 0.1323], + [0.1282, 0.0317, 0.3769, 0.1335, 0.1335], + [0.1251, 0.0359, 0.373, 0.1347, 0.1347], + [0.1221, 0.0397, 0.3692, 0.1359, 0.1359], + [0.1193, 0.0432, 0.3655, 0.137, 0.137], + [0.1167, 0.0465, 0.362, 0.1381, 0.1381], + [0.1142, 0.0495, 0.3586, 0.1392, 0.1392], + [0.1119, 0.0523, 0.3553, 0.1402, 0.1402], + [0.1098, 0.0549, 0.3521, 0.1412, 0.1412], + [0.1078, 0.0572, 0.3491, 0.1422, 0.1422], + [0.1059, 0.0594, 0.3461, 0.1432, 0.1432], + [0.1042, 0.0614, 0.3433, 0.1441, 0.1441], + [0.1026, 0.0632, 0.3406, 0.145, 0.145], + [0.1011, 0.0649, 0.3379, 0.1458, 0.1458], + [0.0997, 0.0665, 0.3354, 0.1467, 0.1467], + [0.0984, 0.0679, 0.3329, 0.1475, 0.1475] + ][idxBondLength]; + } + + function H2IdentityCoeff(idxBond : Int) : Double { + return [ + 2.8489, 2.1868, 1.7252, 1.3827, 1.1182, + 0.9083, 0.7381, 0.5979, 0.4808, 0.3819, + 0.2976, 0.2252, 0.1626, 0.1083, 0.0609, + 0.0193, -0.0172, -0.0493, -0.0778, -0.1029, + -0.1253, -0.1452, -0.1629, -0.1786, -0.1927, + -0.2053, -0.2165, -0.2265, -0.2355, -0.2436, + -0.2508, -0.2573, -0.2632, -0.2684, -0.2731, + -0.2774, -0.2812, -0.2847, -0.2879, -0.2908, + -0.2934, -0.2958, -0.298, -0.3, -0.3018, + -0.3035, -0.3051, -0.3066, -0.3079, -0.3092, + -0.3104, -0.3115, -0.3125, -0.3135 + ][idxBond]; + } + + function H2Terms(idxHamiltonian : Int) + : (Pauli[], Int[]) { + return [ + ([PauliZ], [0]), + ([PauliZ], [1]), + ([PauliZ, PauliZ], [0, 1]), + ([PauliY, PauliY], [0, 1]), + ([PauliX, PauliX], [0, 1]) + ][idxHamiltonian]; + } + + operation PrepareInitalState(q : Qubit[]) + : Unit { + X(q[0]); + } + + operation EvolveUnderHamiltonianTerm( + idxBondLength : Int, + idxTerm : Int, + stepSize : Double, + qubits : Qubit[]) + : Unit is Adj + Ctl { + let (pauliString, idxQubits) = + H2Terms(idxTerm); + let coeff = + (H2Coeff(idxBondLength))[idxTerm]; + let op = Exp(pauliString, + stepSize * coeff, _); + (RestrictedToSubregisterCA(op, idxQubits)) + (qubits); + } + + operation EvolveUnderHamiltonian( + idxBondLength : Int, + trotterStepSize : Double, + qubits : Qubit[]) + : Unit is Adj + Ctl { + let trotterOrder = 1; + let op = EvolveUnderHamiltonianTerm( + idxBondLength, _, _, _); + (DecomposedIntoTimeStepsCA ((5, op), trotterOrder)) + (trotterStepSize, qubits); + } + + operation EstimateH2Energy(idxBondLength : Int) + : Double { + let nQubits = 2; + let trotterStepSize = 1.0; + let trotterStep = EvolveUnderHamiltonian( + idxBondLength, trotterStepSize, _); + let estPhase = EstimateEnergy(nQubits, + PrepareInitalState, trotterStep, + RobustPhaseEstimation(6, _, _)); + return estPhase / trotterStepSize + + H2IdentityCoeff(idxBondLength); + } +} diff --git a/ch11/GroverSearch.ipynb b/ch11/GroverSearch.ipynb index eafc1a1..8666f1f 100644 --- a/ch11/GroverSearch.ipynb +++ b/ch11/GroverSearch.ipynb @@ -28,7 +28,7 @@ "outputs": [ { "data": { - "application/json": "[\"DumpInitialState\"]", + "application/x-qsharp-data": "[\"DumpInitialState\"]", "text/html": [ "
  • DumpInitialState
" ], @@ -60,7 +60,7 @@ "outputs": [ { "data": { - "application/json": "{\"div_id\":\"dump-machine-div-0c1748b1-2911-4094-871f-ad37cde5f735\",\"qubit_ids\":[0,1,2],\"n_qubits\":3,\"amplitudes\":[{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0}]}", + "application/x-qsharp-data": "{\"diagnostic_kind\":\"state-vector\",\"qubit_ids\":[0,1,2],\"n_qubits\":3,\"amplitudes\":{\"0\":{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},\"1\":{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},\"2\":{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},\"3\":{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},\"4\":{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},\"5\":{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},\"6\":{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0},\"7\":{\"Real\":0.35355339059327384,\"Imaginary\":0.0,\"Magnitude\":0.35355339059327384,\"Phase\":0.0}}}", "text/html": [ "\r\n", " \r\n", @@ -89,12 +89,12 @@ " style=\"width: 100%;\"\r\n", "> \r\n", " \r\n", " \r\n", @@ -119,12 +119,12 @@ " style=\"width: 100%;\"\r\n", "> \r\n", " \r\n", " \r\n", @@ -149,12 +149,12 @@ " style=\"width: 100%;\"\r\n", "> \r\n", " \r\n", " \r\n", @@ -179,12 +179,12 @@ " style=\"width: 100%;\"\r\n", "> \r\n", " \r\n", " \r\n", @@ -209,12 +209,12 @@ " style=\"width: 100%;\"\r\n", "> \r\n", " \r\n", " \r\n", @@ -239,12 +239,12 @@ " style=\"width: 100%;\"\r\n", "> \r\n", " \r\n", " \r\n", @@ -269,12 +269,12 @@ " style=\"width: 100%;\"\r\n", "> \r\n", " \r\n", " \r\n", @@ -299,12 +299,12 @@ " style=\"width: 100%;\"\r\n", "> \r\n", " \r\n", " \r\n", @@ -336,7 +336,7 @@ }, { "data": { - "application/json": "{\"@type\":\"tuple\"}", + "application/x-qsharp-data": "{\"@type\":\"tuple\"}", "text/plain": [ "()" ] @@ -366,12 +366,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "Marked 6 and found 6.\r\n" + "Marked 6 and found 6.\n" ] }, { "data": { - "application/json": "{\"@type\":\"tuple\"}", + "application/x-qsharp-data": "{\"@type\":\"tuple\"}", "text/plain": [ "()" ] @@ -406,22 +406,22 @@ "outputs": [ { "data": { - "application/json": "[{\"Metric\":\"CNOT\",\"Sum\":864120.0,\"Max\":864120.0},{\"Metric\":\"QubitClifford\",\"Sum\":311559.0,\"Max\":311559.0},{\"Metric\":\"R\",\"Sum\":0.0,\"Max\":0.0},{\"Metric\":\"Measure\",\"Sum\":21.0,\"Max\":21.0},{\"Metric\":\"T\",\"Sum\":604884.0,\"Max\":604884.0},{\"Metric\":\"Depth\",\"Sum\":389991.0,\"Max\":389991.0},{\"Metric\":\"Width\",\"Sum\":41.0,\"Max\":41.0},{\"Metric\":\"QubitCount\",\"Sum\":41.0,\"Max\":41.0},{\"Metric\":\"BorrowedWidth\",\"Sum\":0.0,\"Max\":0.0}]", + "application/x-qsharp-data": "[{\"Metric\":\"CNOT\",\"Sum\":864120.0,\"Max\":864120.0},{\"Metric\":\"QubitClifford\",\"Sum\":311559.0,\"Max\":311559.0},{\"Metric\":\"R\",\"Sum\":0.0,\"Max\":0.0},{\"Metric\":\"Measure\",\"Sum\":21.0,\"Max\":21.0},{\"Metric\":\"T\",\"Sum\":604884.0,\"Max\":604884.0},{\"Metric\":\"Depth\",\"Sum\":389991.0,\"Max\":389991.0},{\"Metric\":\"Width\",\"Sum\":41.0,\"Max\":41.0},{\"Metric\":\"QubitCount\",\"Sum\":41.0,\"Max\":41.0},{\"Metric\":\"BorrowedWidth\",\"Sum\":0.0,\"Max\":0.0}]", "text/html": [ "
\r\n", - "

\r\n", + "

\r\n", "

\r\n", "
\r\n", - "

\r\n", + "

\r\n", "

\r\n", "
\r\n", - "

\r\n", + "

\r\n", "

\r\n", "
\r\n", - "

\r\n", + "

\r\n", "

\r\n", "
\r\n", - "

\r\n", + "

\r\n", "

\r\n", "
\r\n", - "

\r\n", + "

\r\n", "

\r\n", "
\r\n", - "

\r\n", + "

\r\n", "

\r\n", "
\r\n", - "

\r\n", + "

\r\n", "

\r\n", "
MetricSumMax
CNOT864120864120
QubitClifford311559311559
R00
Measure2121
T604884604884
Depth389991389991
Width4141
QubitCount4141
BorrowedWidth00
" ], "text/plain": [ - "Metric Sum Max\r\n", - "------------- ------ ------\r\n", - "CNOT 864120 864120\r\n", - "QubitClifford 311559 311559\r\n", - "R 0 0\r\n", - "Measure 21 21\r\n", - "T 604884 604884\r\n", - "Depth 389991 389991\r\n", - "Width 41 41\r\n", - "QubitCount 41 41\r\n", - "BorrowedWidth 0 0\r\n" + "Metric Sum Max\n", + "------------- ------ ------\n", + "CNOT 864120 864120\n", + "QubitClifford 311559 311559\n", + "R 0 0\n", + "Measure 21 21\n", + "T 604884 604884\n", + "Depth 389991 389991\n", + "Width 41 41\n", + "QubitCount 41 41\n", + "BorrowedWidth 0 0\n" ] }, "execution_count": 4, @@ -447,16 +447,16 @@ "outputs": [ { "data": { - "application/json": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.17.2105143879\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v3.1\"}]}", + "application/x-qsharp-data": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.24.210930\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v6.0\"}]}", "text/html": [ - "
ComponentVersion
iqsharp0.17.2105143879
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v3.1
" + "
ComponentVersion
iqsharp0.24.210930
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v6.0
" ], "text/plain": [ - "Component Version\r\n", - "------------ ------------------------\r\n", - "iqsharp 0.17.2105143879\r\n", - "Jupyter Core 1.5.0.0\r\n", - ".NET Runtime .NETCoreApp,Version=v3.1\r\n" + "Component Version\n", + "------------ ------------------------\n", + "iqsharp 0.24.210930\n", + "Jupyter Core 1.5.0.0\n", + ".NET Runtime .NETCoreApp,Version=v6.0\n" ] }, "metadata": {}, @@ -466,6 +466,13 @@ "source": [ "%version" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -478,7 +485,7 @@ "file_extension": ".qs", "mimetype": "text/x-qsharp", "name": "qsharp", - "version": "0.14" + "version": "0.24" } }, "nbformat": 4, diff --git a/ch11/ResourceEstimation.ipynb b/ch11/ResourceEstimation.ipynb index f44fd7a..d339158 100644 --- a/ch11/ResourceEstimation.ipynb +++ b/ch11/ResourceEstimation.ipynb @@ -23,12 +23,12 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 8, "metadata": {}, "outputs": [ { "data": { - "application/json": "[\"ApplyNotOracle\"]", + "application/x-qsharp-data": "[\"ApplyNotOracle\"]", "text/html": [ "
  • ApplyNotOracle
" ], @@ -36,7 +36,7 @@ "ApplyNotOracle" ] }, - "execution_count": 1, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -53,12 +53,12 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 9, "metadata": {}, "outputs": [ { "data": { - "application/json": "[\"CheckIfOracleIsBalanced\"]", + "application/x-qsharp-data": "[\"CheckIfOracleIsBalanced\"]", "text/html": [ "
  • CheckIfOracleIsBalanced
" ], @@ -66,7 +66,7 @@ "CheckIfOracleIsBalanced" ] }, - "execution_count": 2, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -92,12 +92,12 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { - "application/json": "[\"RunDeutschJozsaAlgorithm\"]", + "application/x-qsharp-data": "[\"RunDeutschJozsaAlgorithm\"]", "text/html": [ "
  • RunDeutschJozsaAlgorithm
" ], @@ -105,7 +105,7 @@ "RunDeutschJozsaAlgorithm" ] }, - "execution_count": 3, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -118,30 +118,30 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { - "application/json": "[{\"Metric\":\"CNOT\",\"Sum\":1.0,\"Max\":1.0},{\"Metric\":\"QubitClifford\",\"Sum\":8.0,\"Max\":8.0},{\"Metric\":\"R\",\"Sum\":0.0,\"Max\":0.0},{\"Metric\":\"Measure\",\"Sum\":1.0,\"Max\":1.0},{\"Metric\":\"T\",\"Sum\":0.0,\"Max\":0.0},{\"Metric\":\"Depth\",\"Sum\":0.0,\"Max\":0.0},{\"Metric\":\"Width\",\"Sum\":2.0,\"Max\":2.0},{\"Metric\":\"QubitCount\",\"Sum\":2.0,\"Max\":2.0},{\"Metric\":\"BorrowedWidth\",\"Sum\":0.0,\"Max\":0.0}]", + "application/x-qsharp-data": "[{\"Metric\":\"CNOT\",\"Sum\":1.0,\"Max\":1.0},{\"Metric\":\"QubitClifford\",\"Sum\":8.0,\"Max\":8.0},{\"Metric\":\"R\",\"Sum\":0.0,\"Max\":0.0},{\"Metric\":\"Measure\",\"Sum\":1.0,\"Max\":1.0},{\"Metric\":\"T\",\"Sum\":0.0,\"Max\":0.0},{\"Metric\":\"Depth\",\"Sum\":0.0,\"Max\":0.0},{\"Metric\":\"Width\",\"Sum\":2.0,\"Max\":2.0},{\"Metric\":\"QubitCount\",\"Sum\":2.0,\"Max\":2.0},{\"Metric\":\"BorrowedWidth\",\"Sum\":0.0,\"Max\":0.0}]", "text/html": [ "
MetricSumMax
CNOT11
QubitClifford88
R00
Measure11
T00
Depth00
Width22
QubitCount22
BorrowedWidth00
" ], "text/plain": [ - "Metric Sum Max\r\n", - "------------- - -\r\n", - "CNOT 1 1\r\n", - "QubitClifford 8 8\r\n", - "R 0 0\r\n", - "Measure 1 1\r\n", - "T 0 0\r\n", - "Depth 0 0\r\n", - "Width 2 2\r\n", - "QubitCount 2 2\r\n", - "BorrowedWidth 0 0\r\n" + "Metric Sum Max\n", + "------------- - -\n", + "CNOT 1 1\n", + "QubitClifford 8 8\n", + "R 0 0\n", + "Measure 1 1\n", + "T 0 0\n", + "Depth 0 0\n", + "Width 2 2\n", + "QubitCount 2 2\n", + "BorrowedWidth 0 0\n" ] }, - "execution_count": 4, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -159,12 +159,12 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 12, "metadata": {}, "outputs": [ { "data": { - "application/json": "[\"EstimateCcnotResources\"]", + "application/x-qsharp-data": "[\"EstimateCcnotResources\"]", "text/html": [ "
  • EstimateCcnotResources
" ], @@ -172,7 +172,7 @@ "EstimateCcnotResources" ] }, - "execution_count": 5, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -186,30 +186,30 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 13, "metadata": {}, "outputs": [ { "data": { - "application/json": "[{\"Metric\":\"CNOT\",\"Sum\":10.0,\"Max\":10.0},{\"Metric\":\"QubitClifford\",\"Sum\":2.0,\"Max\":2.0},{\"Metric\":\"R\",\"Sum\":0.0,\"Max\":0.0},{\"Metric\":\"Measure\",\"Sum\":0.0,\"Max\":0.0},{\"Metric\":\"T\",\"Sum\":7.0,\"Max\":7.0},{\"Metric\":\"Depth\",\"Sum\":5.0,\"Max\":5.0},{\"Metric\":\"Width\",\"Sum\":3.0,\"Max\":3.0},{\"Metric\":\"QubitCount\",\"Sum\":3.0,\"Max\":3.0},{\"Metric\":\"BorrowedWidth\",\"Sum\":0.0,\"Max\":0.0}]", + "application/x-qsharp-data": "[{\"Metric\":\"CNOT\",\"Sum\":10.0,\"Max\":10.0},{\"Metric\":\"QubitClifford\",\"Sum\":2.0,\"Max\":2.0},{\"Metric\":\"R\",\"Sum\":0.0,\"Max\":0.0},{\"Metric\":\"Measure\",\"Sum\":0.0,\"Max\":0.0},{\"Metric\":\"T\",\"Sum\":7.0,\"Max\":7.0},{\"Metric\":\"Depth\",\"Sum\":5.0,\"Max\":5.0},{\"Metric\":\"Width\",\"Sum\":3.0,\"Max\":3.0},{\"Metric\":\"QubitCount\",\"Sum\":3.0,\"Max\":3.0},{\"Metric\":\"BorrowedWidth\",\"Sum\":0.0,\"Max\":0.0}]", "text/html": [ "
MetricSumMax
CNOT1010
QubitClifford22
R00
Measure00
T77
Depth55
Width33
QubitCount33
BorrowedWidth00
" ], "text/plain": [ - "Metric Sum Max\r\n", - "------------- -- --\r\n", - "CNOT 10 10\r\n", - "QubitClifford 2 2\r\n", - "R 0 0\r\n", - "Measure 0 0\r\n", - "T 7 7\r\n", - "Depth 5 5\r\n", - "Width 3 3\r\n", - "QubitCount 3 3\r\n", - "BorrowedWidth 0 0\r\n" + "Metric Sum Max\n", + "------------- -- --\n", + "CNOT 10 10\n", + "QubitClifford 2 2\n", + "R 0 0\n", + "Measure 0 0\n", + "T 7 7\n", + "Depth 5 5\n", + "Width 3 3\n", + "QubitCount 3 3\n", + "BorrowedWidth 0 0\n" ] }, - "execution_count": 6, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -230,21 +230,21 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 14, "metadata": {}, "outputs": [ { "data": { - "application/json": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.17.2105143879\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v3.1\"}]}", + "application/x-qsharp-data": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.24.210930\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v6.0\"}]}", "text/html": [ - "
ComponentVersion
iqsharp0.17.2105143879
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v3.1
" + "
ComponentVersion
iqsharp0.24.210930
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v6.0
" ], "text/plain": [ - "Component Version\r\n", - "------------ ------------------------\r\n", - "iqsharp 0.17.2105143879\r\n", - "Jupyter Core 1.5.0.0\r\n", - ".NET Runtime .NETCoreApp,Version=v3.1\r\n" + "Component Version\n", + "------------ ------------------------\n", + "iqsharp 0.24.210930\n", + "Jupyter Core 1.5.0.0\n", + ".NET Runtime .NETCoreApp,Version=v6.0\n" ] }, "metadata": {}, @@ -254,6 +254,13 @@ "source": [ "%version" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -266,7 +273,7 @@ "file_extension": ".qs", "mimetype": "text/x-qsharp", "name": "qsharp", - "version": "0.14" + "version": "0.24" } }, "nbformat": 4, diff --git a/ch11/ch11-exercise-solutions.ipynb b/ch11/ch11-exercise-solutions.ipynb index 85eccb6..53b61d6 100644 --- a/ch11/ch11-exercise-solutions.ipynb +++ b/ch11/ch11-exercise-solutions.ipynb @@ -480,21 +480,21 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 17, "metadata": {}, "outputs": [ { "data": { - "application/json": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.17.2105143879\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v3.1\"}]}", + "application/x-qsharp-data": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.24.210930\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v6.0\"}]}", "text/html": [ - "
ComponentVersion
iqsharp0.17.2105143879
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v3.1
" + "
ComponentVersion
iqsharp0.24.210930
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v6.0
" ], "text/plain": [ - "Component Version\r\n", - "------------ ------------------------\r\n", - "iqsharp 0.17.2105143879\r\n", - "Jupyter Core 1.5.0.0\r\n", - ".NET Runtime .NETCoreApp,Version=v3.1\r\n" + "Component Version\n", + "------------ ------------------------\n", + "iqsharp 0.24.210930\n", + "Jupyter Core 1.5.0.0\n", + ".NET Runtime .NETCoreApp,Version=v6.0\n" ] }, "metadata": {}, @@ -504,6 +504,13 @@ "source": [ "%version" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -516,7 +523,7 @@ "file_extension": ".qs", "mimetype": "text/x-qsharp", "name": "qsharp", - "version": "0.14" + "version": "0.24" } }, "nbformat": 4, diff --git a/ch11/operations.qs b/ch11/operations.qs index 41cf0c2..1397268 100644 --- a/ch11/operations.qs +++ b/ch11/operations.qs @@ -1,100 +1,100 @@ -// operations.qs: Sample code for Grover's search (Chapter 11). -// -// Copyright (c) Sarah Kaiser and Chris Granade. -// Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. -// Book ISBN 9781617296130. -// Code licensed under the MIT License. -// - -namespace GroverSearch { - open Microsoft.Quantum.Arithmetic; - open Microsoft.Quantum.Convert; - open Microsoft.Quantum.Math; - open Microsoft.Quantum.Arrays; - open Microsoft.Quantum.Canon; - open Microsoft.Quantum.Intrinsic; - - operation PrepareAllOnes(register : Qubit[]) : Unit is Adj + Ctl { - ApplyToEachCA(X, register); - } - - operation ReflectAboutAllOnes(register : Qubit[]) : Unit is Adj + Ctl { - Controlled Z(Most(register), - Tail(register)); - } - - operation PrepareInitialState(register : Qubit[]) : Unit is Adj + Ctl { - ApplyToEachCA(H, register); - } - - operation ReflectAboutInitialState( - prepareInitialState : (Qubit[] => Unit is Adj), - register : Qubit[]) - : Unit { - within { - Adjoint prepareInitialState(register); - PrepareAllOnes(register); - } apply { - ReflectAboutAllOnes(register); - } - } - - operation ReflectAboutMarkedState( - markedItemOracle : - ((Qubit[], Qubit) => Unit is Adj), - inputQubits : Qubit[]) - : Unit is Adj { - use flag = Qubit(); - within { - X(flag); - H(flag); - } apply{ - markedItemOracle(inputQubits, - flag); - } - } - - function NIterations(nQubits : Int) : Int { - let nItems = 1 <<< nQubits; - let angle = ArcSin(1. / - Sqrt(IntAsDouble(nItems))); - let nIterations = - Round(0.25 * PI() / angle - 0.5); - return nIterations; - } - - operation ApplyOracle( - idxMarkedItem : Int, - register : Qubit[], - flag : Qubit - ) : Unit is Adj + Ctl { - (ControlledOnInt(idxMarkedItem, X)) - (register, flag); - } - - operation SearchForMarkedItem( - nItems : Int, - markItem : ((Qubit[], Qubit) => Unit is Adj) - ) : Int { - use qubits = Qubit[BitSizeI(nItems)]; - PrepareInitialState(qubits); - - for idxIteration in - 0..NIterations(BitSizeI(nItems)) - 1 { - ReflectAboutMarkedState(markItem, qubits); - ReflectAboutInitialState(PrepareInitialState, qubits); - } - - return MeasureInteger(LittleEndian(qubits)); - } - - operation RunGroverSearch(nItems : Int, idxMarkedItem : Int) : Unit { - let markItem = ApplyOracle( - idxMarkedItem, _, _); - let foundItem = SearchForMarkedItem( - nItems, markItem); - Message( - $"Marked {idxMarkedItem} and found {foundItem}."); - } -} +// operations.qs: Sample code for Grover's search (Chapter 11). +// +// Copyright (c) Sarah Kaiser and Chris Granade. +// Code sample from the book "Learn Quantum Computing with Python and Q#" by +// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Book ISBN 9781617296130. +// Code licensed under the MIT License. +// + +namespace GroverSearch { + open Microsoft.Quantum.Arithmetic; + open Microsoft.Quantum.Convert; + open Microsoft.Quantum.Math; + open Microsoft.Quantum.Arrays; + open Microsoft.Quantum.Canon; + open Microsoft.Quantum.Intrinsic; + + operation PrepareAllOnes(register : Qubit[]) : Unit is Adj + Ctl { + ApplyToEachCA(X, register); + } + + operation ReflectAboutAllOnes(register : Qubit[]) : Unit is Adj + Ctl { + Controlled Z(Most(register), + Tail(register)); + } + + operation PrepareInitialState(register : Qubit[]) : Unit is Adj + Ctl { + ApplyToEachCA(H, register); + } + + operation ReflectAboutInitialState( + prepareInitialState : (Qubit[] => Unit is Adj), + register : Qubit[]) + : Unit { + within { + Adjoint prepareInitialState(register); + PrepareAllOnes(register); + } apply { + ReflectAboutAllOnes(register); + } + } + + operation ReflectAboutMarkedState( + markedItemOracle : + ((Qubit[], Qubit) => Unit is Adj), + inputQubits : Qubit[]) + : Unit is Adj { + use flag = Qubit(); + within { + X(flag); + H(flag); + } apply{ + markedItemOracle(inputQubits, + flag); + } + } + + function NIterations(nQubits : Int) : Int { + let nItems = 1 <<< nQubits; + let angle = ArcSin(1. / + Sqrt(IntAsDouble(nItems))); + let nIterations = + Round(0.25 * PI() / angle - 0.5); + return nIterations; + } + + operation ApplyOracle( + idxMarkedItem : Int, + register : Qubit[], + flag : Qubit + ) : Unit is Adj + Ctl { + (ControlledOnInt(idxMarkedItem, X)) + (register, flag); + } + + operation SearchForMarkedItem( + nItems : Int, + markItem : ((Qubit[], Qubit) => Unit is Adj) + ) : Int { + use qubits = Qubit[BitSizeI(nItems)]; + PrepareInitialState(qubits); + + for idxIteration in + 0..NIterations(BitSizeI(nItems)) - 1 { + ReflectAboutMarkedState(markItem, qubits); + ReflectAboutInitialState(PrepareInitialState, qubits); + } + + return MeasureInteger(LittleEndian(qubits)); + } + + operation RunGroverSearch(nItems : Int, idxMarkedItem : Int) : Unit { + let markItem = ApplyOracle( + idxMarkedItem, _, _); + let foundItem = SearchForMarkedItem( + nItems, markItem); + Message( + $"Marked {idxMarkedItem} and found {foundItem}."); + } +} diff --git a/ch11/plot_resources_vs_size.py b/ch11/plot_resources_vs_size.py index 35406ca..af4d3f1 100644 --- a/ch11/plot_resources_vs_size.py +++ b/ch11/plot_resources_vs_size.py @@ -1,25 +1,25 @@ -import numpy as np -import matplotlib.pyplot as plt -import random -import qsharp -from GroverSearch import RunGroverSearch - -if __name__ == "__main__": - - n_search_items = 2 ** np.arange(4, 25) - depth = np.empty_like(n_search_items) - - for idx, searchsize in enumerate(n_search_items): - estimate = RunGroverSearch.estimate_resources( - nItems=int(searchsize), - idxMarkedItem=int(random.randint(0,searchsize-1)) - ) - depth[idx] = estimate['Depth'] - - plt.plot(n_search_items, n_search_items, label='Classical') - plt.plot(n_search_items, depth, label='Quantum', linestyle='--') - plt.xlabel('# of Items') - plt.ylabel('# of Steps') - plt.legend() - - plt.show() +import numpy as np +import matplotlib.pyplot as plt +import random +import qsharp +from GroverSearch import RunGroverSearch + +if __name__ == "__main__": + + n_search_items = 2 ** np.arange(4, 25) + depth = np.empty_like(n_search_items) + + for idx, searchsize in enumerate(n_search_items): + estimate = RunGroverSearch.estimate_resources( + nItems=int(searchsize), + idxMarkedItem=int(random.randint(0,searchsize-1)) + ) + depth[idx] = estimate['Depth'] + + plt.plot(n_search_items, n_search_items, label='Classical') + plt.plot(n_search_items, depth, label='Quantum', linestyle='--') + plt.xlabel('# of Items') + plt.ylabel('# of Steps') + plt.legend() + + plt.show() diff --git a/ch12/IntegerFactorization.ipynb b/ch12/IntegerFactorization.ipynb index 3c09309..cd82e95 100644 --- a/ch12/IntegerFactorization.ipynb +++ b/ch12/IntegerFactorization.ipynb @@ -35,7 +35,7 @@ "outputs": [ { "data": { - "application/json": "\"\\\"true\\\"\"", + "application/x-qsharp-data": "\"\\\"true\\\"\"", "text/plain": [ "\"true\"" ] @@ -63,7 +63,7 @@ "outputs": [ { "data": { - "application/json": "{\"LastUpdated\":\"2021-05-27T08:41:20.2102965-07:00\",\"IsCompleted\":true,\"Description\":\"Adding package Microsoft.Quantum.Numerics\",\"Subtask\":\"done\"}", + "application/x-qsharp-data": "{\"LastUpdated\":\"2022-06-14T03:08:19.094622+00:00\",\"IsCompleted\":true,\"Description\":\"Adding package Microsoft.Quantum.Numerics\",\"Subtask\":\"done\"}", "text/plain": [ "Adding package Microsoft.Quantum.Numerics: done!" ] @@ -73,12 +73,12 @@ }, { "data": { - "application/json": "[\"Microsoft.Quantum.Standard::0.17.2105143879\",\"Microsoft.Quantum.Standard.Visualization::0.17.2105143879\",\"Microsoft.Quantum.Numerics::0.17.2105143879\"]", + "application/x-qsharp-data": "[\"Microsoft.Quantum.Standard::0.24.210930\",\"Microsoft.Quantum.Standard.Visualization::0.24.210930\",\"Microsoft.Quantum.Numerics::0.24.210930\"]", "text/html": [ - "
  • Microsoft.Quantum.Standard::0.17.2105143879
  • Microsoft.Quantum.Standard.Visualization::0.17.2105143879
  • Microsoft.Quantum.Numerics::0.17.2105143879
" + "
  • Microsoft.Quantum.Standard::0.24.210930
  • Microsoft.Quantum.Standard.Visualization::0.24.210930
  • Microsoft.Quantum.Numerics::0.24.210930
" ], "text/plain": [ - "Microsoft.Quantum.Standard::0.17.2105143879, Microsoft.Quantum.Standard.Visualization::0.17.2105143879, Microsoft.Quantum.Numerics::0.17.2105143879" + "Microsoft.Quantum.Standard::0.24.210930, Microsoft.Quantum.Standard.Visualization::0.24.210930, Microsoft.Quantum.Numerics::0.24.210930" ] }, "execution_count": 2, @@ -104,7 +104,7 @@ "outputs": [ { "data": { - "application/json": "[\"AddCustom\"]", + "application/x-qsharp-data": "[\"AddCustom\"]", "text/html": [ "
  • AddCustom
" ], @@ -162,12 +162,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "Before addition:\r\n" + "Before addition:\n" ] }, { "data": { - "application/json": "{\"div_id\":\"dump-machine-div-ac69a1af-9f0d-4cc6-a9ff-73f57bc48bf4\",\"qubit_ids\":[4,5,6,7],\"n_qubits\":4,\"amplitudes\":[{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":1.0,\"Imaginary\":0.0,\"Magnitude\":1.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0}]}", + "application/x-qsharp-data": "{\"diagnostic_kind\":\"state-vector\",\"qubit_ids\":[4,5,6,7],\"n_qubits\":4,\"amplitudes\":{\"0\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"1\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"2\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"3\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"4\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"5\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"6\":{\"Real\":1.0,\"Imaginary\":0.0,\"Magnitude\":1.0,\"Phase\":0.0},\"7\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"8\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"9\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"10\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"11\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"12\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"13\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"14\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"15\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0}}}", "text/html": [ "\r\n", " \r\n", @@ -196,12 +196,12 @@ " style=\"width: 100%;\"\r\n", "> \r\n", " \r\n", - "

\r\n", + "

\r\n", "

\r\n", " \r\n", " \r\n", @@ -228,12 +228,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "After addition:\r\n" + "After addition:\n" ] }, { "data": { - "application/json": "{\"div_id\":\"dump-machine-div-29e2048b-90ad-46a7-8472-8da26d66824c\",\"qubit_ids\":[4,5,6,7],\"n_qubits\":4,\"amplitudes\":[{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":1.0,\"Imaginary\":0.0,\"Magnitude\":1.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0}]}", + "application/x-qsharp-data": "{\"diagnostic_kind\":\"state-vector\",\"qubit_ids\":[4,5,6,7],\"n_qubits\":4,\"amplitudes\":{\"0\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"1\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"2\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"3\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"4\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"5\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"6\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"7\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"8\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"9\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"10\":{\"Real\":1.0,\"Imaginary\":0.0,\"Magnitude\":1.0,\"Phase\":0.0},\"11\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"12\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"13\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"14\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"15\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0}}}", "text/html": [ "\r\n", " \r\n", @@ -262,12 +262,12 @@ " style=\"width: 100%;\"\r\n", "> \r\n", " \r\n", - "

\r\n", + "

\r\n", "

\r\n", " \r\n", " \r\n", @@ -292,7 +292,7 @@ }, { "data": { - "application/json": "10", + "application/x-qsharp-data": "10", "text/plain": [ "10" ] @@ -320,7 +320,7 @@ "outputs": [ { "data": { - "application/json": "[\"PrepareSuperpositionOfTwoInts\",\"MultiplyInSuperpositionMod\"]", + "application/x-qsharp-data": "[\"PrepareSuperpositionOfTwoInts\",\"MultiplyInSuperpositionMod\"]", "text/html": [ "
  • PrepareSuperpositionOfTwoInts
  • MultiplyInSuperpositionMod
" ], @@ -410,12 +410,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "Before multiplication:\r\n" + "Before multiplication:\n" ] }, { "data": { - "application/json": "{\"div_id\":\"dump-machine-div-8fcc34c5-45b6-481c-ae68-79304d504dc5\",\"qubit_ids\":[0,1,2,3],\"n_qubits\":4,\"amplitudes\":[{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.7071067811865476,\"Imaginary\":0.0,\"Magnitude\":0.7071067811865476,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":-0.7071067811865476,\"Magnitude\":0.7071067811865476,\"Phase\":-1.5707963267948966},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0}]}", + "application/x-qsharp-data": "{\"diagnostic_kind\":\"state-vector\",\"qubit_ids\":[0,1,2,3],\"n_qubits\":4,\"amplitudes\":{\"0\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"1\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"2\":{\"Real\":0.7071067811865476,\"Imaginary\":0.0,\"Magnitude\":0.7071067811865476,\"Phase\":0.0},\"3\":{\"Real\":0.0,\"Imaginary\":-0.7071067811865476,\"Magnitude\":0.7071067811865476,\"Phase\":-1.5707963267948966},\"4\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"5\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"6\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"7\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"8\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"9\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"10\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"11\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"12\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"13\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"14\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},\"15\":{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0}}}", "text/html": [ "\r\n", " \r\n", @@ -444,12 +444,12 @@ " style=\"width: 100%;\"\r\n", "> \r\n", " \r\n", - "

\r\n", + "

\r\n", "

\r\n", " \r\n", " \r\n", @@ -474,12 +474,12 @@ " style=\"width: 100%;\"\r\n", "> \r\n", " \r\n", - "

\r\n", + "

\r\n", "

\r\n", " \r\n", " \r\n", @@ -507,12 +507,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "After multiplication:\r\n" + "After multiplication:\n" ] }, { "data": { - "application/json": "{\"div_id\":\"dump-machine-div-a66b6eb3-fc58-453c-b3fc-ff5c71e7fb8c\",\"qubit_ids\":[0,1,2,3],\"n_qubits\":4,\"amplitudes\":[{\"Real\":-2.053134880831493E-34,\"Imaginary\":1.2910504968323847E-33,\"Magnitude\":1.3072738862839787E-33,\"Phase\":1.7285039415654526},{\"Real\":4.895614577113624E-17,\"Imaginary\":-0.707106781186565,\"Magnitude\":0.707106781186565,\"Phase\":-1.5707963267948966},{\"Real\":8.737785755760589E-33,\"Imaginary\":-3.600686271093188E-33,\"Magnitude\":9.45060006224005E-33,\"Phase\":-0.3908785089499971},{\"Real\":-6.96587970384825E-33,\"Imaginary\":3.219848606333852E-33,\"Magnitude\":7.674040988696571E-33,\"Phase\":2.708613743994322},{\"Real\":8.260283341481202E-33,\"Imaginary\":5.696720612386342E-33,\"Magnitude\":1.0034186893672016E-32,\"Phase\":0.6037471577023479},{\"Real\":-2.1263373355983523E-33,\"Imaginary\":3.8842879449597495E-33,\"Magnitude\":4.428205427045942E-33,\"Phase\":2.071656658783588},{\"Real\":0.7071067811865637,\"Imaginary\":-5.144551441211654E-16,\"Magnitude\":0.7071067811865637,\"Phase\":-7.275494420487408E-16},{\"Real\":-7.798555202703428E-33,\"Imaginary\":5.921257574207684E-33,\"Magnitude\":9.791769733287471E-33,\"Phase\":2.4921811449131313},{\"Real\":3.760805630465078E-33,\"Imaginary\":-2.7798710862777163E-33,\"Magnitude\":4.676680686818449E-33,\"Phase\":-0.6365331810832874},{\"Real\":1.1496735851466057E-17,\"Imaginary\":1.1563400301803713E-17,\"Magnitude\":1.630604678572152E-17,\"Phase\":0.7882890511261407},{\"Real\":-1.2984998950412664E-32,\"Imaginary\":-2.2622285196330395E-34,\"Magnitude\":1.2986969412490675E-32,\"Phase\":-3.1241725545062455},{\"Real\":-6.747029060000957E-33,\"Imaginary\":-6.676217335949799E-33,\"Magnitude\":9.49180062229154E-33,\"Phase\":-2.361469746646994},{\"Real\":-4.777370743522004E-33,\"Imaginary\":5.975728454355033E-33,\"Magnitude\":7.650660218650962E-33,\"Phase\":2.245209432442664},{\"Real\":-1.9156089874010932E-34,\"Imaginary\":-9.909801346205675E-34,\"Magnitude\":1.0093251236042412E-33,\"Phase\":-1.761745674828624},{\"Real\":-5.7483679257332105E-18,\"Imaginary\":1.149673585146601E-17,\"Magnitude\":1.2853741441618554E-17,\"Phase\":2.034443935795717},{\"Real\":-1.3100164976577904E-32,\"Imaginary\":-1.0992533923188516E-32,\"Magnitude\":1.7101173189755394E-32,\"Phase\":-2.4434524273031974}]}", + "application/x-qsharp-data": "{\"diagnostic_kind\":\"state-vector\",\"qubit_ids\":[0,1,2,3],\"n_qubits\":4,\"amplitudes\":{\"0\":{\"Real\":1.2422261936729362E-32,\"Imaginary\":-2.9119100491260842E-33,\"Magnitude\":1.2758989448969564E-32,\"Phase\":-0.23025334663995392},\"1\":{\"Real\":-1.5232281402562548E-16,\"Imaginary\":-0.7071067811865567,\"Magnitude\":0.7071067811865567,\"Phase\":-1.5707963267948968},\"2\":{\"Real\":-2.6618380688318134E-32,\"Imaginary\":-1.87178595207219E-33,\"Magnitude\":2.668411087367542E-32,\"Phase\":-3.0713889139202335},\"3\":{\"Real\":-1.9959404939820973E-32,\"Imaginary\":-1.5055385784826876E-32,\"Magnitude\":2.500084971919389E-32,\"Phase\":-2.495345008135966},\"4\":{\"Real\":9.82466964426112E-33,\"Imaginary\":8.65328113843532E-33,\"Magnitude\":1.3092112437634593E-32,\"Phase\":0.7220890276612095},\"5\":{\"Real\":5.374248439198013E-32,\"Imaginary\":-3.9717766351943686E-33,\"Magnitude\":5.388904933529728E-32,\"Phase\":-0.07376974278656839},\"6\":{\"Real\":0.7071067811865562,\"Imaginary\":-9.33758885341901E-16,\"Magnitude\":0.7071067811865562,\"Phase\":-1.320534479636884E-15},\"7\":{\"Real\":3.321822124249853E-33,\"Imaginary\":-5.7530346065824564E-33,\"Magnitude\":6.643185185563562E-33,\"Phase\":-1.047157654196138},\"8\":{\"Real\":-1.4398553799661166E-32,\"Imaginary\":-2.3736271739520483E-33,\"Magnitude\":1.4592890648622726E-32,\"Phase\":-2.9782103331993652},\"9\":{\"Real\":1.1496735851465772E-17,\"Imaginary\":-4.351443200226003E-17,\"Magnitude\":4.5007563005762594E-17,\"Phase\":-1.3124934620731674},\"10\":{\"Real\":-1.5260590355596194E-32,\"Imaginary\":2.1696925590563605E-32,\"Magnitude\":2.6526254882357013E-32,\"Phase\":2.183768857124929},\"11\":{\"Real\":6.852457345385459E-34,\"Imaginary\":1.3314540931784101E-33,\"Magnitude\":1.4974417247241423E-33,\"Phase\":1.095489872938444},\"12\":{\"Real\":-1.301390189285331E-32,\"Imaginary\":-9.172565598096719E-34,\"Magnitude\":1.3046187261929242E-32,\"Phase\":-3.0712261982124045},\"13\":{\"Real\":-1.7399200457104502E-32,\"Imaginary\":2.089353921689888E-34,\"Magnitude\":1.7400454894760835E-32,\"Phase\":3.129584897789701},\"14\":{\"Real\":-3.11228915850131E-17,\"Imaginary\":3.925231146709488E-17,\"Magnitude\":5.009369557261979E-17,\"Phase\":2.2411888182973443},\"15\":{\"Real\":-6.422787487891192E-34,\"Imaginary\":5.7988583828965714E-33,\"Magnitude\":5.834319200732504E-33,\"Phase\":1.6811062273752184}}}", "text/html": [ "\r\n", " \r\n", @@ -532,27 +532,27 @@ " \r\n", " \r\n", " $\\left|1\\right\\rangle$\r\n", - " 0ドル.0000 -0.7071 i$\r\n", + " $-0.0000 -0.7071 i$\r\n", " \r\n", " \r\n", " \r\n", " \r\n", - "

\r\n", + "

\r\n", "

\r\n", " \r\n", " \r\n", " \r\n", " \r\n", - " \r\n", " ↑\r\n", " \r\n", @@ -567,22 +567,22 @@ " \r\n", " \r\n", " \r\n", - "

\r\n", + "

\r\n", "

\r\n", " \r\n", " \r\n", " \r\n", " \r\n", - " \r\n", " ↑\r\n", " \r\n", @@ -593,8 +593,8 @@ " " ], "text/plain": [ - "|1⟩\t4.895614577113624E-17 + -0.707106781186565i\n", - "|6⟩\t0.7071067811865637 + -5.144551441211654E-16i" + "|1⟩\t-1.5232281402562548E-16 + -0.7071067811865567i\n", + "|6⟩\t0.7071067811865562 + -9.33758885341901E-16i" ] }, "metadata": {}, @@ -602,9 +602,9 @@ }, { "data": { - "application/json": "1", + "application/x-qsharp-data": "6", "text/plain": [ - "1" + "6" ] }, "execution_count": 6, @@ -634,14 +634,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "We have guessed a divisor of 21 to be 3 by accident. Nothing left to do.\r\n" + "Estimating period of 8...\n" ] }, { "data": { - "application/json": "{\"@type\":\"@tuple\",\"Item1\":3,\"Item2\":7}", + "application/x-qsharp-data": "{\"@type\":\"@tuple\",\"Item1\":7,\"Item2\":3}", "text/plain": [ - "(3, 7)" + "(7, 3)" ] }, "execution_count": 7, @@ -662,14 +662,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "Estimating period of 5...\n", - "The estimated period did not yield a valid factor, trying again.\n", "We have guessed a divisor of 21 to be 3 by accident. Nothing left to do.\n" ] }, { "data": { - "application/json": "{\"@type\":\"@tuple\",\"Item1\":3,\"Item2\":7}", + "application/x-qsharp-data": "{\"@type\":\"@tuple\",\"Item1\":3,\"Item2\":7}", "text/plain": [ "(3, 7)" ] @@ -700,16 +698,16 @@ "outputs": [ { "data": { - "application/json": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.17.2105143879\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v3.1\"}]}", + "application/x-qsharp-data": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.24.210930\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v6.0\"}]}", "text/html": [ - "
ComponentVersion
iqsharp0.17.2105143879
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v3.1
" + "
ComponentVersion
iqsharp0.24.210930
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v6.0
" ], "text/plain": [ - "Component Version\r\n", - "------------ ------------------------\r\n", - "iqsharp 0.17.2105143879\r\n", - "Jupyter Core 1.5.0.0\r\n", - ".NET Runtime .NETCoreApp,Version=v3.1\r\n" + "Component Version\n", + "------------ ------------------------\n", + "iqsharp 0.24.210930\n", + "Jupyter Core 1.5.0.0\n", + ".NET Runtime .NETCoreApp,Version=v6.0\n" ] }, "metadata": {}, @@ -731,7 +729,7 @@ "file_extension": ".qs", "mimetype": "text/x-qsharp", "name": "qsharp", - "version": "0.14" + "version": "0.24" } }, "nbformat": 4, diff --git a/ch12/ch12-exercise-solutions.ipynb b/ch12/ch12-exercise-solutions.ipynb index bc860a9..1d82393 100644 --- a/ch12/ch12-exercise-solutions.ipynb +++ b/ch12/ch12-exercise-solutions.ipynb @@ -30,24 +30,9 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/json": "[\"Powers\"]", - "text/html": [ - "
  • Powers
" - ], - "text/plain": [ - "Powers" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "open Microsoft.Quantum.Arrays;\n", "open Microsoft.Quantum.Logical;\n", @@ -67,24 +52,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/json": "[1,11,16,8,4,2]", - "text/html": [ - "
  • 1
  • 11
  • 16
  • 8
  • 4
  • 2
" - ], - "text/plain": [ - "1, 11, 16, 8, 4, 2" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "%simulate Powers generator=11 modulus=21" ] @@ -146,24 +116,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/json": "[\"SharedFactorsFact\"]", - "text/html": [ - "
  • SharedFactorsFact
" - ], - "text/plain": [ - "SharedFactorsFact" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "open Microsoft.Quantum.Diagnostics;\n", "open Microsoft.Quantum.Math;\n", @@ -181,21 +136,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/json": "{\"@type\":\"tuple\"}", - "text/plain": [ - "()" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "%simulate SharedFactorsFact generator=19 modulus=143 period=60" ] @@ -217,24 +160,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/json": "[\"ExerciseGCD\"]", - "text/html": [ - "
  • ExerciseGCD
" - ], - "text/plain": [ - "ExerciseGCD" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "open Microsoft.Quantum.Math;\n", "function ExerciseGCD() : Int {\n", @@ -244,21 +172,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/json": "5", - "text/plain": [ - "5" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "%simulate ExerciseGCD" ] @@ -289,24 +205,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/json": "[\"PrepareSuperpositionOfTwoInts\",\"MultiplyInSuperpositionMod\"]", - "text/html": [ - "
  • PrepareSuperpositionOfTwoInts
  • MultiplyInSuperpositionMod
" - ], - "text/plain": [ - "PrepareSuperpositionOfTwoInts, MultiplyInSuperpositionMod" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "open Microsoft.Quantum.Arithmetic;\n", "open Microsoft.Quantum.Diagnostics;\n", @@ -349,1083 +250,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Before multiplication:\r\n" - ] - }, - { - "data": { - "application/json": "{\"div_id\":\"dump-machine-div-41c270d7-1d54-4bbe-af10-69a7e4173648\",\"qubit_ids\":[0,1,2,3],\"n_qubits\":4,\"amplitudes\":[{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.7071067811865476,\"Imaginary\":0.0,\"Magnitude\":0.7071067811865476,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":-0.7071067811865476,\"Magnitude\":0.7071067811865476,\"Phase\":-1.5707963267948966},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0}]}", - "text/html": [ - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - "
Qubit IDs0, 1, 2, 3
Basis state (little endian)AmplitudeMeas. Pr.Phase
$\\left|0\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|1\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|2\\right\\rangle$0ドル.7071 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|3\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|4\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|5\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|6\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|7\\right\\rangle$0ドル.0000 -0.7071 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|8\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|9\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|10\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|11\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|12\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|13\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|14\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|15\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
" - ], - "text/plain": [ - "|0⟩\t0 + 0i\n", - "|1⟩\t0 + 0i\n", - "|2⟩\t0.7071067811865476 + 0i\n", - "|3⟩\t0 + 0i\n", - "|4⟩\t0 + 0i\n", - "|5⟩\t0 + 0i\n", - "|6⟩\t0 + 0i\n", - "|7⟩\t0 + -0.7071067811865476i\n", - "|8⟩\t0 + 0i\n", - "|9⟩\t0 + 0i\n", - "|10⟩\t0 + 0i\n", - "|11⟩\t0 + 0i\n", - "|12⟩\t0 + 0i\n", - "|13⟩\t0 + 0i\n", - "|14⟩\t0 + 0i\n", - "|15⟩\t0 + 0i" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "After multiplication:\r\n" - ] - }, - { - "data": { - "application/json": "{\"div_id\":\"dump-machine-div-d3c3382b-1637-4c24-ae52-27b7fa4457a9\",\"qubit_ids\":[0,1,2,3],\"n_qubits\":4,\"amplitudes\":[{\"Real\":8.048776560288357E-33,\"Imaginary\":-1.460122887337483E-32,\"Magnitude\":1.6672692905770265E-32,\"Phase\":-1.0670018534527357},{\"Real\":0.7071067811865606,\"Imaginary\":1.9992185179568873E-16,\"Magnitude\":0.7071067811865606,\"Phase\":2.827321942242017E-16},{\"Real\":-8.65436685860561E-33,\"Imaginary\":3.4429570232036055E-33,\"Magnitude\":9.314076378630259E-33,\"Phase\":2.7629593368606225},{\"Real\":-6.577780649231735E-33,\"Imaginary\":-2.102246182297412E-32,\"Magnitude\":2.2027507788395216E-32,\"Phase\":-1.8740391691128941},{\"Real\":2.99216292339912E-32,\"Imaginary\":-5.787841102164402E-32,\"Magnitude\":6.515530951815671E-32,\"Phase\":-1.0936619714878015},{\"Real\":-1.7283263829171187E-32,\"Imaginary\":-1.620050236154245E-32,\"Magnitude\":2.3688973919422505E-32,\"Phase\":-2.3885201339779614},{\"Real\":3.9739786835464645E-32,\"Imaginary\":3.776080382166454E-32,\"Magnitude\":5.481905656782507E-32,\"Phase\":0.7598686411062161},{\"Real\":1.3396819126055798E-32,\"Imaginary\":-1.358643685327334E-33,\"Magnitude\":1.346553657898319E-32,\"Phase\":-0.10106983506666815},{\"Real\":1.6581641771351613E-16,\"Imaginary\":-0.707106781186564,\"Magnitude\":0.707106781186564,\"Phase\":-1.5707963267948963},{\"Real\":6.733339744291133E-33,\"Imaginary\":-4.237286353411284E-33,\"Magnitude\":7.955655834238689E-33,\"Phase\":-0.5616850135675081},{\"Real\":9.12850440141019E-18,\"Imaginary\":4.600413928980151E-17,\"Magnitude\":4.6901070610403177E-17,\"Phase\":1.3749128648565254},{\"Real\":-2.1154384951130604E-33,\"Imaginary\":-1.2052339377170018E-32,\"Magnitude\":1.2236583039766011E-32,\"Phase\":-1.7445474537255992},{\"Real\":7.690881461009681E-33,\"Imaginary\":6.904054068179995E-33,\"Magnitude\":1.0335164257216967E-32,\"Phase\":0.7315393134680052},{\"Real\":-9.59407778011189E-33,\"Imaginary\":1.2559367772680923E-32,\"Magnitude\":1.5804557801479067E-32,\"Phase\":2.2231330752300327},{\"Real\":-3.4477542521925934E-33,\"Imaginary\":-5.183290758564699E-33,\"Magnitude\":6.225231921088107E-33,\"Phase\":-2.1577600193794244},{\"Real\":3.074280240429881E-33,\"Imaginary\":-8.709147993958713E-33,\"Magnitude\":9.235824693949786E-33,\"Phase\":-1.2314564086356794}]}", - "text/html": [ - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - "
Qubit IDs0, 1, 2, 3
Basis state (little endian)AmplitudeMeas. Pr.Phase
$\\left|0\\right\\rangle$0ドル.0000 -0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|1\\right\\rangle$0ドル.7071 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|2\\right\\rangle$$-0.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|3\\right\\rangle$$-0.0000 -0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|4\\right\\rangle$0ドル.0000 -0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|5\\right\\rangle$$-0.0000 -0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|6\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|7\\right\\rangle$0ドル.0000 -0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|8\\right\\rangle$0ドル.0000 -0.7071 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|9\\right\\rangle$0ドル.0000 -0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|10\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|11\\right\\rangle$$-0.0000 -0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|12\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|13\\right\\rangle$$-0.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|14\\right\\rangle$$-0.0000 -0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|15\\right\\rangle$0ドル.0000 -0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
" - ], - "text/plain": [ - "|0⟩\t8.048776560288357E-33 + -1.460122887337483E-32i\n", - "|1⟩\t0.7071067811865606 + 1.9992185179568873E-16i\n", - "|2⟩\t-8.65436685860561E-33 + 3.4429570232036055E-33i\n", - "|3⟩\t-6.577780649231735E-33 + -2.102246182297412E-32i\n", - "|4⟩\t2.99216292339912E-32 + -5.787841102164402E-32i\n", - "|5⟩\t-1.7283263829171187E-32 + -1.620050236154245E-32i\n", - "|6⟩\t3.9739786835464645E-32 + 3.776080382166454E-32i\n", - "|7⟩\t1.3396819126055798E-32 + -1.358643685327334E-33i\n", - "|8⟩\t1.6581641771351613E-16 + -0.707106781186564i\n", - "|9⟩\t6.733339744291133E-33 + -4.237286353411284E-33i\n", - "|10⟩\t9.12850440141019E-18 + 4.600413928980151E-17i\n", - "|11⟩\t-2.1154384951130604E-33 + -1.2052339377170018E-32i\n", - "|12⟩\t7.690881461009681E-33 + 6.904054068179995E-33i\n", - "|13⟩\t-9.59407778011189E-33 + 1.2559367772680923E-32i\n", - "|14⟩\t-3.4477542521925934E-33 + -5.183290758564699E-33i\n", - "|15⟩\t3.074280240429881E-33 + -8.709147993958713E-33i" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/json": "8", - "text/plain": [ - "8" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "%simulate MultiplyInSuperpositionMod superpositionInt1=2 superpositionInt2=7 multiplier=5 modulus=9" ] @@ -1454,597 +281,11 @@ }, { "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Before multiplication:\r\n" - ] - }, - { - "data": { - "application/json": "{\"div_id\":\"dump-machine-div-acb54e75-b5b1-4d36-94a5-b32e9ab83f34\",\"qubit_ids\":[0,1,2,3],\"n_qubits\":4,\"amplitudes\":[{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.7071067811865476,\"Imaginary\":0.0,\"Magnitude\":0.7071067811865476,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":-0.7071067811865476,\"Magnitude\":0.7071067811865476,\"Phase\":-1.5707963267948966},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0},{\"Real\":0.0,\"Imaginary\":0.0,\"Magnitude\":0.0,\"Phase\":0.0}]}", - "text/html": [ - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - "
Qubit IDs0, 1, 2, 3
Basis state (little endian)AmplitudeMeas. Pr.Phase
$\\left|0\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|1\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|2\\right\\rangle$0ドル.7071 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|3\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|4\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|5\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|6\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|7\\right\\rangle$0ドル.0000 -0.7071 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|8\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|9\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|10\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|11\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|12\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|13\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|14\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
$\\left|15\\right\\rangle$0ドル.0000 + 0.0000 i$\r\n", - " \r\n", - " \r\n", - "

\r\n", - "

\r\n", - "
\r\n", - " ↑\r\n", - "
" - ], - "text/plain": [ - "|0⟩\t0 + 0i\n", - "|1⟩\t0 + 0i\n", - "|2⟩\t0.7071067811865476 + 0i\n", - "|3⟩\t0 + 0i\n", - "|4⟩\t0 + 0i\n", - "|5⟩\t0 + 0i\n", - "|6⟩\t0 + 0i\n", - "|7⟩\t0 + -0.7071067811865476i\n", - "|8⟩\t0 + 0i\n", - "|9⟩\t0 + 0i\n", - "|10⟩\t0 + 0i\n", - "|11⟩\t0 + 0i\n", - "|12⟩\t0 + 0i\n", - "|13⟩\t0 + 0i\n", - "|14⟩\t0 + 0i\n", - "|15⟩\t0 + 0i" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "\r\n", - "
\r\n", - " \r\n", - " Unhandled exception of type Microsoft.Quantum.Simulation.Core.ExecutionFailException: `constMultiplier` and `modulus` must be co-prime\n", - "\tExpected:\tTrue\n", - "\tActual:\tFalse\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \n", - "\r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - " \r\n", - "
SourceCallable
D:\\a\1円\\s\\submodules\\QuantumLibraries\\Standard\\src\\Arithmetic\\Modular.qs:234 Microsoft.Quantum.Arithmetic.MultiplyByModularInteger
(notebook)MultiplyInSuperpositionMod
\r\n", - "
\r\n", - " " - ], - "text/plain": [ - "Unhandled exception. Microsoft.Quantum.Simulation.Core.ExecutionFailException: `constMultiplier` and `modulus` must be co-prime\n", - "\tExpected:\tTrue\n", - "\tActual:\tFalse\r\n", - " ---> Microsoft.Quantum.Arithmetic.MultiplyByModularInteger on https://github.com/microsoft/QuantumLibraries/blob/f71e9fe09ff5570d7b45cd335990e01c2b111297/Standard/src/Arithmetic/Modular.qs#L234:line 234\r\n", - " at SNIPPET.MultiplyInSuperpositionMod on C:\\snippet_.qs:line 0\r\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "`constMultiplier` and `modulus` must be co-prime\n", - "\tExpected:\tTrue\n", - "\tActual:\tFalse\r\n" - ] - } - ], + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], "source": [ "%simulate MultiplyInSuperpositionMod superpositionInt1=2 superpositionInt2=7 multiplier=3 modulus=9" ] @@ -2074,12 +315,37 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/x-qsharp-data": "{\"rows\":[{\"@type\":\"@tuple\",\"Item1\":\"iqsharp\",\"Item2\":\"0.24.210930\"},{\"@type\":\"@tuple\",\"Item1\":\"Jupyter Core\",\"Item2\":\"1.5.0.0\"},{\"@type\":\"@tuple\",\"Item1\":\".NET Runtime\",\"Item2\":\".NETCoreApp,Version=v6.0\"}]}", + "text/html": [ + "
ComponentVersion
iqsharp0.24.210930
Jupyter Core1.5.0.0
.NET Runtime.NETCoreApp,Version=v6.0
" + ], + "text/plain": [ + "Component Version\n", + "------------ ------------------------\n", + "iqsharp 0.24.210930\n", + "Jupyter Core 1.5.0.0\n", + ".NET Runtime .NETCoreApp,Version=v6.0\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "%version" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -2092,7 +358,7 @@ "file_extension": ".qs", "mimetype": "text/x-qsharp", "name": "qsharp", - "version": "0.14" + "version": "0.24" } }, "nbformat": 4, diff --git a/ch12/operations.qs b/ch12/operations.qs index 157c0ea..2b60d2f 100644 --- a/ch12/operations.qs +++ b/ch12/operations.qs @@ -1,174 +1,174 @@ -// IntegerFactorization.qs: Sample code for integer factorization example (Chapter 12). -// -// Copyright (c) Sarah Kaiser and Chris Granade. -// Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. -// Book ISBN 9781617296130. -// Code licensed under the MIT License. -// -// Adapted from the QDK samples repo here: -// https://github.com/microsoft/Quantum/tree/master/samples/ - -namespace IntegerFactorization { - open Microsoft.Quantum.Canon; - open Microsoft.Quantum.Convert; - open Microsoft.Quantum.Oracles; - open Microsoft.Quantum.Characterization; - open Microsoft.Quantum.Diagnostics; - open Microsoft.Quantum.Math; - open Microsoft.Quantum.Random; - open Microsoft.Quantum.Intrinsic; - open Microsoft.Quantum.Arithmetic; - - operation FactorSemiprimeInteger(number : Int) : (Int, Int) { - if number % 2 == 0 { - Message("An even number has been given; 2 is a factor."); - return (number / 2, 2); - } - mutable factors = (1, 1); - mutable foundFactors = false; - - repeat { - let generator = DrawRandomInt( - 3, number - 2); - - if IsCoprimeI(generator, number) { - Message($"Estimating period of {generator}..."); - let period = EstimatePeriod( - generator, number); - set (foundFactors, factors) = - MaybeFactorsFromPeriod( - generator, period, number - ); - } else { - let gcd = GreatestCommonDivisorI( - number, generator); - Message( - $"We have guessed a divisor of {number} to be " + - $"{gcd} by accident. Nothing left to do." - ); - set foundFactors = true; - set factors = (gcd, number / gcd); - } - } - until foundFactors - fixup { - Message( - "The estimated period did not yield a valid factor, " + - "trying again." - ); - } - return factors; - } - - function MaybeFactorsFromPeriod( - generator : Int, period : Int, number : Int) - : (Bool, (Int, Int)) { - if period % 2 == 0 { - - let halfPower = ExpModI(generator, - period / 2, number); - - if (halfPower != number - 1) { - let factor = MaxI( - GreatestCommonDivisorI(halfPower - 1, number), - GreatestCommonDivisorI(halfPower + 1, number) - ); - return (true, (factor, number / factor)); - } else { - return (false, (1, 1)); - } - } else { - return (false, (1, 1)); - } - } - - operation EstimatePeriod(generator : Int, modulus : Int) : Int { - Fact( - IsCoprimeI(generator, modulus), - "`generator` and `modulus` must be co-prime" - ); - - let bitSize = BitSizeI(modulus); - let nBitsPrecision = 2 * bitSize + 1; - mutable result = 1; - mutable frequencyEstimate = 0; - - repeat { - set frequencyEstimate = - EstimateFrequency( - ApplyPeriodFindingOracle( - generator, modulus, _, _ - ), - nBitsPrecision, bitSize - ); - - if frequencyEstimate != 0 { - set result = - PeriodFromFrequency( - frequencyEstimate, nBitsPrecision, - modulus, result - ); - } else { - Message("The estimated frequency was 0, trying again."); - } - } - until ExpModI(generator, result, modulus) == 1 - fixup { - Message( - "The estimated period from continued fractions failed, " + - "trying again." - ); - } - return result; - } - - operation EstimateFrequency( - inputOracle : ((Int, Qubit[]) => Unit is Adj+Ctl), - nBitsPrecision : Int, - bitSize : Int) - : Int { - use register = Qubit[bitSize]; - - let registerLE = LittleEndian(register); - ApplyXorInPlace(1, registerLE); - - let phase = RobustPhaseEstimation( - nBitsPrecision, - DiscreteOracle(inputOracle), - registerLE! - ); - ResetAll(register); - - return Round( - (phase * IntAsDouble(2 ^ nBitsPrecision)) / (2.0 * PI()) - ); - } - - function PeriodFromFrequency( - frequencyEstimate : Int, nBitsPrecision : Int, - modulus : Int, result : Int) - : Int { - let continuedFraction = ContinuedFractionConvergentI( - Fraction(frequencyEstimate, 2^nBitsPrecision), modulus - ); - let denominator = AbsI(Snd(continuedFraction!)); - return (denominator * result) / GreatestCommonDivisorI( - result, denominator - ); - } - - operation ApplyPeriodFindingOracle( - generator : Int, modulus : Int, power : Int, target : Qubit[]) - : Unit is Adj + Ctl { - Fact( - IsCoprimeI(generator, modulus), - "The generator and modulus must be co-prime." - ); - MultiplyByModularInteger( - ExpModI(generator, power, modulus), - modulus, - LittleEndian(target) - ); - } -} +// IntegerFactorization.qs: Sample code for integer factorization example (Chapter 12). +// +// Copyright (c) Sarah Kaiser and Chris Granade. +// Code sample from the book "Learn Quantum Computing with Python and Q#" by +// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Book ISBN 9781617296130. +// Code licensed under the MIT License. +// +// Adapted from the QDK samples repo here: +// https://github.com/microsoft/Quantum/tree/master/samples/ + +namespace IntegerFactorization { + open Microsoft.Quantum.Canon; + open Microsoft.Quantum.Convert; + open Microsoft.Quantum.Oracles; + open Microsoft.Quantum.Characterization; + open Microsoft.Quantum.Diagnostics; + open Microsoft.Quantum.Math; + open Microsoft.Quantum.Random; + open Microsoft.Quantum.Intrinsic; + open Microsoft.Quantum.Arithmetic; + + operation FactorSemiprimeInteger(number : Int) : (Int, Int) { + if number % 2 == 0 { + Message("An even number has been given; 2 is a factor."); + return (number / 2, 2); + } + mutable factors = (1, 1); + mutable foundFactors = false; + + repeat { + let generator = DrawRandomInt( + 3, number - 2); + + if IsCoprimeI(generator, number) { + Message($"Estimating period of {generator}..."); + let period = EstimatePeriod( + generator, number); + set (foundFactors, factors) = + MaybeFactorsFromPeriod( + generator, period, number + ); + } else { + let gcd = GreatestCommonDivisorI( + number, generator); + Message( + $"We have guessed a divisor of {number} to be " + + $"{gcd} by accident. Nothing left to do." + ); + set foundFactors = true; + set factors = (gcd, number / gcd); + } + } + until foundFactors + fixup { + Message( + "The estimated period did not yield a valid factor, " + + "trying again." + ); + } + return factors; + } + + function MaybeFactorsFromPeriod( + generator : Int, period : Int, number : Int) + : (Bool, (Int, Int)) { + if period % 2 == 0 { + + let halfPower = ExpModI(generator, + period / 2, number); + + if (halfPower != number - 1) { + let factor = MaxI( + GreatestCommonDivisorI(halfPower - 1, number), + GreatestCommonDivisorI(halfPower + 1, number) + ); + return (true, (factor, number / factor)); + } else { + return (false, (1, 1)); + } + } else { + return (false, (1, 1)); + } + } + + operation EstimatePeriod(generator : Int, modulus : Int) : Int { + Fact( + IsCoprimeI(generator, modulus), + "`generator` and `modulus` must be co-prime" + ); + + let bitSize = BitSizeI(modulus); + let nBitsPrecision = 2 * bitSize + 1; + mutable result = 1; + mutable frequencyEstimate = 0; + + repeat { + set frequencyEstimate = + EstimateFrequency( + ApplyPeriodFindingOracle( + generator, modulus, _, _ + ), + nBitsPrecision, bitSize + ); + + if frequencyEstimate != 0 { + set result = + PeriodFromFrequency( + frequencyEstimate, nBitsPrecision, + modulus, result + ); + } else { + Message("The estimated frequency was 0, trying again."); + } + } + until ExpModI(generator, result, modulus) == 1 + fixup { + Message( + "The estimated period from continued fractions failed, " + + "trying again." + ); + } + return result; + } + + operation EstimateFrequency( + inputOracle : ((Int, Qubit[]) => Unit is Adj+Ctl), + nBitsPrecision : Int, + bitSize : Int) + : Int { + use register = Qubit[bitSize]; + + let registerLE = LittleEndian(register); + ApplyXorInPlace(1, registerLE); + + let phase = RobustPhaseEstimation( + nBitsPrecision, + DiscreteOracle(inputOracle), + registerLE! + ); + ResetAll(register); + + return Round( + (phase * IntAsDouble(2 ^ nBitsPrecision)) / (2.0 * PI()) + ); + } + + function PeriodFromFrequency( + frequencyEstimate : Int, nBitsPrecision : Int, + modulus : Int, result : Int) + : Int { + let continuedFraction = ContinuedFractionConvergentI( + Fraction(frequencyEstimate, 2^nBitsPrecision), modulus + ); + let denominator = AbsI(Snd(continuedFraction!)); + return (denominator * result) / GreatestCommonDivisorI( + result, denominator + ); + } + + operation ApplyPeriodFindingOracle( + generator : Int, modulus : Int, power : Int, target : Qubit[]) + : Unit is Adj + Ctl { + Fact( + IsCoprimeI(generator, modulus), + "The generator and modulus must be co-prime." + ); + MultiplyByModularInteger( + ExpModI(generator, power, modulus), + modulus, + LittleEndian(target) + ); + } +} diff --git a/environment.yml b/environment.yml index 8335c43..1465d13 100644 --- a/environment.yml +++ b/environment.yml @@ -1,12 +1,12 @@ -name: qsharp-book -channels: -- conda-forge -- quantum-engineering -dependencies: -- notebook -- numpy -- scipy -- qutip -- matplotlib -- pip -- qsharp==0.17.2105.143879 +name: qsharp-book +channels: +- conda-forge +- microsoft +dependencies: +- notebook +- numpy +- scipy +- qutip +- matplotlib +- pip +- qsharp==0.24.210930 From 5a5e2f11a52f6e3cf0921c7a6b419b6a2cd7620b Mon Sep 17 00:00:00 2001 From: Cassandra Granade Date: 2022年6月14日 03:15:14 +0000 Subject: [PATCH 3/6] Update name. --- .github/workflows/build-devcontainer.yml | 4 ++-- LICENSE | 2 +- README.md | 2 +- apxb/apxb-exercise-solutions.ipynb | 4 ++-- ch02/interface.py | 4 ++-- ch02/qrng.py | 4 ++-- ch02/simulator.py | 4 ++-- ch03/bb84.py | 4 ++-- ch03/ch03-exercise-solutions.ipynb | 4 ++-- ch03/interface.py | 4 ++-- ch03/qkd.py | 4 ++-- ch03/simulator.py | 4 ++-- ch04/ch04-exercise-solutions.ipynb | 4 ++-- ch04/chsh.py | 4 ++-- ch05/ch05-exercise-solutions.ipynb | 4 ++-- ch05/chsh.py | 4 ++-- ch05/interface.py | 4 ++-- ch05/simulator.py | 4 ++-- ch06/ch06-exercise-solutions.ipynb | 4 ++-- ch06/interface.py | 4 ++-- ch06/simulator.py | 4 ++-- ch06/teleport.py | 4 ++-- ch07/BiasedQrng/Operation.qs | 4 ++-- ch07/ClassicalHello/EntryPoint.qs | 4 ++-- ch07/ClassicalHello/Operation.qs | 4 ++-- ch07/Qrng/Operation.qs | 4 ++-- ch07/ch07-exercise-solutions.ipynb | 4 ++-- ch07/chapter-07.ipynb | 4 ++-- ch08/Algorithm.qs | 4 ++-- ch08/Oracles.qs | 4 ++-- ch08/ch08-exercise-solutions.ipynb | 4 ++-- ch09/ch09-exercise-solutions.ipynb | 4 ++-- ch09/host.ipynb | 4 ++-- ch09/host.py | 4 ++-- ch09/operations.qs | 4 ++-- ch09/qsharp-interop.py | 4 ++-- ch10/ch10-exercise-solutions.ipynb | 4 ++-- ch10/host.ipynb | 4 ++-- ch10/host.py | 4 ++-- ch10/operations.qs | 4 ++-- ch11/GroverSearch.ipynb | 4 ++-- ch11/ResourceEstimation.ipynb | 4 ++-- ch11/ch11-exercise-solutions.ipynb | 4 ++-- ch11/operations.qs | 4 ++-- ch12/IntegerFactorization.ipynb | 4 ++-- ch12/ch12-exercise-solutions.ipynb | 4 ++-- ch12/operations.qs | 4 ++-- 47 files changed, 92 insertions(+), 92 deletions(-) diff --git a/.github/workflows/build-devcontainer.yml b/.github/workflows/build-devcontainer.yml index 0c6bda1..b8eccc2 100644 --- a/.github/workflows/build-devcontainer.yml +++ b/.github/workflows/build-devcontainer.yml @@ -2,9 +2,9 @@ # build-devcontainer.yml: GitHub Actions configuration for building sample # Docker images. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/LICENSE b/LICENSE index 0dfacf4..dfa2c01 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Sarah Kaiser and Chris Granade. +Copyright (c) 2019 Sarah Kaiser and Cassandra Granade. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 216c679..cf24d85 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![](https://img.shields.io/github/license/crazy4pi314/learn-qc-with-python-and-qsharp)](https://github.com/crazy4pi314/learn-qc-with-python-and-qsharp/blob/main/LICENSE) -This repository provides sample code for [_Learn Quantum Computing with Python and Q#_](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp) (Dr. Sarah Kaiser and Dr. Chris Granade, Manning Publications), available from [Manning Publications](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338), [Amazon](https://www.amazon.com/Learn-Quantum-Computing-Python-hands/dp/1617296139/), and a variety of local resellers. +This repository provides sample code for [_Learn Quantum Computing with Python and Q#_](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp) (Dr. Sarah Kaiser and Dr. Cassandra Granade, Manning Publications), available from [Manning Publications](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338), [Amazon](https://www.amazon.com/Learn-Quantum-Computing-Python-hands/dp/1617296139/), and a variety of local resellers. Below, we provide some instructions on getting started with each sample; please see [Appendix A](https://livebook.manning.com/book/learn-quantum-computing-with-python-and-q-sharp/appendix-a?origin=product-toc) for more details. diff --git a/apxb/apxb-exercise-solutions.ipynb b/apxb/apxb-exercise-solutions.ipynb index 528027e..6c5ad15 100644 --- a/apxb/apxb-exercise-solutions.ipynb +++ b/apxb/apxb-exercise-solutions.ipynb @@ -6,9 +6,9 @@ "source": [ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Appendix B Exercise Solutions\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch02/interface.py b/ch02/interface.py index 3c72e59..399ddd8 100644 --- a/ch02/interface.py +++ b/ch02/interface.py @@ -4,9 +4,9 @@ # interface.py: Contains classes that define the interface to the qubit # simulator in simulator.py. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch02/qrng.py b/ch02/qrng.py index 9d66ae2..a0869b6 100644 --- a/ch02/qrng.py +++ b/ch02/qrng.py @@ -4,9 +4,9 @@ # qrng.py: Defines and runs a quantum random number generator (qrng) using # the interface defined in interface.py and the simulator in simulator.py. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch02/simulator.py b/ch02/simulator.py index 2dcb21a..32c7279 100644 --- a/ch02/simulator.py +++ b/ch02/simulator.py @@ -3,9 +3,9 @@ ## # simulator.py: Defines a class that implements a single qubit simulator. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch03/bb84.py b/ch03/bb84.py index e8e230f..a76bf4b 100644 --- a/ch03/bb84.py +++ b/ch03/bb84.py @@ -5,9 +5,9 @@ # distribution. Uses the single qubit simulator defined in simulator.py, # and the interface to the simulator defined in interface.py. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch03/ch03-exercise-solutions.ipynb b/ch03/ch03-exercise-solutions.ipynb index e5ff84f..524071a 100644 --- a/ch03/ch03-exercise-solutions.ipynb +++ b/ch03/ch03-exercise-solutions.ipynb @@ -6,9 +6,9 @@ "source": [ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 3 Exercise Solutions\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch03/interface.py b/ch03/interface.py index 6937914..68ee7d9 100644 --- a/ch03/interface.py +++ b/ch03/interface.py @@ -4,9 +4,9 @@ # interface.py: Contains classes that define the interface to the qubit # simulator in simulator.py. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch03/qkd.py b/ch03/qkd.py index 2dc4211..ee95b5f 100644 --- a/ch03/qkd.py +++ b/ch03/qkd.py @@ -4,9 +4,9 @@ # qkd.py: Defines functions needed to perform a basic quantum key exchange # protocol. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch03/simulator.py b/ch03/simulator.py index 81b377d..f486d5c 100644 --- a/ch03/simulator.py +++ b/ch03/simulator.py @@ -3,9 +3,9 @@ ## # simulator.py: Defines a class that implements a single qubit simulator. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch04/ch04-exercise-solutions.ipynb b/ch04/ch04-exercise-solutions.ipynb index 255193a..01f94e5 100644 --- a/ch04/ch04-exercise-solutions.ipynb +++ b/ch04/ch04-exercise-solutions.ipynb @@ -6,9 +6,9 @@ "source": [ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 4 Exercise Solutions\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch04/chsh.py b/ch04/chsh.py index ce1c25d..1913b1c 100644 --- a/ch04/chsh.py +++ b/ch04/chsh.py @@ -4,9 +4,9 @@ # chsh.py: Implements the CHSH nonlocal game using the multi-qubit simulator # in simulator.py with the simulator interface defined in interface.py. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch05/ch05-exercise-solutions.ipynb b/ch05/ch05-exercise-solutions.ipynb index 4985b41..eb7f856 100644 --- a/ch05/ch05-exercise-solutions.ipynb +++ b/ch05/ch05-exercise-solutions.ipynb @@ -6,9 +6,9 @@ "source": [ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 5 Exercise Solutions\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch05/chsh.py b/ch05/chsh.py index ed8ce98..52a8d22 100644 --- a/ch05/chsh.py +++ b/ch05/chsh.py @@ -4,9 +4,9 @@ # chsh.py: Implements the CHSH nonlocal game using the multi-qubit simulator # in simulator.py with the simulator interface defined in interface.py. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch05/interface.py b/ch05/interface.py index a25a6d6..961a4f0 100644 --- a/ch05/interface.py +++ b/ch05/interface.py @@ -4,9 +4,9 @@ # interface.py: Contains classes that define the interface to the qubit # simulator in simulator.py. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch05/simulator.py b/ch05/simulator.py index 1e34f7c..bac6441 100644 --- a/ch05/simulator.py +++ b/ch05/simulator.py @@ -3,9 +3,9 @@ ## # simulator.py: Defines a class that implements a multi-qubit simulator. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch06/ch06-exercise-solutions.ipynb b/ch06/ch06-exercise-solutions.ipynb index 48fb1d8..82e4779 100644 --- a/ch06/ch06-exercise-solutions.ipynb +++ b/ch06/ch06-exercise-solutions.ipynb @@ -6,9 +6,9 @@ "source": [ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 6 Exercise Solutions\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch06/interface.py b/ch06/interface.py index db1cc53..81caf82 100644 --- a/ch06/interface.py +++ b/ch06/interface.py @@ -4,9 +4,9 @@ # interface.py: Contains classes that define the interface to the qubit # simulator in simulator.py. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch06/simulator.py b/ch06/simulator.py index 5a637c4..b19c5d8 100644 --- a/ch06/simulator.py +++ b/ch06/simulator.py @@ -3,9 +3,9 @@ ## # simulator.py: Defines a class that implements a multi-qubit simulator. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch06/teleport.py b/ch06/teleport.py index d75cf0e..1d32869 100644 --- a/ch06/teleport.py +++ b/ch06/teleport.py @@ -4,9 +4,9 @@ # teleport.py: Implements a quantum teleportation program using the simulator # in simulator.py with the interface defined in interface.py. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch07/BiasedQrng/Operation.qs b/ch07/BiasedQrng/Operation.qs index d2bce69..7952f25 100644 --- a/ch07/BiasedQrng/Operation.qs +++ b/ch07/BiasedQrng/Operation.qs @@ -1,9 +1,9 @@ // Operation.qs: Sample code for a biased quantum random number generator // (Chapter 7). // -// Copyright (c) Sarah Kaiser and Chris Granade. +// Copyright (c) Sarah Kaiser and Cassandra Granade. // Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. // Book ISBN 9781617296130. // Code licensed under the MIT License. diff --git a/ch07/ClassicalHello/EntryPoint.qs b/ch07/ClassicalHello/EntryPoint.qs index 3722b89..23904b7 100644 --- a/ch07/ClassicalHello/EntryPoint.qs +++ b/ch07/ClassicalHello/EntryPoint.qs @@ -1,9 +1,9 @@ // Operation.qs: Demo of the Message function used to make a HelloWorld program // (Chapter 7). // -// Copyright (c) Sarah Kaiser and Chris Granade. +// Copyright (c) Sarah Kaiser and Cassandra Granade. // Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. // Book ISBN 9781617296130. // Code licensed under the MIT License. diff --git a/ch07/ClassicalHello/Operation.qs b/ch07/ClassicalHello/Operation.qs index ac3e508..4ec0140 100644 --- a/ch07/ClassicalHello/Operation.qs +++ b/ch07/ClassicalHello/Operation.qs @@ -1,9 +1,9 @@ // Operation.qs: Demo of the Message function used to make a HelloWorld program // (Chapter 7). // -// Copyright (c) Sarah Kaiser and Chris Granade. +// Copyright (c) Sarah Kaiser and Cassandra Granade. // Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. // Book ISBN 9781617296130. // Code licensed under the MIT License. diff --git a/ch07/Qrng/Operation.qs b/ch07/Qrng/Operation.qs index 1cecb06..b6fd765 100644 --- a/ch07/Qrng/Operation.qs +++ b/ch07/Qrng/Operation.qs @@ -1,8 +1,8 @@ // Operation.qs: Sample code for a quantum random number generator (Chapter 7). // -// Copyright (c) Sarah Kaiser and Chris Granade. +// Copyright (c) Sarah Kaiser and Cassandra Granade. // Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. // Book ISBN 9781617296130. // Code licensed under the MIT License. diff --git a/ch07/ch07-exercise-solutions.ipynb b/ch07/ch07-exercise-solutions.ipynb index b3c430d..fe97c72 100644 --- a/ch07/ch07-exercise-solutions.ipynb +++ b/ch07/ch07-exercise-solutions.ipynb @@ -6,9 +6,9 @@ "source": [ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 7 Exercise Solutions\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch07/chapter-07.ipynb b/ch07/chapter-07.ipynb index 2138679..5293a0f 100644 --- a/ch07/chapter-07.ipynb +++ b/ch07/chapter-07.ipynb @@ -7,9 +7,9 @@ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)\n", "# Chapter 7 | Changing the odds: An introduction to Q#\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch08/Algorithm.qs b/ch08/Algorithm.qs index ed772b9..0d7cdda 100644 --- a/ch08/Algorithm.qs +++ b/ch08/Algorithm.qs @@ -1,8 +1,8 @@ // Algorithm.qs: Sample code for Deutsch Jozsa algorithm (Chapter 8). // -// Copyright (c) Sarah Kaiser and Chris Granade. +// Copyright (c) Sarah Kaiser and Cassandra Granade. // Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. // Book ISBN 9781617296130. // Code licensed under the MIT License. diff --git a/ch08/Oracles.qs b/ch08/Oracles.qs index a45fac7..56bf72d 100644 --- a/ch08/Oracles.qs +++ b/ch08/Oracles.qs @@ -1,9 +1,9 @@ // Oracles.qs: Sample code for oracles used in the one bit version of the // Deutsch Jozsa algorithim (Chapter 8). // -// Copyright (c) Sarah Kaiser and Chris Granade. +// Copyright (c) Sarah Kaiser and Cassandra Granade. // Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. // Book ISBN 9781617296130. // Code licensed under the MIT License. diff --git a/ch08/ch08-exercise-solutions.ipynb b/ch08/ch08-exercise-solutions.ipynb index 62ad839..9e9810b 100644 --- a/ch08/ch08-exercise-solutions.ipynb +++ b/ch08/ch08-exercise-solutions.ipynb @@ -6,9 +6,9 @@ "source": [ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 8 Exercise Solutions\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch09/ch09-exercise-solutions.ipynb b/ch09/ch09-exercise-solutions.ipynb index fcb8f8a..84951fc 100644 --- a/ch09/ch09-exercise-solutions.ipynb +++ b/ch09/ch09-exercise-solutions.ipynb @@ -6,9 +6,9 @@ "source": [ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 9 Exercise Solutions\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch09/host.ipynb b/ch09/host.ipynb index e6747ef..3661c61 100644 --- a/ch09/host.ipynb +++ b/ch09/host.ipynb @@ -7,9 +7,9 @@ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)\n", "# Chapter 9 | Quantum sensing: It's not just a phase\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License.\n", "---" diff --git a/ch09/host.py b/ch09/host.py index 8ae14a4..82d04a2 100644 --- a/ch09/host.py +++ b/ch09/host.py @@ -3,9 +3,9 @@ ## # host.py: Runs the host program for the phase estimation quantum algorithm. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch09/operations.qs b/ch09/operations.qs index c71afd5..98b8f7a 100644 --- a/ch09/operations.qs +++ b/ch09/operations.qs @@ -1,8 +1,8 @@ // operations.qs: Sample code for Phase Estimation (Chapter 9). // -// Copyright (c) Sarah Kaiser and Chris Granade. +// Copyright (c) Sarah Kaiser and Cassandra Granade. // Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. // Book ISBN 9781617296130. // Code licensed under the MIT License. diff --git a/ch09/qsharp-interop.py b/ch09/qsharp-interop.py index 62c58d2..ade2aa9 100644 --- a/ch09/qsharp-interop.py +++ b/ch09/qsharp-interop.py @@ -3,9 +3,9 @@ ## # qsharp-interop.py: Demo showing how Q# code can be run from a Python host. ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch10/ch10-exercise-solutions.ipynb b/ch10/ch10-exercise-solutions.ipynb index 5664c47..1b6421d 100644 --- a/ch10/ch10-exercise-solutions.ipynb +++ b/ch10/ch10-exercise-solutions.ipynb @@ -6,9 +6,9 @@ "source": [ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 10 Exercise Solutions\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch10/host.ipynb b/ch10/host.ipynb index 480f9ef..0588d1e 100644 --- a/ch10/host.ipynb +++ b/ch10/host.ipynb @@ -7,9 +7,9 @@ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)\n", "# Chapter 10 | Solving chemistry problems with quantum computers\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License.\n", "---" diff --git a/ch10/host.py b/ch10/host.py index 0d0d720..b9cba1d 100644 --- a/ch10/host.py +++ b/ch10/host.py @@ -3,9 +3,9 @@ ## # host.py: Host program for the Hamiltonian simulation example (Chapter 9). ## -# Copyright (c) Sarah Kaiser and Chris Granade. +# Copyright (c) Sarah Kaiser and Cassandra Granade. # Code sample from the book "Learn Quantum Computing with Python and Q#" by -# Sarah Kaiser and Chris Granade, published by Manning Publications Co. +# Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. # Book ISBN 9781617296130. # Code licensed under the MIT License. ## diff --git a/ch10/operations.qs b/ch10/operations.qs index c7e8fc6..de48934 100644 --- a/ch10/operations.qs +++ b/ch10/operations.qs @@ -1,8 +1,8 @@ // operations.qs: Sample code for Hamiltonian simulation (Chapter 10). // -// Copyright (c) Sarah Kaiser and Chris Granade. +// Copyright (c) Sarah Kaiser and Cassandra Granade. // Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. // Book ISBN 9781617296130. // Code licensed under the MIT License. // diff --git a/ch11/GroverSearch.ipynb b/ch11/GroverSearch.ipynb index 8666f1f..31e0211 100644 --- a/ch11/GroverSearch.ipynb +++ b/ch11/GroverSearch.ipynb @@ -7,9 +7,9 @@ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)\n", "# Chapter 11 | Searching with quantum computers\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch11/ResourceEstimation.ipynb b/ch11/ResourceEstimation.ipynb index d339158..3427b2e 100644 --- a/ch11/ResourceEstimation.ipynb +++ b/ch11/ResourceEstimation.ipynb @@ -7,9 +7,9 @@ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)\n", "# Chapter 11 | Resource Estimation Example\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch11/ch11-exercise-solutions.ipynb b/ch11/ch11-exercise-solutions.ipynb index 53b61d6..7c9c8ba 100644 --- a/ch11/ch11-exercise-solutions.ipynb +++ b/ch11/ch11-exercise-solutions.ipynb @@ -6,9 +6,9 @@ "source": [ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 11 Exercise Solutions\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch11/operations.qs b/ch11/operations.qs index 1397268..3d5d67f 100644 --- a/ch11/operations.qs +++ b/ch11/operations.qs @@ -1,8 +1,8 @@ // operations.qs: Sample code for Grover's search (Chapter 11). // -// Copyright (c) Sarah Kaiser and Chris Granade. +// Copyright (c) Sarah Kaiser and Cassandra Granade. // Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. // Book ISBN 9781617296130. // Code licensed under the MIT License. // diff --git a/ch12/IntegerFactorization.ipynb b/ch12/IntegerFactorization.ipynb index cd82e95..e293a90 100644 --- a/ch12/IntegerFactorization.ipynb +++ b/ch12/IntegerFactorization.ipynb @@ -7,9 +7,9 @@ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)\n", "# Chapter 12 | Arithmetic with quantum computers\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch12/ch12-exercise-solutions.ipynb b/ch12/ch12-exercise-solutions.ipynb index 1d82393..de4ee39 100644 --- a/ch12/ch12-exercise-solutions.ipynb +++ b/ch12/ch12-exercise-solutions.ipynb @@ -6,9 +6,9 @@ "source": [ "# [Learn Quantum Computing with Python and Q#](https://www.manning.com/books/learn-quantum-computing-with-python-and-q-sharp?a_aid=learn-qc-granade&a_bid=ee23f338)
Chapter 12 Exercise Solutions\n", "----\n", - "> Copyright (c) Sarah Kaiser and Chris Granade.\n", + "> Copyright (c) Sarah Kaiser and Cassandra Granade.\n", "> Code sample from the book \"Learn Quantum Computing with Python and Q#\" by\n", - "> Sarah Kaiser and Chris Granade, published by Manning Publications Co.\n", + "> Sarah Kaiser and Cassandra Granade, published by Manning Publications Co.\n", "> Book ISBN 9781617296130.\n", "> Code licensed under the MIT License." ] diff --git a/ch12/operations.qs b/ch12/operations.qs index 2b60d2f..7bcc7e7 100644 --- a/ch12/operations.qs +++ b/ch12/operations.qs @@ -1,8 +1,8 @@ // IntegerFactorization.qs: Sample code for integer factorization example (Chapter 12). // -// Copyright (c) Sarah Kaiser and Chris Granade. +// Copyright (c) Sarah Kaiser and Cassandra Granade. // Code sample from the book "Learn Quantum Computing with Python and Q#" by -// Sarah Kaiser and Chris Granade, published by Manning Publications Co. +// Sarah Kaiser and Cassandra Granade, published by Manning Publications Co. // Book ISBN 9781617296130. // Code licensed under the MIT License. // From c6fc0a77b9cf6fd354b664b64f8f6ecd95d78c54 Mon Sep 17 00:00:00 2001 From: Cassandra Granade Date: 2022年6月13日 20:34:45 -0700 Subject: [PATCH 4/6] Update for changes in latest QuTiP. --- ch05/simulator.py | 4 ++-- ch06/simulator.py | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ch05/simulator.py b/ch05/simulator.py index bac6441..9719ff9 100644 --- a/ch05/simulator.py +++ b/ch05/simulator.py @@ -12,7 +12,7 @@ from interface import QuantumDevice, Qubit import qutip as qt -from qutip.qip.operations import hadamard_transform +from qutip.qip.operations import hadamard_transform, gate_expand_1toN import numpy as np from typing import List @@ -38,7 +38,7 @@ def x(self) -> None: def measure(self) -> bool: projectors = [ - qt.circuit.gate_expand_1toN( + gate_expand_1toN( qt.basis(2, outcome) * qt.basis(2, outcome).dag(), self.parent.capacity, self.qubit_id diff --git a/ch06/simulator.py b/ch06/simulator.py index b19c5d8..b93fdf6 100644 --- a/ch06/simulator.py +++ b/ch06/simulator.py @@ -12,7 +12,9 @@ from interface import QuantumDevice, Qubit import qutip as qt -from qutip.qip.operations import hadamard_transform +from qutip.qip.operations import ( + hadamard_transform, gate_expand_1toN, gate_expand_2toN +) import numpy as np from typing import List @@ -32,7 +34,7 @@ def h(self) -> None: def measure(self) -> bool: projectors = [ - qt.circuit.gate_expand_1toN( + gate_expand_1toN( qt.basis(2, outcome) * qt.basis(2, outcome).dag(), self.parent.capacity, self.qubit_id @@ -118,10 +120,10 @@ def deallocate_qubit(self, qubit: SimulatedQubit): def _apply(self, unitary: qt.Qobj, ids: List[int]): if len(ids) == 1: - matrix = qt.circuit.gate_expand_1toN(unitary, + matrix = gate_expand_1toN(unitary, self.capacity, ids[0]) elif len(ids) == 2: - matrix = qt.circuit.gate_expand_2toN(unitary, + matrix = gate_expand_2toN(unitary, self.capacity, *ids) else: raise ValueError("Only one- or two-qubit unitary matrices supported.") From ee19c27c2b61d67bafbbc694c8d3c7b5c165a480 Mon Sep 17 00:00:00 2001 From: Cassandra Granade Date: 2022年6月13日 20:36:41 -0700 Subject: [PATCH 5/6] Rebuild devcontainer. --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e5038c1..f16ddd2 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,5 +1,5 @@ { - "dockerFile": "./Dockerfile", + "image": "sckaiser/learn-qc-with-python-and-qsharp:latest", "remoteEnv": { "IQSHARP_HOSTING_ENV": "QSHARP_BOOK_DEVCONTAINER" }, From a752b5ecec533b000d37b0ff06eb44493ca0140d Mon Sep 17 00:00:00 2001 From: Cassandra Granade Date: 2022年6月13日 20:37:19 -0700 Subject: [PATCH 6/6] Update GH action. --- .github/workflows/build-devcontainer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-devcontainer.yml b/.github/workflows/build-devcontainer.yml index b8eccc2..5d4caae 100644 --- a/.github/workflows/build-devcontainer.yml +++ b/.github/workflows/build-devcontainer.yml @@ -19,7 +19,7 @@ jobs: steps: - uses: actions/checkout@v2 - - uses: elgohr/Publish-Docker-Github-Action@master + - uses: elgohr/Publish-Docker-Github-Action@v4 with: name: sckaiser/learn-qc-with-python-and-qsharp username: ${{ secrets.DOCKER_USERNAME }}

AltStyle によって変換されたページ (->オリジナル) /