This repository was archived by the owner on Aug 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ExploringDJAlgorithm] Refactor tutorial (#725)
This change splits the tutorial in three parts: * problem definition and classical algorithm, * single-qubit oracles and Deutsch algorithm (new tasks added), * multi-qubit oracles and Deutsch-Jozsa algorithm.
- Loading branch information
1 parent
bcf92fa
commit 500441e
Showing
9 changed files
with
638 additions
and
223 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
189 changes: 189 additions & 0 deletions
189
tutorials/ExploringDeutschJozsaAlgorithm/DeutschJozsaAlgorithmTutorial_P1.ipynb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Deutsch–Jozsa Algorithm Tutorial (Part I)\n", | ||
"\n", | ||
"The **Deutsch–Jozsa algorithm** is one of the most famous algorithms in quantum computing. The problem it solves has little practical value, but the algorithm itself is one of the earliest examples of a quantum algorithm that is exponentially faster than any possible deterministic algorithm for the same problem. It is also relatively simple to explain and illustrates several very important concepts (such as quantum oracles). As such, Deutsch–Jozsa algorithm is part of almost every introductory course on quantum computing.\n", | ||
"\n", | ||
"This tutorial will:\n", | ||
"* introduce you to the problems solved by the Deutsch and Deutsch–Jozsa algorithms and walk you through the classical solution to them,\n", | ||
"* give you a brief introduction to quantum oracles (for a more detailed introduction, see the [Oracles tutorial](../Oracles/Oracles.ipynb)),\n", | ||
"* describe the idea behind the Deutsch and Deutsch–Jozsa algorithms and walk you through the math for them,\n", | ||
"* teach you how to implement the algorithms in the Q# programming language,\n", | ||
"* and finally help you to run your implementation of the algorithm on several quantum oracles to see for yourself how the algorithm works!\n", | ||
"\n", | ||
"Let's go!\n", | ||
"\n", | ||
"This tutorial consists of several notebooks:\n", | ||
"1. Part I covers the problem statement and the classical algorithm for solving it.\n", | ||
"2. [Part II](./DeutschJozsaAlgorithmTutorial_P2.ipynb) introduces single-qubit quantum oracles and Deutsch algorithm for solving the problem for one-bit input functions.\n", | ||
"3. [Part III](./DeutschJozsaAlgorithmTutorial_P3.ipynb) introduces multi-qubit quantum oracles and Deutsch-Jozsa algorithm for solving the general case of the problem." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Part I. Problem statement and classical algorithm\n", | ||
"\n", | ||
"## The problem\n", | ||
"\n", | ||
"You are given a classical function $f(x): \\{0, 1\\}^N \\to \\{0, 1\\}$. You are guaranteed that the function $f$ is\n", | ||
"* either *constant* (has the same value for all inputs) \n", | ||
"* or *balanced* (has value 0 for half of the inputs and 1 for the other half of the inputs). \n", | ||
"\n", | ||
"The task is to figure out whether the function is constant or balanced.\n", | ||
"\n", | ||
"For the single-bit functions ($N = 1$) the problem can be formulated in a simpler way: given a classical function $f(x): \\{0, 1\\} \\to \\{0, 1\\}$, figure out whether $f(0) = f(1)$. \n", | ||
"Indeed, $f(0) = f(1)$ is an equivalent definition of a constant single-bit function, and $f(0) \\neq f(1)$ - of a balanced single-bit function.\n", | ||
"\n", | ||
"> ## Examples\n", | ||
">\n", | ||
"> * $f(x) \\equiv 0$ or $f(x) \\equiv 1$ are examples of constant functions (and they are actually the only constant functions in existence).\n", | ||
"> * For single-bit functions, $f(x) = x$ and $f(x) = 1 - x$ are the only existing balanced functions.\n", | ||
"> * $f(x) = x \\bmod 2$ (the least significant bit of $x$) or $f(x) = 1 \\text{ if the binary notation of }x \\text{ has odd number of 1s and 0 otherwise}$ are examples of multi-bit balanced functions. \n", | ||
"> Indeed, for both these functions you can check that for every possible input $x$ for which $f(x) = 0$ there exists an input $x^\\prime$ (equal to $x$ with the least significant bit flipped) such that $f(x^\\prime) = 1$, and vice versa, which means that the function is balanced.\n", | ||
">\n", | ||
"> There exist more complicated examples of balanced functions, but we will not need to consider them for this tutorial.\n", | ||
"\n", | ||
"## Implementing classical functions in Q#\n", | ||
"\n", | ||
"Here is the implementation of these functions in Q#; it is pretty self-descriptory, since the functions are not only very simple but also classical.\n", | ||
"\n", | ||
"> **Note**: These are just code samples, you don't have to modify the code and they are not covered by tests." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"// Function 1. f(x) = 0\n", | ||
"function Function_Zero (x : Int) : Int {\n", | ||
" return 0;\n", | ||
"}\n", | ||
"\n", | ||
"\n", | ||
"// Function 2. f(x) = 1\n", | ||
"function Function_One (x : Int) : Int {\n", | ||
" return 1;\n", | ||
"}\n", | ||
"\n", | ||
"\n", | ||
"// Function 3. f(x) = x mod 2 (least significant bit of x)\n", | ||
"function Function_Xmod2 (x : Int) : Int {\n", | ||
" return x % 2;\n", | ||
"}\n", | ||
"\n", | ||
"\n", | ||
"// Function 4. f(x) = 1 if the binary notation of x has odd number of 1s, and 0 otherwise\n", | ||
"function Function_OddNumberOfOnes (x : Int) : Int {\n", | ||
" mutable nOnes = 0;\n", | ||
" mutable xBits = x;\n", | ||
" while (xBits > 0) {\n", | ||
" if (xBits % 2 > 0) {\n", | ||
" set nOnes += 1;\n", | ||
" }\n", | ||
" set xBits /= 2;\n", | ||
" }\n", | ||
" return nOnes % 2;\n", | ||
"}" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## <span style=\"color:blue\">Exercise 1</span>: Implement a classical function in Q#\n", | ||
"\n", | ||
"Try to implement a similar classical function in Q#!\n", | ||
"\n", | ||
"**Inputs:** \n", | ||
"1. An integer $x$.\n", | ||
"2. The number of bits in the input $N$ ($1 \\le N \\le 5$, $0 \\le x \\le 2^N-1$).\n", | ||
"\n", | ||
"**Output:** Return $f(x) = \\text{the most significant bit of }x$.\n", | ||
"\n", | ||
"> Useful documentation: [Q# Bitwise Expressions](https://docs.microsoft.com/azure/quantum/user-guide/language/expressions/bitwiseexpressions)." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"%kata T1_ClassicalFunction \n", | ||
"\n", | ||
"function Function_MostSignificantBit (x : Int, N : Int) : Int {\n", | ||
" // ...\n", | ||
"}" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Classical algorithm\n", | ||
"\n", | ||
"If we solve this problem classically, how many calls to the given function will we need? \n", | ||
"\n", | ||
"The first call will give us no information - regardless of whether it returns 0 or 1, the function could still be constant or balanced.\n", | ||
"In the best case scenario the second call will return a different value and we'll be able to conclude that the function is balanced in just <span style=\"color:red\">$2$</span> calls. \n", | ||
"However, if we get the same value for the first two calls, we'll have to keep querying the function until either we get a different value or until we do <span style=\"color:red\">$2^{N-1}+1$</span> queries that will return the same value - in this case we'll know for certain that the function will be constant.\n", | ||
"\n", | ||
"## <span style=\"color:blue\">Exercise 2</span>: Implement the classical algorithm!\n", | ||
"\n", | ||
"Q# is a domain-specific language, so it is not designed to handle arbitrary classical computations. However, this classical algorithm is so simple that you can easily implement it in Q#. Try it!\n", | ||
"\n", | ||
"**Inputs:** \n", | ||
"1. The number of bits in the input $N$ ($1 \\le N \\le 5$).\n", | ||
"2. The \"black box\" function that evaluates $f(x)$ on any given input $x \\in [0, 2^N-1]$. \n", | ||
" You are guaranteed that the function implemented by the black box is either constant or balanced.\n", | ||
"\n", | ||
"**Goal:** Return `true` if the function is constant, or `false` if it is balanced.\n", | ||
"\n", | ||
"> Useful documentation: [Q# statements](https://docs.microsoft.com/azure/quantum/user-guide/language/statements/)." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"%kata T2_ClassicalAlgorithm \n", | ||
"\n", | ||
"operation IsFunctionConstant_Classical (N : Int, f : (Int -> Int)) : Bool {\n", | ||
" // ...\n", | ||
"}" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Continue to [part II](./DeutschJozsaAlgorithmTutorial_P2.ipynb) to learn about single-qubit quantum oracles and Deutsch algorithm for solving the problem for one-bit input functions." | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Q#", | ||
"language": "qsharp", | ||
"name": "iqsharp" | ||
}, | ||
"language_info": { | ||
"file_extension": ".qs", | ||
"mimetype": "text/x-qsharp", | ||
"name": "qsharp", | ||
"version": "0.14" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
Oops, something went wrong.