{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "7bd5137ff0b2" }, "source": [ "##### Copyright 2021 The Cirq Developers" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "cellView": "form", "execution": { "iopub.execute_input": "2024-08-16T10:54:46.673313Z", "iopub.status.busy": "2024-08-16T10:54:46.672782Z", "iopub.status.idle": "2024-08-16T10:54:46.676873Z", "shell.execute_reply": "2024-08-16T10:54:46.676234Z" }, "id": "906e07f6e562" }, "outputs": [], "source": [ "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# https://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." ] }, { "cell_type": "markdown", "metadata": { "id": "ytiXnAqTUBrB" }, "source": [ "# Fourier Checking Problem" ] }, { "cell_type": "markdown", "metadata": { "id": "view-in-github" }, "source": [ "\n", " \n", " \n", " \n", " \n", "
\n", " View on QuantumAI\n", " \n", " Run in Google Colab\n", " \n", " View source on GitHub\n", " \n", " Download notebook\n", "
" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:54:46.680268Z", "iopub.status.busy": "2024-08-16T10:54:46.679747Z", "iopub.status.idle": "2024-08-16T10:55:03.936897Z", "shell.execute_reply": "2024-08-16T10:55:03.936073Z" }, "id": "-7UPLcFfFzVv" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "installing cirq...\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\r\n", "tensorflow-metadata 1.15.0 requires protobuf<4.21,>=3.20.3; python_version < \"3.11\", but you have protobuf 4.25.4 which is incompatible.\u001b[0m\u001b[31m\r\n", "\u001b[0m" ] }, { "name": "stdout", "output_type": "stream", "text": [ "installed cirq.\n" ] } ], "source": [ "# Initial setup to install cirq and set up dependencies for the tutorial.\n", "try:\n", " import cirq\n", "except:\n", " print(\"installing cirq...\")\n", " !pip install --quiet cirq\n", " print(\"installed cirq.\")\n", " import cirq\n", "\n", "from typing import Sequence, Tuple\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import pandas as pd\n", "\n", "# Sets a seed for deterministic results. Uncomment for random results each run.\n", "np.random.seed(2021)\n", "np.set_printoptions(precision=3, suppress=True, linewidth=200)" ] }, { "cell_type": "markdown", "metadata": { "id": "2k_4KaHyDMSh" }, "source": [ "# Introduction\n", "\n", "\n", "In past decades, there is ample evidence suggesting that quantum computers can be exponentially more powerful in solving certain computational tasks than their classical couterparts. The *black-box* or *query* model, such as Grover’s search, Deutsch-Jozsa’s algorithm, etc., offers a concrete setting to show such exponential speedups. Normally, one provides \"black-box access\" to a function $f$, meaning that the quantum algorithm can apply a unitary\n", "transformation that maps basis states of the form $|x, y \\rangle$ to to basis states of the form $|x, y \\oplus f(x)\\rangle $ or $|x\\rangle$ to $(-1)^{f(x)} |x\\rangle$ if $f$ is Boolean. Then, a natural question is asked:\n", "\n", "> What is the maximal possible separation between quantum and classical query complexities?\n", "\n", "For example, could there be a function of $N$ bits with a quantum query\n", "complexity of 1, but a classical randomized query complexity of $\\Omega(\\sqrt{N})$ or $\\Omega(N)$?\n", "Specifically, [Buhrman et al. from 2002](https://www.sciencedirect.com/science/article/pii/S030439750100144X) asked whether there is any\n", "property of $N-$bit strings that exhibits a **“maximal”** separation: that is, one that requires $\\Omega(N)$\n", "queries to test classically, but only O (1) quantumly.\n", "\n", "**Fourier Checking** is a problem that provides a separation between quantum and classical computers -- $O(1)$ VS $\\tilde{\\Omega}(\\sqrt{N})$, which can be proved as optimal. Currently, it only has theoretical importance - but, as it falls into the category of small quantum algorithms, it can be used to demonstrate query complexity and oracle synthesis in Cirq.\n", "\n", "Goal of this notebook is to introduce:\n", "\n", "1. What is Forrelation and the Fourier Checking problem and why we are interested in it?\n", "2. What is bounded-error quantum polynomial time (BQP) and why does the Fourier Checking problem belong to it?\n", "3. How to implement the Fourier Checking algorithm and an oracle function in Cirq?\n", "\n", "We won't include the formal proofs and argument. However, we do give sketches of the derivation for intuition and encourage the reader to check the corresponding lemmas and theorems in the original paper.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "hq6-obwCiEXX" }, "source": [ "# Preliminary\n", "\n", "Before we present the Fourier Checking problem, three preliminary concepts, 1) BPP and BQP 2) Fourier Transform over $Z_2^n$ and 3) Forrelation, are introduced first.\n" ] }, { "cell_type": "markdown", "metadata": { "id": "HNCLXihE01A7" }, "source": [ "## Bounded-error Probabilistic Polynomial time (BPP)\n", "\n", "In computational complexity theory, [bounded-error probabilistic polynomial time (BPP)](https://en.wikipedia.org/wiki/BPP_(complexity)) is the class of decision problems solvable by a [probabilistic Turing machine](https://en.wikipedia.org/wiki/Probabilistic_Turing_machine) in polynomial time with an error probability bounded away from 1/3 for all instances:\n", "\n", "|        Anwser Provided

Correct Anwser| Yes

  | No

 |\n", "|:---------------|------|-------|\n", "| Yes | $\\geq$ 2/3 | $\\leq$ 1/3 |\n", "| No | $\\leq$ 1/3 | $\\geq$ 2/3 |\n", "\n", "The choice of 1/3 in the definition is arbitrary. It can be any constant between 0 and ​1/2 (exclusive) and the set BPP will be unchanged." ] }, { "cell_type": "markdown", "metadata": { "id": "Mj1IjP3TWVn0" }, "source": [ "To understand this better, let's consider a simple example.\n", "\n", "**Problem**: Supposing we have a boolean function $f: \\{0, 1\\}^n \\rightarrow\\{-1, 1\\}$. The function is drawn either from distribution $\\mathcal{B}$ or $\\mathcal{C}$. Under the distribution $\\mathcal{B}$, the function $f$ is balanced, i.e., $\\sum_{x} f(x) = 0$. Under the distribution $\\mathcal{C}$, the function $f$ is constant, i.e., function is always equal to $+1$ or $-1$. The problem is to accept the function if it is drawn from $\\mathcal{B}$ or reject it otherwise.\n", "\n", "For example, consider the case that $n=2$. There are only four possible functions listed in following table\n", "\n", "|x | f_0(x)| f_1(x)| f_2(x)| f_3(x)|\n", "|----|----:|----:|----:|----:|\n", "| 0 | +1 | -1 | +1 | -1 |\n", "| 1 | -1 | +1 | +1 | -1 |\n", "\n", "Clearly, $f_0$ and $f_1$ belongs to $\\mathcal{B}$ and $f_2$ and $f_3$ belongs to $\\mathcal{C}$.\n", "\n", "**Deterministic Algorithm**: We evaluate the outputs of function of $2^{n-1}+1$ different inputs. If the results contain both $+1$ and $-1$ value, the function must be drawn from distribution $\\mathcal{B}$. Otherwise, it must come from $\\mathcal{C}$.\n", "\n", "Remembering that the function is guaranteed to be either balanced or constant, not somewhere in between. So above algorithm is guaranteed to be always correct. However, the query complexity is $O(N)$, denoting $N=2^n$. Here we are interested in the query complexity instead of computation complexity. Namely, how many times we have to evaluate $f$ -- which you can imagine being a very costly function. If the bounded-error probability is acceptable for solving the problem, we can achieve better algorithm in terms of query complexity.\n", "\n", "**Randomized Algorithm**: Randomly select $K$ different inputs and evaluate the corresponding outputs. If both $+1$ and $-1$ are observed, we accept it. Otherwise, it reject it.\n", "\n", "The complexity of algorithm depends on the choice of $K$. For this problem, selecting fixed number is sufficient, i.e. $O(1)$ query complexity. It is worth to remark that $O(1)$ means no matter the fixed number is independent of the input size of function $N$. Consider the $K=2$ case, it is not hard to establish the following confusion matrix regardless of $N$:\n", "\n", "| Randomized Algorithm (K=2): | Accept | Reject |\n", "|---------------|---------|-------|\n", "| Drawn from $\\mathcal{B}$ | 1/2 | 1/2 |\n", "| Drawn from $\\mathcal{C}$ | 0 | 1 |\n", "\n", "This is not sufficient to solve it. However, if we select $K>2$ entries, the probability of correctness will boost. Let's use the code to exam it." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:03.942061Z", "iopub.status.busy": "2024-08-16T10:55:03.941226Z", "iopub.status.idle": "2024-08-16T10:55:03.949548Z", "shell.execute_reply": "2024-08-16T10:55:03.948888Z" }, "id": "DzkklbuNWWEi" }, "outputs": [], "source": [ "def gen_balanced_function(N: int) -> np.ndarray:\n", " \"\"\"Generates a balanced function for N bits.\n", "\n", " Creates a function 𝑓:{0,1}^N → {−1,1}\n", " where f(x)=-1 for half of the inputs and f(x)=1 for the other half.\n", "\n", " Returns:\n", " the function as represented by a 1-d numpy array of size N\n", " \"\"\"\n", " half_size = N // 2\n", " f = np.ones(N)\n", " flip_loc = np.random.permutation(N)[:half_size]\n", " f[flip_loc] = -1\n", " return f\n", "\n", "\n", "def gen_constant_function(N: int) -> np.ndarray:\n", " \"\"\"Generates a constant function for N bits.\n", "\n", " Creates a function 𝑓:{0,1}^𝑛 → {−1,1}\n", " where f(x)=c for all inputs.\n", " \n", " c is randomly chosen as either -1 or 1, but, once chosen,\n", " is constant for all values of x.\n", "\n", " Returns:\n", " the function as represented by a 1-d numpy array of size N\n", " \"\"\"\n", "\n", " flip = np.random.random() > 0.5\n", " f = np.ones(N) if flip else -1 * np.ones(N)\n", " return f\n", "\n", "def choose_random_function() -> Tuple[str, np.ndarray]:\n", " \"\"\"Randomly choose a function from constant or balanced distributions.\n", "\n", " Returns:\n", " a Tuple of the distribution (\"B\" or \"C\") and the function as an array.\n", " \"\"\"\n", " if np.random.rand() > 0.5:\n", " f = gen_balanced_function(N)\n", " dist = \"B\"\n", " else:\n", " f = gen_constant_function(N)\n", " dist = \"C\"\n", " return dist, f\n", "\n", "def randomized_alg(f:np.ndarray, sample_size:int) -> str:\n", " \"\"\"Samples the function f from `sample_size` different inputs.\n", "\n", " Queries the function f a number of times equal to sample_size.\n", " If all the inputs are the same, then guess that the function\n", " is constant. If any inputs are different, then guess the function\n", " is balanced.\n", "\n", " Args:\n", " f: the function to sample\n", " sample_size: number of times to sample the function f\n", "\n", " Returns:\n", " a string representing the type of function, either\n", " \"balanced\" or \"constant\"\n", " \"\"\"\n", " N = len(f)\n", " sample_index = np.random.choice(N, size=sample_size)\n", " if len(set(f[sample_index])) == 2:\n", " return \"balanced\"\n", " return \"constant\"" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:03.952789Z", "iopub.status.busy": "2024-08-16T10:55:03.952267Z", "iopub.status.idle": "2024-08-16T10:55:04.506671Z", "shell.execute_reply": "2024-08-16T10:55:04.505931Z" }, "id": "Zo7zeqllWWNf" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Decisionbalancedconstant
Distribution
B75.4624.54
CNaN100.00
\n", "
" ], "text/plain": [ "Decision balanced constant\n", "Distribution \n", "B 75.46 24.54\n", "C NaN 100.00" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "N = 128 # size of the problem, n=7, N=2^7=128\n", "samples_size_per_function = 3\n", "number_of_functions_to_try = 1000\n", "\n", "\n", "res = pd.DataFrame()\n", "for _ in range(number_of_functions_to_try):\n", " dist, f = choose_random_function()\n", " decision = randomized_alg(f, samples_size_per_function)\n", " res=pd.concat([res, pd.DataFrame({\n", " \"Distribution\": [dist],\n", " \"Decision\":[decision],\n", " \"Count\": [1]\n", " })], ignore_index=True)\n", "confusion = res.pivot_table(index=\"Distribution\",\n", " columns=\"Decision\",\n", " values=\"Count\",\n", " aggfunc=\"sum\")\n", "# Translate the counts into percentage\n", "confusion.div(confusion.sum(axis=1), axis=0).apply(lambda x: round(x, 4) * 100)" ] }, { "cell_type": "markdown", "metadata": { "id": "dU4e1_FrbME1" }, "source": [ "Recall that the B in BPP means *bounded-error*. Actually, you can achieve arbitary small error rate under the same query complexity order. Say, you set an acceptable error rate $\\epsilon$. Then the key is that we can run the algorithm multiple times. Repeat it as many times as you want until the error rate is lower than $\\epsilon$. It is crucial to note that the error rate for this particular problem does not depend on the size of the input but only on the size of the sample and the reptitation. For this reason, in order to get to a bounded probability error, it is sufficient to just adjust the sample size and/or repetitions to a given constant - which means that the \"query complexity\" of the algorithm will stay $O(1)$. For example, let's run previous algorithms 3 times and make the final decision based on the majority of the decision of each term. You should verify that the probability of error indeed decreased and independent of $N$." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:04.510321Z", "iopub.status.busy": "2024-08-16T10:55:04.509783Z", "iopub.status.idle": "2024-08-16T10:55:05.079326Z", "shell.execute_reply": "2024-08-16T10:55:05.078596Z" }, "id": "uY_VUjr0bLS_" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Decisionbalancedconstant
Distribution
B86.9213.08
CNaN100.00
\n", "
" ], "text/plain": [ "Decision balanced constant\n", "Distribution \n", "B 86.92 13.08\n", "C NaN 100.00" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "N = 128\n", "samples_size_per_function = 3\n", "repetitions_of_randomized_alg = 3\n", "number_of_functions_to_try = 1000\n", "\n", "res = pd.DataFrame()\n", "for _ in range(number_of_functions_to_try):\n", " dist, f = choose_random_function()\n", " constant_minus_blanaced_count = 0\n", " for _ in range(repetitions_of_randomized_alg):\n", " decision = randomized_alg(f, samples_size_per_function)\n", " constant_minus_blanaced_count += 1 if decision == \"constant\" else -1\n", " final_decision = \"constant\" if constant_minus_blanaced_count > 0 else \"balanced\"\n", " res=pd.concat([res, pd.DataFrame({\n", " \"Distribution\": [dist],\n", " \"Decision\":[final_decision],\n", " \"Count\": [1]\n", " })], ignore_index=True)\n", "confusion = res.pivot_table(index=\"Distribution\",\n", " columns=\"Decision\",\n", " values=\"Count\",\n", " aggfunc=\"sum\")\n", "# Translate the counts into percentage\n", "confusion.div(confusion.sum(axis=1), axis=0).apply(lambda x: round(x, 4) * 100)" ] }, { "cell_type": "markdown", "metadata": { "id": "Tda2vy2pb1aU" }, "source": [ "If you try the algorithm with more repetitions, you will observe the error rate decreases rapidly. You can also try different values of $K, N, $ and/or repetitions to see how the confusion matrix changes according.\n", "\n", "After you understand the concept of BPP, it is easy to understand [bounded-error quantum polynomial time (BQP)](https://en.wikipedia.org/wiki/BQP) now. BQP is the class of decision problems solvable by a quantum computer in polynomial time, with an error probability of at most 1/3 for all instances. It is the quantum analogue to the complexity class BPP. Actually, with a quantum computer, the previous problem can be solved using the[Deutsch–Jozsa algorithm](https://en.wikipedia.org/wiki/Deutsch%E2%80%93Jozsa_algorithm). This algorithm utilizes a single query and is guaranteed to be correct always. The Fourier Checking problem that will be introduced later belongs to BQP as well." ] }, { "cell_type": "markdown", "metadata": { "id": "spyqzGyf5kGW" }, "source": [ "## Fourier Transform over $\\mathbb{Z}^n_2$\n", "In this colab, we are interested in the boolean function of the form $f : \\{0, 1\\}^n \\rightarrow\\{-1, 1\\}$. In this case, the Fourier transform of $f$ over $\\mathbb{Z}^n_2$ is defined as\n", "$$\n", " \\hat{f}(y) := \\frac{1}{\\sqrt{N}} \\sum_{x\\in\\{0,1\\}^n} (-1)^{x \\cdot y} f\n", " (x).\n", "$$\n", "where $x \\cdot y$ means the bit-wise inner product between $x$ and $y$. Note this is not the standard discrete Fourier transform definition over $\\mathbb{Z}_N$. According to the Parseval's identity, we have\n", "\n", "$$\n", " \\sum_{x\\in\\{0,1\\}^n} f(x)^2 = \\sum_{y\\in\\{0,1\\}^n} \\hat{f}(y)^2 = N .\n", "$$" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:05.083153Z", "iopub.status.busy": "2024-08-16T10:55:05.082599Z", "iopub.status.idle": "2024-08-16T10:55:05.088085Z", "shell.execute_reply": "2024-08-16T10:55:05.087417Z" }, "id": "ucEcJmSQ26vg" }, "outputs": [], "source": [ "def bitwise_dot(x: int, y: int) -> int:\n", " \"\"\"Compute the dot product of two integers bitwise.\"\"\"\n", " i = x & y\n", "\n", " n = bin(i).count(\"1\")\n", " return int(n % 2)\n", "\n", "\n", "def fourier_transform_over_z2(v: np.ndarray) -> np.ndarray:\n", " \"\"\"Fourier transform function over z_2^n group.\n", "\n", " Args:\n", " v: an array with 2**n elements.\n", "\n", " Returns:\n", " vs: a numpy array with same length as input.\n", " \"\"\"\n", " N = len(v)\n", " assert bin(N).count(\"1\") == 1, \"v must be a 2**n long vector\"\n", " v_hat = np.array([0.0] * N)\n", " for y in range(N):\n", " for x in range(N):\n", " v_hat[y] += ((-1)**bitwise_dot(x, y)) * v[x]\n", " return v_hat / np.sqrt(N)" ] }, { "cell_type": "markdown", "metadata": { "id": "fqXHBoEm7ebP" }, "source": [ "Let's have some examples in $\\mathbb{Z}^2_2$. You should verify that both functions have same energy 4(as defined by Parseval's identity above).\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:05.091593Z", "iopub.status.busy": "2024-08-16T10:55:05.090934Z", "iopub.status.idle": "2024-08-16T10:55:05.096545Z", "shell.execute_reply": "2024-08-16T10:55:05.095849Z" }, "id": "AueS6I2f4hAx" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "f: [1, -1, 1, -1] f_hat: [0.0, 2.0, 0.0, 0.0]\n", "f: [1, 1, 1, -1] f_hat: [1.0, 1.0, 1.0, -1.0]\n", "f: [1, -1, -1, 1] f_hat: [0.0, 0.0, 0.0, 2.0]\n" ] } ], "source": [ "f = np.array([1, -1, 1, -1])\n", "f_hat = fourier_transform_over_z2(f)\n", "print(f\"f: {list(f)} f_hat: {list(f_hat)}\")\n", "\n", "f = np.array([1, 1, 1, -1])\n", "f_hat = fourier_transform_over_z2(f)\n", "print(f\"f: {list(f)} f_hat: {list(f_hat)}\")\n", "\n", "f = np.array([1, -1, -1, 1])\n", "f_hat = fourier_transform_over_z2(f)\n", "print(f\"f: {list(f)} f_hat: {list(f_hat)}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "02GAaXsAsYOW" }, "source": [ "## Forrelation\n", "\n", "The concept of *forrelation* is the key concept in the Fourier checking problem, which is a combination of the words \"Fourier Transform\" and \"Correlation\".\n", "Recall the classical correlation between two vectors $u$ and $v$ is defined as\n", "$$\n", " {\\rm correlation}(u,v) = \\frac{ \\langle u, v \\rangle }{\\|u\\| \\|v\\|}.\n", "$$\n", "Then, the forrelation between two vectors $u$ and $v$ is just the correlation between $u$ and the Fourier trasformed of $v$ -- denoted as $\\widehat{v}$:\n", "\\begin{align}\n", " {\\rm forrelation}(u, v) =& \\frac{\\langle u, \\widehat{v} \\rangle }{\\|u\\| \\|\\widehat{v}\\|},\\\\\n", " =& \\frac{ \\langle u, \\widehat{v} \\rangle }{\\|u\\| \\|v\\|}.\n", "\\end{align}\n", "where the second equality is due to the Parseval's identity.\n", "Since in this tutorial we are interesed in Boolean function, we replace the arbitrary vector $u$ and $v$ by the output of Boolean function $f$ and $g$. Now we can further simplify the above definition:\n", "\n", "$$\n", "\\begin{align}\n", " {\\rm forrelation}(f, g) =& \\frac{\\langle f, \\widehat{g} \\rangle }{\\|f\\| \\|g\\|}\\\\\n", " =& \\frac{1}{N} \\langle f, \\widehat{g}\\rangle \\\\\n", " =& \\frac{1}{N} \\sum_{x \\in \\{0,1\\}^n}f(x)\\widehat{g}(x)\\\\\n", " =& \\frac{1}{N^{3/2}} \\sum_{x, y \\in \\{0,1\\}^n}f(x)(-1)^{x \\cdot y}g(y)\n", "\\end{align}\n", "$$" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:05.099844Z", "iopub.status.busy": "2024-08-16T10:55:05.099313Z", "iopub.status.idle": "2024-08-16T10:55:05.103771Z", "shell.execute_reply": "2024-08-16T10:55:05.103112Z" }, "id": "9r_wFSV6BT3s" }, "outputs": [], "source": [ "def get_correlation(f: np.ndarray, g: np.ndarray) -> np.ndarray:\n", " \"\"\"Returns the classical correlation between two 1-d numpy arrays.\"\"\"\n", " return f.dot(g) / np.linalg.norm(f) / np.linalg.norm(g)\n", "\n", "\n", "def get_forrelation(f: np.ndarray, g: np.ndarray) -> np.ndarray:\n", " \"\"\"Returns the forrelation over Z^2 between two 1-d numpy arrays.\"\"\"\n", " g_hat = fourier_transform_over_z2(g)\n", " return f.dot(g_hat) / np.linalg.norm(f) / np.linalg.norm(g)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:05.106860Z", "iopub.status.busy": "2024-08-16T10:55:05.106353Z", "iopub.status.idle": "2024-08-16T10:55:05.112539Z", "shell.execute_reply": "2024-08-16T10:55:05.111812Z" }, "id": "evFK1aCTBm1E" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Correlation: 1.0 Forrelation: -0.5\n", "Correlation: -1.0 Forrelation: -1.0\n", "Correlation: 0.0 Forrelation: 0.5\n" ] } ], "source": [ "# let's see some examples to gain some insights of forrelation\n", "f = np.array([1, -1, 1, -1]) \n", "g = np.array([1, -1, 1, -1])\n", "print(f\"Correlation: {get_correlation(f,g)} Forrelation: {get_forrelation(f,g)}\")\n", "\n", "f = np.array([1, 1, 1, -1])\n", "g = np.array([-1, -1, -1, 1])\n", "print(f\"Correlation: {get_correlation(f,g)} Forrelation: {get_forrelation(f,g)}\")\n", "\n", "f = np.array([1, -1, -1, 1])\n", "g = np.array([1, 1, 1, 1])\n", "print(f\"Correlation: {get_correlation(f,g)} Forrelation: {get_forrelation(f,g)}\")" ] }, { "cell_type": "markdown", "metadata": { "id": "ozbeF_nZiEib" }, "source": [ "# Fourier Checking Problem\n", "\n", "Now we are prepared to discuss the *Fourier Checking* problem. Here we are given oracle access to two Boolean functions $f,g : \\{0, 1\\}^n \\rightarrow\\{-1, 1\\}$. We are promised that one of the following two cases is true:\n", "\n", "- $\\langle f, g \\rangle$ was drawn from the uniform distribution $\\mathcal{U}$.\n", "- $\\langle f, g \\rangle$ was drawn from the forrelated distribution $\\mathcal{F}$ (Will be explained in more details later).\n", "\n", "The problem is a decision problem that accepts the $\\langle f, g \\rangle$ if it was drawn from $\\mathcal{F}$ and rejects $\\langle f, g \\rangle$ if it was drawn from $\\mathcal{U}$.\n", "\n", "*Note: Since $\\mathcal{F}$ and $\\mathcal{U}$ overlap slightly, we can only hope to succeed with overwhelming probability over the choice of $\\langle f, g \\rangle$ , not for every $\\langle f, g \\rangle$ pair.*\n" ] }, { "cell_type": "markdown", "metadata": { "id": "hQMu28BGwZYS" }, "source": [ "## Generate functions $f$ and $g$ from distribution $\\mathcal U$ and $\\mathcal F$\n", "The forrelated distribution $\\mathcal{F}$ is generated as followings.\n", "First\n", "choose a random real vector $v=(v_x)_{x\\in\\{0, 1\\}^n} \\in \\mathbb{R}^N$, by drawing each entry independently from Gaussian distribution with zero-mean and variance 1. Then set $f(x) := {\\rm sgn}(v_x)$ and $g(x) := {\\rm sgn}(\\widehat{v}_x)$, where $\\widehat{v}_x$ the Fourier Transform of $v$ is\n", "$$\n", " \\widehat{v}_y := \\frac{1}{\\sqrt{N}} \\sum_{x\\in\\{0,1\\}^n} (-1)^{x\\cdot y}v_x,\n", "$$\n", "and \n", "$$\n", " {\\rm sgn}(\\alpha) := \\left\\{\n", " \\begin{aligned}\n", " 1 \\;\\;\\; &{\\rm if}\\; \\alpha \\geq 0 \\\\\n", " -1 \\;\\;\\;&{\\rm if}\\; \\alpha < 0\n", " \\end{aligned}\\right.\n", "$$\n", "Notice, $f$ and $g$ *individually* are still uniformly random, but they are no longer independent. Now $f$ is forrelated with $g$.\n", "For simplicity, we only consider the *PROMISE FOURIER CHECKING* problem. Under this situation, we are promised that the quatity:\n", "\n", "\\begin{align}\n", " p(f,g) := \\left[{\\rm forrelation}(f, g)\\right]^2 = \\frac{1}{N^3} \\left(\\sum_{x, y \\in \\{0,1\\}^n}f(x)(-1)^{x \\cdot y}g(y)\\right)^2\n", "\\end{align}\n", "\n", "is either at least 0.05 or at most 0.01." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:05.116026Z", "iopub.status.busy": "2024-08-16T10:55:05.115465Z", "iopub.status.idle": "2024-08-16T10:55:05.124338Z", "shell.execute_reply": "2024-08-16T10:55:05.123638Z" }, "id": "Ow6khbkKebag" }, "outputs": [], "source": [ "def draw_two_distribution_from_f_set(N:int)-> Tuple[np.ndarray, np.ndarray, float, float]:\n", " \"\"\"Samples two distributions from the 'F' set above.\n", "\n", " Uses a while loop to guarantee a forrelated pair \"as promised\".\n", "\n", " Returns:\n", " A tuple that contains the two distributions, and the correlation/forrelation.\n", " \"\"\"\n", " sgn = lambda x: 1 if x >= 0 else -1\n", " forrelation = 0.2\n", " while (abs(forrelation)**2 < 0.05) and (abs(forrelation)**2 > 0.01):\n", " vs = np.array([np.random.normal() for _ in range(N)])\n", " vs_hat = fourier_transform_over_z2(vs)\n", " fs = np.array([sgn(v) for v in vs])\n", " gs = np.array([sgn(v_hat) for v_hat in vs_hat])\n", " forrelation = get_forrelation(fs, gs)\n", " correlation = get_correlation(fs, gs)\n", " return fs, gs, forrelation, correlation\n", "\n", "\n", "def draw_two_distribution_from_u_set(N:int)-> Tuple[np.ndarray, np.ndarray, float, float]:\n", " \"\"\"Samples two distributions from the 'U' set above.\n", "\n", " Uses a while loop to guarantee a forrelated pair \"as promised\".\n", " \n", " Returns:\n", " A tuple that contains the two distributions, and the correlation/forrelation.\n", " \"\"\"\n", " sgn = lambda x: 1 if x >= 0 else -1\n", " forrelation = 0.2\n", " while (abs(forrelation)**2 < 0.05) and (abs(forrelation)**2 > 0.01):\n", " vs = np.array([np.random.normal() for _ in range(N)])\n", " fs = np.array([sgn(v) for v in vs])\n", " us = np.array([np.random.normal() for _ in range(N)])\n", " gs = np.array([sgn(u) for u in us])\n", " forrelation = get_forrelation(fs, gs)\n", " correlation = get_correlation(fs, gs)\n", " return fs, gs, forrelation, correlation" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:05.127547Z", "iopub.status.busy": "2024-08-16T10:55:05.126965Z", "iopub.status.idle": "2024-08-16T10:55:05.585249Z", "shell.execute_reply": "2024-08-16T10:55:05.584457Z" }, "id": "bVFeIs6-RrfP" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Correlation and forrelation from F set\n", "fs: [1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, 1]\n", "gs: [-1, 1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1]\n", "Correlation: 0.1875 Forrelation: 0.703125\n", "\n", "Correlation and forrelation from U set\n", "fs: [-1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1]\n", "gs: [1, 1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1]\n", "Correlation: 0.0 Forrelation: -0.015625\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAABNIAAAHDCAYAAADhvTdKAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB8CklEQVR4nO3deXxU1f3/8fckkBUSQJaArK5IFVAoiIJY4SuIP5W6orYsVawKtYgrtoKgglsVtVRqFcVWqnXtoqIUxaUiKJZWRakLigoJKpJAIgGS+/tjhsHI4sA9k/vJyev5eOThncnNmc/5nM85MxznzsSCIAgEAAAAAAAAYJcyog4AAAAAAAAAqAvYSAMAAAAAAABSwEYaAAAAAAAAkAI20gAAAAAAAIAUsJEGAAAAAAAApICNNAAAAAAAACAFbKQBAAAAAAAAKWAjDQAAAAAAAEgBG2kAAAAAAABACthIAwAA9UIsFtM111yTvH3//fcrFovp448/Tvtjjxw5Uh07dkze/vjjjxWLxXTLLbek/bEl6ZprrlEsFquVx9oT77//vo499lgVFhYqFovpySefjDokAACAHWIjDQAA7JFYLJbSz4IFC6IO1ZmKigpdc801JvtkObbvM2LECL311lu6/vrr9cc//lE9e/aMOqSdWrBgwU5rfdiwYbUWx9NPP11jYxgAANSOBlEHAAAA6qY//vGPNW4/8MADmjdv3nb3H3TQQbUZVsp++tOfatiwYcrOzk75byoqKjR58mRJ0tFHH53y3/3hD39QdXX17oa4W3YV269//WtdeeWVaX38PfXNN99o4cKF+tWvfqWxY8dGHU7KLrroIv3whz+scd+333WYbk8//bRmzJjBZhoAALWMjTQAALBHfvKTn9S4/dprr2nevHnb3W9VZmamMjMz0/oY5eXlys/PV8OGDdP6ON+nQYMGatDA5su+L774QpLUpEmT7z13az4t6Nevn0499dSowwAAALWMSzsBAEBanHzyyTrssMNq3HfCCScoFovpb3/7W/K+RYsWKRaL6Zlnnkne99FHH+m0005Ts2bNlJeXp8MPP1xPPfVUSo9bWVmpiy++WC1atFDjxo114okn6rPPPtvuvB19Rtobb7yhQYMGqXnz5srNzVWnTp30s5/9TFL8c81atGghSZo8eXLycr6t7wgaOXKkGjVqpA8//FBDhgxR48aNdfbZZyd/t7N3K912223q0KGDcnNz1b9/f7399ts1fn/00Ufv8N1v327z+2Lb0WekbdmyRddee6323XdfZWdnq2PHjrrqqqtUWVlZ47yOHTvq//2//6dXXnlFvXr1Uk5OjvbZZx898MADNc7bvHmzJk+erP333185OTnaa6+91LdvX82bN2+H/d4aV4cOHSRJl112mWKxWLJPW2NetmyZzjrrLDVt2lR9+/bdo9gXLFignj17Kjc3V4ccckjy8tfHH39chxxyiHJyctSjRw/9+9//3mmsLhQXF2vUqFFq27atsrOz1bp1a5100knbfU7fM888o379+ik/P1+NGzfW8ccfr3feeSf5+5EjR2rGjBmSal5iDQAA0s/m/5oEAAB1Xr9+/fTXv/5VZWVlKigoUBAE+te//qWMjAy9/PLLOvHEEyVJL7/8sjIyMnTkkUdKkkpKSnTEEUeooqJCF110kfbaay/Nnj1bJ554oh599FH9+Mc/3uXjnnvuufrTn/6ks846S0cccYSef/55HX/88d8b75o1a3TssceqRYsWuvLKK9WkSRN9/PHHevzxxyVJLVq00F133aULLrhAP/7xj3XyySdLkrp27ZpsY8uWLRo0aJD69u2rW265RXl5ebt8zAceeEDr16/XmDFjtHHjRt1+++065phj9NZbb6lVq1bfG/NWqcT2Xeeee65mz56tU089VZdccokWLVqkadOm6d1339UTTzxR49wPPvhAp556qs455xyNGDFCs2bN0siRI9WjRw/94Ac/kBTf+Jo2bZrOPfdc9erVS2VlZXrjjTf05ptv6v/+7/92GMPJJ5+sJk2a6OKLL9aZZ56pIUOGqFGjRjXOOe2007T//vtr6tSpCoJgj2I/66yz9POf/1w/+clPdMstt+iEE07QzJkzddVVV+nCCy+UJE2bNk2nn366li9froyM7/9/zevXr9eXX35Z475mzZrt8m9POeUUvfPOO/rFL36hjh07as2aNZo3b55WrlyZ3ED84x//qBEjRmjQoEG68cYbVVFRobvuukt9+/bVv//9b3Xs2FE///nPtWrVqh1eSg0AANIsAAAAcGDMmDHBt19avP7664Gk4Omnnw6CIAj++9//BpKC0047Lejdu3fyvBNPPDE49NBDk7fHjRsXSApefvnl5H3r168POnXqFHTs2DGoqqraaQxLly4NJAUXXnhhjfvPOuusQFIwadKk5H333XdfIClYsWJFEARB8MQTTwSSgtdff32n7X/xxRfbtbPViBEjAknBlVdeucPfdejQIXl7xYoVgaQgNzc3+Oyzz5L3L1q0KJAUXHzxxcn7+vfvH/Tv3/9729xVbJMmTaoxNlvzdO6559Y479JLLw0kBc8//3zyvg4dOgSSgpdeeil535o1a4Ls7OzgkksuSd7XrVu34Pjjj9/usb/P1lzcfPPNO4z5zDPPrHH/nsT+6quvJu979tlnk7n/5JNPkvf//ve/DyQFL7zwwi7jfeGFFwJJO/zZWks78vXXX++wn9+2fv36oEmTJsHo0aNr3F9cXBwUFhbWuP+78w0AANQOLu0EAABpceihh6pRo0Z66aWXJMXfeda2bVsNHz5cb775pioqKhQEgV555RX169cv+XdPP/20evXqlbyMT5IaNWqk8847Tx9//LGWLVu208d8+umnJcU/CP7bxo0b973xbv2Mrn/84x/avHlzqt3czgUXXJDyuUOHDtXee++dvN2rVy/17t072Y902dr++PHja9x/ySWXSNJ2l9F26dKlxhi1aNFCBx54oD766KPkfU2aNNE777yj999/32ms559/fujY+/Tpk7zdu3dvSdIxxxyj9u3bb3f/t/u0KxMnTtS8efNq/BQVFe30/NzcXGVlZWnBggX6+uuvd3jOvHnztG7dOp155pn68ssvkz+ZmZnq3bu3XnjhhZRiAwAA6cNGGgAASIvMzEz16dNHL7/8sqT4Rlq/fv3Ut29fVVVV6bXXXtOyZcu0du3aGps0n3zyiQ488MDt2tv67Z+ffPLJTh/zk08+UUZGhvbdd98a9++ove/q37+/TjnlFE2ePFnNmzfXSSedpPvuu2+7z93alQYNGqht27Ypn7///vtvd98BBxyw3WdmubY1T/vtt1+N+4uKitSkSZPtcvztDaetmjZtWmNDaMqUKVq3bp0OOOAAHXLIIbrsssv03//+N3SsnTp1chp7YWGhJKldu3Y7vH9nm1zfdcghh2jgwIE1fnJycnZ6fnZ2tm688UY988wzatWqlY466ijddNNNKi4uTp6zdRPymGOOUYsWLWr8PPfcc1qzZk1KsQEAgPRhIw0AAKRN37599frrr2vjxo3JjbQmTZro4IMP1ssvv5zcZPv2RlpUYrGYHn30US1cuFBjx47V559/rp/97Gfq0aOHNmzYkFIb2dnZKX2+1u7GtSNVVVVpa/u7dvbtpkHiM8sk6aijjtKHH36oWbNm6eCDD9Y999yjww47TPfcc0+oGHNzc3d4f9jYU+mTa+PGjdP//vc/TZs2TTk5Obr66qt10EEHJb/koLq6WlL8c9K++263efPm6a9//WvaYgMAAKlhIw0AAKRNv379tGnTJv35z3/W559/ntwwO+qoo5IbaQcccECND9bv0KGDli9fvl1b7733XvL3O9OhQwdVV1frww8/rHH/jtrbmcMPP1zXX3+93njjDT344IN655139NBDD0lKffMmVTu6DPJ///tfjW/4bNq0qdatW7fded9959XuxLY1T999/JKSEq1bt26XOd6VZs2aadSoUfrzn/+sTz/9VF27dk1+c6gr6Yq9tuy777665JJL9Nxzz+ntt9/Wpk2b9Jvf/Cb5O0lq2bLldu92GzhwYI1vb+VbOgEAiAYbaQAAIG169+6thg0b6sYbb1SzZs2S3/DYr18/vfbaa3rxxRe3ezfakCFDtHjxYi1cuDB5X3l5ue6++2517NhRXbp02enjHXfccZKkO+64o8b906dP/95Yv/766+3ejdS9e3dJSl7eufVbOHe0sbUnnnzySX3++efJ24sXL9aiRYuS/ZDimyvvvfeevvjii+R9//nPf/Svf/2rRlu7E9uQIUMkbZ+XW2+9VZJS+pbT7/rqq69q3G7UqJH222+/3bo0NhXpiL02VFRUaOPGjTXu23fffdW4ceNkjgYNGqSCggJNnTp1h5/T9+0ayM/Pl+SuFgEAQGoaRB0AAADwV15ennr06KHXXntNJ5xwQvJdNEcddZTKy8tVXl6+3UbalVdeqT//+c867rjjdNFFF6lZs2aaPXu2VqxYoccee2yXl052795dZ555pn73u9+ptLRURxxxhObPn68PPvjge2OdPXu2fve73+nHP/6x9t13X61fv15/+MMfVFBQkNy8yc3NVZcuXfTwww/rgAMOULNmzXTwwQfr4IMP3qP87Lfffurbt68uuOACVVZWavr06dprr710+eWXJ8/52c9+pltvvVWDBg3SOeecozVr1mjmzJn6wQ9+oLKysuR5uxNbt27dNGLECN19991at26d+vfvr8WLF2v27NkaOnSofvSjH+12X7p06aKjjz5aPXr0ULNmzfTGG2/o0Ucf1dixY/coNzuTjthrw//+9z8NGDBAp59+urp06aIGDRroiSeeUElJiYYNGyZJKigo0F133aWf/vSnOuywwzRs2DC1aNFCK1eu1FNPPaUjjzxSv/3tbyVJPXr0kBT/Yo1BgwYpMzMz2Q4AAEgfNtIAAEBabX332be/hbOoqEj77befPvjgg+020lq1aqVXX31VV1xxhe68805t3LhRXbt21d///veU3m00a9YstWjRQg8++KCefPJJHXPMMXrqqae2+3D579q6IfPQQw+ppKREhYWF6tWrlx588MEaH3h/zz336Be/+IUuvvhibdq0SZMmTdrjjbThw4crIyND06dP15o1a9SrVy/99re/VevWrZPnHHTQQXrggQc0ceJEjR8/Xl26dNEf//hHzZkzRwsWLKjR3u7Eds8992ifffbR/fffryeeeEJFRUWaMGGCJk2atEd9ueiii/S3v/1Nzz33nCorK9WhQwddd911uuyyy/aovV1xHXttaNeunc4880zNnz9ff/zjH9WgQQN17txZf/nLX3TKKackzzvrrLPUpk0b3XDDDbr55ptVWVmpvffeW/369dOoUaOS55188sn6xS9+oYceekh/+tOfFAQBG2kAANSCWJDOT1QFAAAAAAAAPMFnpAEAAAAAAAApYCMNAAAAAAAASAEbaQAAAAAAAEAK2EgDAAAAAAAAUsBGGgAAAAAAAJACNtIAAAAAAACAFDSIOoAoVFdXa9WqVWrcuLFisVjU4QAAAAAAACBCQRBo/fr1atOmjTIydv6+s3q5kbZq1Sq1a9cu6jAAAAAAAABgyKeffqq2bdvu9Pf1ciOtcePGkuLJKSgoiDgaAAAAAAAARKmsrEzt2rVL7hntTL3cSNt6OWdBQQEbaQAAAAAAAJCk7/0IML5sAAAAAAAAAEgBG2kAAAAAAABACthIAwAAAAAAAFLARhoAAAAAAACQAjbSAAAAAAAAgBSwkQYAAAAAAACkgI00AAAAAAAAIAVspAEAAAAAAAApYCMNAAAAAAAASAEbaQAAAAAAAEAKGqSz8Zdeekk333yzlixZotWrV+uJJ57Q0KFDd/k3CxYs0Pjx4/XOO++oXbt2+vWvf62RI0fWOGfGjBm6+eabVVxcrG7duunOO+9Ur1690tcR46qqAy1esVZr1m9Uy8Y56tWpmTIzYrvXxuYt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p52mli1b6tBDD9Uf/vCH5O/591HdxkZaHfbll1+qqqpKrVq1qnF/q1atVFxcHFFUwPa21iO1Cguqq6s1btw4HXnkkTr44IMlxWs0KytLTZo0qXEuNYra8NZbb6lRo0bKzs7W+eefryeeeEJdunShLmHCQw89pDfffFPTpk3b7nfUKKLUu3dv3X///Zo7d67uuusurVixQv369dP69eupTUTuo48+0l133aX9999fzz77rC644AJddNFFmj17tiT+fVTXNYg6AAAAatOYMWP09ttv1/gcFSBKBx54oJYuXarS0lI9+uijGjFihF588cWowwL06aef6pe//KXmzZunnJycqMMBajjuuOOSx127dlXv3r3VoUMH/eUvf1Fubm6EkQHx/3Hbs2dPTZ06VZJ06KGH6u2339bMmTM1YsSIiKNDWLwjrQ5r3ry5MjMzt/v2mZKSEhUVFUUUFbC9rfVIrSJqY8eO1T/+8Q+98MILatu2bfL+oqIibdq0SevWratxPjWK2pCVlaX99ttPPXr00LRp09StWzfdfvvt1CUit2TJEq1Zs0aHHXaYGjRooAYNGujFF1/UHXfcoQYNGqhVq1bUKMxo0qSJDjjgAH3wwQesn4hc69at1aVLlxr3HXTQQcnLj/n3Ud3GRlodlpWVpR49emj+/PnJ+6qrqzV//nz16dMnwsiAmjp16qSioqIatVpWVqZFixZRq6gVQRBo7NixeuKJJ/T888+rU6dONX7fo0cPNWzYsEaNLl++XCtXrqRGUeuqq6tVWVlJXSJyAwYM0FtvvaWlS5cmf3r27Kmzzz47eUyNwooNGzboww8/VOvWrVk/EbkjjzxSy5cvr3Hf//73P3Xo0EES/z6q67i0s44bP368RowYoZ49e6pXr16aPn26ysvLNWrUqKhDQz2zYcMGffDBB8nbK1as0NKlS9WsWTO1b99e48aN03XXXaf9999fnTp10tVXX602bdpo6NCh0QWNemPMmDGaM2eO/vrXv6px48bJz54oLCxUbm6uCgsLdc4552j8+PFq1qyZCgoK9Itf/EJ9+vTR4YcfHnH08NmECRN03HHHqX379lq/fr3mzJmjBQsW6Nlnn6UuEbnGjRsnP0tyq/z8fO21117J+6lRROXSSy/VCSecoA4dOmjVqlWaNGmSMjMzdeaZZ7J+InIXX3yxjjjiCE2dOlWnn366Fi9erLvvvlt33323JCkWi/Hvo7os6q8NRXh33nln0L59+yArKyvo1atX8Nprr0UdEuqhF154IZC03c+IESOCIIh/xfPVV18dtGrVKsjOzg4GDBgQLF++PNqgUW/sqDYlBffdd1/ynG+++Sa48MILg6ZNmwZ5eXnBj3/842D16tXRBY164Wc/+1nQoUOHICsrK2jRokUwYMCA4Lnnnkv+nrqENf379w9++ctfJm9To4jKGWecEbRu3TrIysoK9t577+CMM84IPvjgg+TvqU1E7e9//3tw8MEHB9nZ2UHnzp2Du+++u8bv+fdR3RULgiCIaA8PAAAAAAAAqDP4jDQAAAAAAAAgBWykAQAAAAAAAClgIw0AAAAAAABIARtpAAAAAAAAQArYSAMAAAAAAABSwEYaAAAAAAAAkAI20gAAAAAAAIAUsJEGAAAAAAAApICNNAAAAAAAACAFbKQBAAAAAAAAKWAjDQAAAAAAAEgBG2kAAAAAAABACv4/G9mfs4ioBY4AAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAABNIAAAHDCAYAAADhvTdKAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB6UklEQVR4nO3deXxU1f3/8fckkBUTdgKCLKIiKqBQEEWxwhcQvra4L1gWFapCLcYVqyC4UJefohalLij2K9W61q0oRXGpCIrSqih1QVGBoCIJJBAgub8/AhNHFgfuGe4nJ6/n45GHd2ZuTj7nfD7nzOU4SywIgkAAAAAAAAAAdiot6gAAAAAAAACAmoCNNAAAAAAAACAJbKQBAAAAAAAASWAjDQAAAAAAAEgCG2kAAAAAAABAEthIAwAAAAAAAJLARhoAAAAAAACQBDbSAAAAAAAAgCSwkQYAAAAAAAAkgY00AADgtVgspmuuuSZ++8EHH1QsFtMXX3yR8r89fPhwtWnTJn77iy++UCwW0y233JLyvy1J11xzjWKx2B75W7vjk08+Ub9+/ZSfn69YLKann3466pAAAAB2io00AACwS2KxWFI/c+fOjTpUZ8rKynTNNdeY7JPl2H7OsGHD9P777+v666/XX/7yF3Xr1i3qkHZo6wbsO++8s93H//d//zdh03RPuOuuu/Tggw/u0b8JAEBtVyfqAAAAQM3yl7/8JeH2Qw89pNmzZ29z/4EHHrgnw0rab37zG51++unKzMxM+nfKyso0ceJESdIxxxyT9O/de++9qqys3NUQd8nOYrvqqqt0xRVXpPTv767169dr3rx5+sMf/qAxY8ZEHU6NdNddd6lx48YaPnx41KEAAFBrsJEGAAB2yVlnnZVw+6233tLs2bO3ud+q9PR0paenp/RvlJaWKjc3V3Xr1k3p3/k5derUUZ06Ni/3vv32W0lS/fr1f/bcreMJAAAQNd7aCQAAnDrxxBN12GGHJdx3/PHHKxaL6ZlnnonfN3/+fMViMf3jH/+I3/f555/rlFNOUcOGDZWTk6PDDz9czz//fFJ/t7y8XBdddJGaNGmivfbaS7/61a/09ddfb3Pe9j4j7Z133lH//v3VuHFjZWdnq23btjr77LMlVX2uWZMmTSRJEydOjL91devnrg0fPlz16tXTZ599poEDB2qvvfbSkCFD4o/t6O1+t912m1q3bq3s7Gz17t1bH3zwQcLjxxxzzHZf/fbjNn8utu19RtrmzZt17bXXat9991VmZqbatGmjK6+8UuXl5QnntWnTRv/7v/+rN954Q927d1dWVpbatWunhx56KOG8TZs2aeLEidpvv/2UlZWlRo0aqVevXpo9e/Z2+701rtatW0uSLr30UsVisXiftsa8ePFinXnmmWrQoIF69eq1W7HPnTtX3bp1U3Z2tg455JD421+ffPJJHXLIIcrKylLXrl313nvv7TBW13ZWa1tVVlZqypQpOuigg5SVlaVmzZrpt7/9rX744YeEPn744Yd69dVX43nflVdLAgCA3WPzf1ECAIAa66ijjtLf//53lZSUKC8vT0EQ6F//+pfS0tL0+uuv61e/+pUk6fXXX1daWpqOPPJISVJRUZGOOOIIlZWV6cILL1SjRo00Y8YM/epXv9Ljjz+uE044Yad/99xzz9X//d//6cwzz9QRRxyhl19+WYMGDfrZeFetWqV+/fqpSZMmuuKKK1S/fn198cUXevLJJyVJTZo00d13363zzz9fJ5xwgk488URJUqdOneJtbN68Wf3791evXr10yy23KCcnZ6d/86GHHtLatWs1evRobdiwQbfffruOPfZYvf/++2rWrNnPxrxVMrH91LnnnqsZM2bo5JNP1sUXX6z58+dr8uTJ+uijj/TUU08lnPvpp5/q5JNP1jnnnKNhw4Zp+vTpGj58uLp27aqDDjpIUtXG1+TJk3Xuueeqe/fuKikp0TvvvKN3331X//M//7PdGE488UTVr19fF110kc444wwNHDhQ9erVSzjnlFNO0X777acbbrhBQRDsVuxnnnmmfvvb3+qss87SLbfcouOPP17Tpk3TlVdeqQsuuECSNHnyZJ166qlasmSJ0tJS+/+Yf67Wtvrtb3+rBx98UCNGjNCFF16opUuX6k9/+pPee+89/etf/1LdunU1ZcoU/e53v1O9evX0hz/8QZJ2qXYAAMBuCgAAAEIYPXp08ONLirfffjuQFLzwwgtBEATBf/7zn0BScMoppwQ9evSIn/erX/0qOPTQQ+O3x44dG0gKXn/99fh9a9euDdq2bRu0adMmqKio2GEMixYtCiQFF1xwQcL9Z555ZiApmDBhQvy+Bx54IJAULF26NAiCIHjqqacCScHbb7+9w/a//fbbbdrZatiwYYGk4IorrtjuY61bt47fXrp0aSApyM7ODr7++uv4/fPnzw8kBRdddFH8vt69ewe9e/f+2TZ3FtuECRMScrN1nM4999yE8y655JJAUvDyyy/H72vdunUgKXjttdfi961atSrIzMwMLr744vh9nTt3DgYNGrTN3/45W8fi5ptv3m7MZ5xxRsL9uxP7m2++Gb/vxRdfjI/9l19+Gb//z3/+cyApeOWVV3Ya79a62VGdDBo0KCEv25NMrb3++uuBpODhhx9OuH/WrFnb3H/QQQdtt0YAAEDq8NZOAADg1KGHHqp69erptddek1T1yrOWLVtq6NChevfdd1VWVqYgCPTGG2/oqKOOiv/eCy+8oO7du8ffxidJ9erV06hRo/TFF19o8eLFO/ybL7zwgiTpwgsvTLh/7NixPxvv1s/oeu6557Rp06Zku7mN888/P+lzBw8erL333jt+u3v37urRo0e8H6mytf3CwsKE+y+++GJJ2uZttB07dkzIUZMmTXTAAQfo888/j99Xv359ffjhh/rkk0+cxnreeeeFjr1nz57x2z169JAkHXvssdpnn322uf/HfUqVZGrtscceU35+vv7nf/5H3333Xfyna9euqlevnl555ZWUxwkAAHaMjTQAAOBUenq6evbsqddff11S1UbaUUcdpV69eqmiokJvvfWWFi9erNWrVyds0nz55Zc64IADtmlv67d/fvnllzv8m19++aXS0tK07777Jty/vfZ+qnfv3jrppJM0ceJENW7cWL/+9a/1wAMPbPO5WztTp04dtWzZMunz99tvv23u23///RM+ty0Vto5T+/btE+4vKChQ/fr1txnjH284bdWgQYOEz+qaNGmS1qxZo/3331+HHHKILr30Uv3nP/8JHWvbtm2dxp6fny9JatWq1Xbv/3GfdtdPP4/up5KptU8++UTFxcVq2rSpmjRpkvCzbt06rVq1KnScAABg97GRBgAAnOvVq5fefvttbdiwIb6RVr9+fR188MF6/fXX45tsP95Ii0osFtPjjz+uefPmacyYMfrmm2909tlnq2vXrlq3bl1SbWRmZjr/fK0dbcpUVFSkrO2f2tG3mwZbPrNMko4++mh99tlnmj59ug4++GDdd999Ouyww3TfffeFijE7O3u794eNPZk+bU9WVpYkaf369dt9vKysLH7OjiRTa5WVlWratKlmz5693Z9Jkybt9G8AAIDUYiMNAAA4d9RRR2njxo3661//qm+++Sa+YXb00UfHN9L233//hA9Hb926tZYsWbJNWx9//HH88R1p3bq1Kisr9dlnnyXcv732duTwww/X9ddfr3feeUcPP/ywPvzwQz3yyCOSkt+8Sdb23gb53//+N+EbPhs0aKA1a9Zsc95PX3m1K7FtHaef/v2ioiKtWbNmp2O8Mw0bNtSIESP017/+VV999ZU6deoU/+ZQV1IV+678fWnHNfXf//436Rh2Vmv77ruvvv/+ex155JHq27fvNj+dO3eOt+O6LgEAwM9jIw0AADjXo0cP1a1bVzfeeKMaNmwY/4bHo446Sm+99ZZeffXVbV6NNnDgQC1YsEDz5s2L31daWqp77rlHbdq0UceOHXf494477jhJ0h133JFw/5QpU3421h9++GGbVyN16dJFkuJvudv6LZzb29jaHU8//bS++eab+O0FCxZo/vz58X5IVRsqH3/8sb799tv4ff/+97/1r3/9K6GtXYlt4MCBkrYdl1tvvVWSkvqW05/6/vvvE27Xq1dP7du336W3xiYjFbHviq5du6pp06a67777tunb1nz+OH/bk0ytnXrqqaqoqNC11167ze9v3rw5Ic+5ubnOahIAACSnTtQBAAAA/+Tk5Khr16566623dPzxx8dfOXP00UertLRUpaWl22ykXXHFFfrrX/+q4447ThdeeKEaNmyoGTNmaOnSpXriiSd2+tbJLl266IwzztBdd92l4uJiHXHEEZozZ44+/fTTn411xowZuuuuu3TCCSdo33331dq1a3XvvfcqLy8vvnmTnZ2tjh076tFHH9X++++vhg0b6uCDD9bBBx+8W+PTvn179erVS+eff77Ky8s1ZcoUNWrUSJdddln8nLPPPlu33nqr+vfvr3POOUerVq3StGnTdNBBB6mkpCR+3q7E1rlzZw0bNkz33HOP1qxZo969e2vBggWaMWOGBg8erF/+8pe73JeOHTvqmGOOUdeuXdWwYUO98847evzxxzVmzJjdGpsdSUXsuyIjI0O33HKLhg0bpl/84hc67bTT1KhRI7333nuaPn26OnXqpFGjRu20jWRqrXfv3vrtb3+ryZMna9GiRerXr5/q1q2rTz75RI899phuv/12nXzyyZKqNvfuvvtuXXfddWrfvr2aNm2qY489NqXjAABAbcdG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h79300036frrr9eLL76obt26/ezf+frrr/X999+refPmrkKvWcrKpF/8our47berXqoZRRthlZXppfsuqDq+4n0poxZveFrIhyth++KovkPXlk85scBKXsNyVFsm6tPBXI08H1viiHwskMhCbVlpIywLMViJw8o8Zc2xJ2x9+pQPj663vJhnVvrhS11EKOVv7SwsLNSwYcPUrVs3de/eXVOmTFFpaalGjBghSRo6dKj23ntvTZ48WZJ04403avz48Zo5c6batGmjlStXSpLq1aunevXqad26dZo4caJOOukkFRQU6LPPPtNll12m9u3bq3///qnujk1BIC1eXH0cVRthBYH2/36ZJKksqhissJAPV8L2xVF9h64tn3JigZW8huWotkzUp4O5Gnk+tsQR+VggkYXastJGWBZisBKHlXnKmmNP2Pr0KR8eXW95Mc+s9MOXuohQyjfSTjvtNH377bcaP368Vq5cqS5dumjWrFnxLyBYtmyZ0tKq32F69913a+PGjTr55JMT2pkwYYKuueYapaen6z//+Y9mzJihNWvWqEWLFurXr5+uvfZaZWZmpro7AAAAAAAAqKX2yJcNjBkzZodv5Zw7d27C7S+++GKnbWVnZ+vFF190FBkAAAAAAACQnJR+2QAAAAAAAADgCzbSAAAAAAAAgCSwkQYAAAAAAAAkYY98RhpSLBaTWreuPo6qjbBiMX2d11SS1DCqGKywkA9XwvbFUX2Hri2fcmKBlbyG5ai2TNSng7kaeT62xBH5WCCRhdqy0kZYFmKwEoeVecqaY0/Y+vQpHx5db3kxz6z0w5e6iBAbaT7IyZF+5ksa9kgbYeXkqNf50yVJi3Nyoo0lahby4UrYvjiq79C15VNOLLCS17Ac1ZaJ+nQwVyPPx5Y4Ih8LJLJQW1baCMtCDFbisDJPWXPsCVufPuXDo+stL+aZlX74UhcR4q2dAAAAAAAAQBLYSAMAAAAAAACSwFs7fbB+vXT00VXHr70mZWdH00ZY69fr7zMuqjoet1DK2GvPx2CFhXy4ErYvjuo7dG35lBMLrOQ1LEe1ZaI+HczVyPOxJY7IxwKJLNSWlTbCshCDlTiszFPWHHvC1qdP+fDoesuLeWalH77URYTYSPNBZaX0zjvVx1G1EVZlpTqv/ESSVBZVDFZYyIcrYfviqL5D15ZPObHASl7DclRbJurT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fv36qbS0NH7ORRddpGeffVaPPfaYXn31VS1fvlwnnnhihFGjNmjZsqX++Mc/auHChXrnnXd07LHH6te//rU+/PBDSdQl7Hj77bf15z//WZ06dUq4nxpFlA466CCtWLEi/vPGG2/EH6M2EaUffvhBRx55pOrWrat//OMfWrx4sf7f//t/atCgQfwc/n1UgwWo0bp37x6MHj06fruioiJo0aJFMHny5AijQm0nKXjqqafitysrK4OCgoLg5ptvjt+3Zs2aIDMzM/jrX/8aQYSo7VatWhVICl599dUgCKrqsW7dusFjjz0WP+ejjz4KJAXz5s2LKkzUUg0aNAjuu+8+6hJmrF27Nthvv/2C2bNnB7179w5+//vfB0HA2oloTZgwIejcufN2H6M2EbXLL7886NWr1w4f599HNRuvSKvBNm7cqIULF6pv377x+9LS0tS3b1/NmzcvwsiAREuXLtXKlSsTajU/P189evSgVhGJ4uJiSVLDhg0lSQsXLtSmTZsSarRDhw7aZ599qFHsMRUVFXrkkUdUWlqqnj17UpcwY/To0Ro0aFBCLUqsnYjeJ598ohYtWqhdu3YaMmSIli1bJonaRPSeeeYZdevWTaeccoqaNm2qQw89VPfee2/8cf59VLOxkVaDfffdd6qoqFCzZs0S7m/WrJlWrlwZUVTAtrbWI7UKCyorKzV27FgdeeSROvjggyVV1WhGRobq16+fcC41ij3h/fffV7169ZSZmanzzjtPTz31lDp27EhdwoRHHnlE7777riZPnrzNY9QootSjRw89+OCDmjVrlu6++24tXbpURx11lNauXUttInKff/657r77bu2333568cUXdf755+vCCy/UjBkzJPHvo5quTtQBAACwJ40ePVoffPBBwueoAFE64IADtGjRIhUXF+vxxx/XsGHD9Oqrr0YdFqCvvvpKv//97zV79mxlZWVFHQ6Q4Ljjjosfd+rUST169FDr1q31t7/9TdnZ2RFGBlT9j9tu3brphhtukCQdeuih+uCDDzRt2jQNGzYs4ugQFq9Iq8EaN26s9PT0bb59pqioSAUFBRFFBWxraz1Sq4jamDFj9Nxzz+mVV15Ry5Yt4/cXFBRo48aNWrNmTcL51Cj2hIyMDLVv315du3bV5MmT1blzZ91+++3UJSK3cOFCrVq1Socddpjq1KmjOnXq6NVXX9Udd9yhOnXqqFmzZtQozKhfv772339/ffrpp6yfiFzz5s3VsWPHhPsOPPDA+NuP+fdRzcZGWg2WkZGhrl27as6cOfH7KisrNWfOHPXs2TPCyIBEbdu2VUFBQUKtlpSUaP78+dQq9oggCDRmzBg99dRTevnll9W2bduEx7t27aq6desm1OiSJUu0bNkyahR7XGVlpcrLy6lLRK5Pnz56//33tWjRovhPt27dNGTIkPgxNQor1q1bp88++0zNmzdn/UTkjjzySC1ZsiThvv/+979q3bq1JP59VNPx1s4arrCwUMOGDVO3bt3UvXt3TZkyRaWlpRoxYkTUoaGWWbdunT799NP47aVLl2rRokVq2LCh9tlnH40dO1bXXXed9ttvP7Vt21ZXX321WrRoocGDB0cXNGqN0aNHa+bMmfr73/+uvfbaK/7ZE/n5+crOzlZ+fr7OOeccFRYWqmHDhsrLy9Pvfvc79ezZU4cffnjE0cNn48aN03HHHad99tlHa9eu1cyZMzV37ly9+OKL1CUit9dee8U/S3Kr3NxcNWrUKH4/NYqoXHLJJTr++OPVunVrLV++XBMmTFB6errOOOMM1k9E7qKLLtIRRxyhG264QaeeeqoWLFige+65R/fcc48kKRaL8e+jmizqrw1FeHfeeWewzz77BBkZGUH37t2Dt956K+qQUAu98sorgaRtfoYNGxYEQdVXPF999dVBs2bNgszMzKBPnz7BkiVLog0atcb2alNS8MADD8TPWb9+fXDBBRcEDRo0CHJycoITTjghWLFiRXRBo1Y4++yzg9atWwcZGRlBkyZNgj59+gQvvfRS/HHqEtb07t07+P3vfx+/TY0iKqeddlrQvHnzICMjI9h7772D0047Lfj000/jj1ObiNqzzz4bHHzwwUFmZmbQoUOH4J577kl4nH8f1VyxIAiCiPbwAAAAAAAAgBqDz0gDAAAAAAAAksBGGgAAAAAAAJAENtIAAAAAAACAJLCRBgAAAAAAACSBjTQAAAAAAAAgCWykAQAAAAAAAElgIw0AAAAAAABIAhtpAAAAAAAAQBLYSAMAAAAAAACSwEYaAAAAAAAAkAQ20gAAAAAAAIAksJEGAAAAAAAAJOH/A2kqGBJbSoN9AAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "n = 6\n", "N = 2 ** n\n", "\n", "fs, gs, forrelation, correlation = draw_two_distribution_from_f_set(N)\n", "print('Correlation and forrelation from F set')\n", "print(f\"fs: {list(fs)}\")\n", "print(f\"gs: {list(gs)}\")\n", "print(f'Correlation: {correlation} Forrelation: {forrelation}')\n", "plt.figure(figsize=(15, 5))\n", "plt.stem(fs)\n", "plt.stem(gs, linefmt='--r', markerfmt='ro')\n", "plt.title(f\"Two distributions from F set\")\n", "\n", "print('')\n", "print('Correlation and forrelation from U set')\n", "fs, gs, forrelation, correlation = draw_two_distribution_from_u_set(N)\n", "print(f\"fs: {list(fs)}\")\n", "print(f\"gs: {list(gs)}\")\n", "print(f'Correlation: {correlation} Forrelation: {forrelation}')\n", "\n", "plt.figure(figsize=(15, 5))\n", "plt.stem(fs)\n", "plt.stem(gs, linefmt='--r', markerfmt='ro')\n", "_ = plt.title(f\"Two distributions from U set\")\n" ] }, { "cell_type": "markdown", "metadata": { "id": "TZwIP2_337WH" }, "source": [ "Typically, $\\mathcal{U}$ and $\\mathcal{F}$ is not obviously different from each other even after we plot the whole functions information together. However, it is not hard to show that Fourier Checking is in BQP: basically, one can prepare a uniform superposition over all $x\\in\\{0,1\\}^n$, then query $f$, apply a quantum Fourier transform, query $g$, and\n", "check whether one has recovered something close to the uniform superposition. On the other hand, being forrelated seems like an extremely “global” property of $f$ and $g$: one that would not be apparent from querying any small number of $f$ and $g$ values, regardless of the outcomes of those queries." ] }, { "cell_type": "markdown", "metadata": { "id": "obqAoSrNRFJ9" }, "source": [ "# Quantum Algorithm for Fourier Checking\n", "\n", "Now, we present the quantum algorithm for Fourier Checking, which is quite simple actually.\n", "It can achieve the constant error probability with $O(1)$ query complexity.\n", "\n", "**Algorithm Description:**\n", "\n", "First, we prepare a uniform superposition over all $x \\in \\{0, 1\\}^n$. Then query $f$ in superposition, to create the state\n", "$$\n", " \\frac{1}{\\sqrt{N}} \\sum_{x \\in \\{0, 1\\}^n} f(x) |x\\rangle\n", "$$\n", "Applying Hadmard gates to all $n$ qubits, to create the state\n", "$$\n", " \\frac{1}{N} \\sum_{x,y \\in \\{0, 1\\}^n} f(x) (-1)^{x\\cdot y} |y\\rangle\n", "$$\n", "Then query $g$ in superposition, to create the state\n", "$$\n", " \\frac{1}{N} \\sum_{x,y \\in \\{0, 1\\}^n} f(x) (-1)^{x\\cdot y}g(y) |y\\rangle\n", "$$\n", "Then apply Hadmard gates to all $n$ qubits again, to create the state\n", "$$\n", " \\frac{1}{N^{3/2}} \\sum_{x,y \\in \\{0, 1\\}^n} f(x) (-1)^{x\\cdot y} g(y) (-1)^{y \\cdot z}|z\\rangle\n", "$$\n", "Finally, measure in the computational basis, and \"accept\" if and only if the outcome $|0\\rangle^{\\otimes n}$is observed.\n", "\n", "If needed, repeat the whole algorithm $O(1)$ times to boost the success probability." ] }, { "cell_type": "markdown", "metadata": { "id": "ddJVURrobh8g" }, "source": [ "It is clear that the probability of observation $|0\\rangle^{\\otimes n}$ equals the quantity:\n", "\\begin{align}\n", " p(f,g) := \\frac{1}{N^3} \\left(\\sum_{x, y \\in \\{0,1\\}^n}f(x)(-1)^{x \\cdot y}g(y)\\right)^2\n", "\\end{align}\n", "\n", "It is shown in the [paper](https://arxiv.org/pdf/0910.4698.pdf) that\n", "\n", "$$\n", "\\begin{align}\n", " {\\rm Pr}_{\\langle f, g \\rangle \\sim \\mathcal{U}} [p(f,g) \\geq 0.01] \\leq& \\; \\frac{100}{N} \\\\\n", " {\\rm Pr}_{\\langle f, g \\rangle \\sim \\mathcal{F}} [p(f,g) \\geq 0.05] \\geq&\\;\\frac{1}{50} \\\\\n", "\\end{align}\n", "$$\n", "\n", "This implies that the probability of the forrelation square between two functions drawing from uniform distribution $\\mathcal{U}$ having larger than 0.01 will decaying quickly when we have more number of qubits. Hence, the Promise Fourier Checking problem can be solved through simply accepting when $p(f,g) \\geq 0.05$ and rejecting when $p(f,g) \\leq 0.01$ with constant error probability, using $O(1)$ queries to $f$ and $g$." ] }, { "cell_type": "markdown", "metadata": { "id": "FDVxr7UKze2X" }, "source": [ "## Implementation in Cirq\n", "\n", "Above algorithm is simple and straightforward to implement. It only involves with Hadmard gates and function oracles. Implementation of oracles based on truth table in Cirq is just simple diagnal gates. To see that, let's use a oracle defined over $\\mathbb{Z}_2^2$ as example:\n", "\n", "$$\n", "\\begin{align}\n", " \\sum_{x\\in \\{0, 1\\}^2} f(x)|x\\rangle\n", " =&\\frac{1}{2}\\Big(f(0,0)|00\\rangle + f(0,1)|01\\rangle+f(1,0)|10\\rangle + f(1,1) |11\\rangle\\Big)\\\\\n", " =&\\;\\;\\left[ \\begin{array}{cccc}\n", " f(0,0) & & & \\\\ \n", " & f(1,0) & & \\\\\n", " & & f(1,0) & \\\\\n", " & & & f(1,1) \\\\\n", " \\end{array} \\right]\n", " \\left[ \\begin{array}{c}\n", " 1/2\\\\\n", " 1/2\\\\\n", " 1/2\\\\\n", " 1/2\n", " \\end{array} \\right]\n", "\\end{align}\n", "$$\n", "\n", "It is crucial to note that the output of $f$ is either 1 or -1, so the diagonal matrix is unitary." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:05.589700Z", "iopub.status.busy": "2024-08-16T10:55:05.589044Z", "iopub.status.idle": "2024-08-16T10:55:05.611512Z", "shell.execute_reply": "2024-08-16T10:55:05.610625Z" }, "id": "_k4-gc7SCBvS" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " ┌ ┐ ┌ ┐\n", " │ 1.+0.j 0.+0.j 0.+0.j ... 0.+0.j 0.+0.j 0.+0.j│ │ 1.+0.j 0.+0.j 0.+0.j ... 0.+0.j 0.+0.j 0.+0.j│\n", " │ 0.+0.j 1.+0.j 0.+0.j ... 0.+0.j 0.+0.j 0.+0.j│ │ 0.+0.j -1.+0.j 0.+0.j ... 0.+0.j 0.+0.j 0.+0.j│\n", " │ 0.+0.j 0.+0.j -1.+0.j ... 0.+0.j 0.+0.j 0.+0.j│ │ 0.+0.j 0.+0.j -1.+0.j ... 0.+0.j 0.+0.j 0.+0.j│\n", "0: ───H───│ ... │───H───│ ... │───H───M───\n", " │ 0.+0.j 0.+0.j 0.+0.j ... 1.+0.j 0.+0.j 0.+0.j│ │ 0.+0.j 0.+0.j 0.+0.j ... -1.+0.j 0.+0.j 0.+0.j│ │\n", " │ 0.+0.j 0.+0.j 0.+0.j ... 0.+0.j 1.+0.j 0.+0.j│ │ 0.+0.j 0.+0.j 0.+0.j ... 0.+0.j 1.+0.j 0.+0.j│ │\n", " │ 0.+0.j 0.+0.j 0.+0.j ... 0.+0.j 0.+0.j -1.+0.j│ │ 0.+0.j 0.+0.j 0.+0.j ... 0.+0.j 0.+0.j 1.+0.j│ │\n", " └ ┘ └ ┘ │\n", " │ │ │\n", "1: ───H───#2──────────────────────────────────────────────────────H───#2──────────────────────────────────────────────────────H───M───\n", " │ │ │\n", "2: ───H───#3──────────────────────────────────────────────────────H───#3──────────────────────────────────────────────────────H───M───\n", " │ │ │\n", "3: ───H───#4──────────────────────────────────────────────────────H───#4──────────────────────────────────────────────────────H───M───\n", " │ │ │\n", "4: ───H───#5──────────────────────────────────────────────────────H───#5──────────────────────────────────────────────────────H───M───\n", " │ │ │\n", "5: ───H───#6──────────────────────────────────────────────────────H───#6──────────────────────────────────────────────────────H───M───\n" ] } ], "source": [ "def oracle(fs: np.ndarray, qubits: Sequence[cirq.Qid]) -> cirq.Operation:\n", " \"\"\"Construct a sample oracle using a function as above.\n", "\n", " This will create an operation with a unitary matrix that is diagonal\n", " and whose entries correspond to the values of the input function 'fs'.\n", " \"\"\"\n", " return cirq.MatrixGate(np.diag(fs).astype(complex))(*qubits)\n", "\n", "\n", "def fourier_checking_algorithm(qubits, fs, gs):\n", " \"\"\"Returns the circuit for Fourier Checking algorithm given an input.\"\"\"\n", " yield cirq.parallel_gate_op(cirq.H, *qubits)\n", " yield oracle(fs, qubits)\n", " yield cirq.parallel_gate_op(cirq.H, *qubits)\n", " yield oracle(gs, qubits)\n", " yield cirq.parallel_gate_op(cirq.H, *qubits)\n", " yield cirq.measure(*qubits)\n", "\n", "\n", "qubits = cirq.LineQubit.range(n)\n", "fs, gs, forrelation, correlation = draw_two_distribution_from_f_set(N)\n", "circuit = cirq.Circuit(fourier_checking_algorithm(qubits, fs, gs))\n", "print(circuit)" ] }, { "cell_type": "markdown", "metadata": { "id": "cD7B8h5nA75O" }, "source": [ "We derived that the square forrelation between $f$ and $g$ is the same as the state of final state in circuit so we can use cirq to check it. Just remember the final state is *never* able to be obtained in reality. In simulation, it is completely doable through `final_state_vector` or the `dirac_notation` of each moment step: " ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:05.615134Z", "iopub.status.busy": "2024-08-16T10:55:05.614540Z", "iopub.status.idle": "2024-08-16T10:55:05.645827Z", "shell.execute_reply": "2024-08-16T10:55:05.644943Z" }, "id": "Y5nCR6jiU7Up" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.12|000000⟩ + 0.12|000001⟩ + 0.12|000010⟩ + 0.12|000011⟩ + 0.12|000100⟩ + 0.12|000101⟩ + 0.12|000110⟩ + 0.12|000111⟩ + 0.12|001000⟩ + 0.12|001001⟩ + 0.12|001010⟩ + 0.12|001011⟩ + 0.12|001100⟩ + 0.12|001101⟩ + 0.12|001110⟩ + 0.12|001111⟩ + 0.12|010000⟩ + 0.12|010001⟩ + 0.12|010010⟩ + 0.12|010011⟩ + 0.12|010100⟩ + 0.12|010101⟩ + 0.12|010110⟩ + 0.12|010111⟩ + 0.12|011000⟩ + 0.12|011001⟩ + 0.12|011010⟩ + 0.12|011011⟩ + 0.12|011100⟩ + 0.12|011101⟩ + 0.12|011110⟩ + 0.12|011111⟩ + 0.12|100000⟩ + 0.12|100001⟩ + 0.12|100010⟩ + 0.12|100011⟩ + 0.12|100100⟩ + 0.12|100101⟩ + 0.12|100110⟩ + 0.12|100111⟩ + 0.12|101000⟩ + 0.12|101001⟩ + 0.12|101010⟩ + 0.12|101011⟩ + 0.12|101100⟩ + 0.12|101101⟩ + 0.12|101110⟩ + 0.12|101111⟩ + 0.12|110000⟩ + 0.12|110001⟩ + 0.12|110010⟩ + 0.12|110011⟩ + 0.12|110100⟩ + 0.12|110101⟩ + 0.12|110110⟩ + 0.12|110111⟩ + 0.12|111000⟩ + 0.12|111001⟩ + 0.12|111010⟩ + 0.12|111011⟩ + 0.12|111100⟩ + 0.12|111101⟩ + 0.12|111110⟩ + 0.12|111111⟩\n", "|0> state probability to observe: 0.015625\n", "0.12|000000⟩ + 0.12|000001⟩ - 0.12|000010⟩ - 0.12|000011⟩ - 0.12|000100⟩ - 0.12|000101⟩ + 0.12|000110⟩ + 0.12|000111⟩ - 0.12|001000⟩ + 0.12|001001⟩ - 0.12|001010⟩ + 0.12|001011⟩ - 0.12|001100⟩ - 0.12|001101⟩ - 0.12|001110⟩ - 0.12|001111⟩ - 0.12|010000⟩ + 0.12|010001⟩ - 0.12|010010⟩ - 0.12|010011⟩ - 0.12|010100⟩ + 0.12|010101⟩ - 0.12|010110⟩ + 0.12|010111⟩ + 0.12|011000⟩ + 0.12|011001⟩ + 0.12|011010⟩ + 0.12|011011⟩ - 0.12|011100⟩ - 0.12|011101⟩ + 0.12|011110⟩ + 0.12|011111⟩ - 0.12|100000⟩ - 0.12|100001⟩ + 0.12|100010⟩ + 0.12|100011⟩ - 0.12|100100⟩ + 0.12|100101⟩ + 0.12|100110⟩ + 0.12|100111⟩ - 0.12|101000⟩ + 0.12|101001⟩ - 0.12|101010⟩ + 0.12|101011⟩ + 0.12|101100⟩ - 0.12|101101⟩ - 0.12|101110⟩ - 0.12|101111⟩ + 0.12|110000⟩ + 0.12|110001⟩ + 0.12|110010⟩ + 0.12|110011⟩ - 0.12|110100⟩ - 0.12|110101⟩ - 0.12|110110⟩ + 0.12|110111⟩ + 0.12|111000⟩ + 0.12|111001⟩ + 0.12|111010⟩ - 0.12|111011⟩ + 0.12|111100⟩ + 0.12|111101⟩ + 0.12|111110⟩ - 0.12|111111⟩\n", "|0> state probability to observe: 0.015625\n", "0.06|000000⟩ - 0.19|000001⟩ - 0.06|000010⟩ - 0.06|000011⟩ + 0.19|000100⟩ - 0.06|000101⟩ + 0.19|000110⟩ - 0.06|000111⟩ - 0.12|001001⟩ - 0.12|001010⟩ - 0.12|001100⟩ + 0.25|001101⟩ + 0.12|001110⟩ - 0.19|010000⟩ - 0.06|010001⟩ - 0.06|010010⟩ + 0.06|010011⟩ - 0.06|010100⟩ - 0.19|010101⟩ - 0.06|010110⟩ + 0.06|010111⟩ + 0.25|011000⟩ + 0.25|011001⟩ - 0.12|011010⟩ - 0.12|011011⟩ - 0.12|011100⟩ + 0.12|011101⟩ + 0.12|011110⟩ + 0.12|011111⟩ - 0.12|100000⟩ - 0.12|100001⟩ + 0.25|100110⟩ - 0.06|101000⟩ + 0.06|101001⟩ + 0.31|101010⟩ - 0.06|101011⟩ - 0.19|101100⟩ - 0.06|101101⟩ + 0.06|101110⟩ - 0.06|101111⟩ + 0.12|110001⟩ + 0.12|110010⟩ + 0.12|110100⟩ + 0.12|110110⟩ + 0.06|111000⟩ + 0.06|111001⟩ - 0.06|111010⟩ + 0.19|111011⟩ + 0.19|111100⟩ - 0.06|111101⟩ + 0.19|111110⟩ - 0.06|111111⟩\n", "|0> state probability to observe: 0.00390625\n", "0.06|000000⟩ + 0.19|000001⟩ + 0.06|000010⟩ + 0.06|000011⟩ + 0.19|000100⟩ + 0.06|000101⟩ + 0.19|000110⟩ + 0.06|000111⟩ - 0.12|001001⟩ + 0.12|001010⟩ + 0.12|001100⟩ + 0.25|001101⟩ + 0.12|001110⟩ + 0.19|010000⟩ + 0.06|010001⟩ + 0.06|010010⟩ + 0.06|010011⟩ + 0.06|010100⟩ + 0.19|010101⟩ - 0.06|010110⟩ + 0.06|010111⟩ + 0.25|011000⟩ + 0.25|011001⟩ + 0.12|011010⟩ + 0.12|011011⟩ + 0.12|011100⟩ + 0.12|011101⟩ - 0.12|011110⟩ + 0.12|011111⟩ + 0.12|100000⟩ + 0.12|100001⟩ + 0.25|100110⟩ - 0.06|101000⟩ + 0.06|101001⟩ + 0.31|101010⟩ + 0.06|101011⟩ + 0.19|101100⟩ - 0.06|101101⟩ + 0.06|101110⟩ + 0.06|101111⟩ + 0.12|110001⟩ + 0.12|110010⟩ + 0.12|110100⟩ + 0.12|110110⟩ - 0.06|111000⟩ + 0.06|111001⟩ + 0.06|111010⟩ + 0.19|111011⟩ + 0.19|111100⟩ + 0.06|111101⟩ + 0.19|111110⟩ - 0.06|111111⟩\n", "|0> state probability to observe: 0.00390625\n", "0.66|000000⟩ + 0.12|000001⟩ + 0.06|000010⟩ - 0.09|000011⟩ - 0.09|000101⟩ - 0.09|000110⟩ - 0.06|000111⟩ - 0.03|001000⟩ + 0.06|001010⟩ - 0.03|001011⟩ - 0.03|001101⟩ + 0.22|001110⟩ + 0.06|001111⟩ - 0.03|010000⟩ + 0.12|010001⟩ - 0.12|010010⟩ - 0.09|010011⟩ - 0.12|010100⟩ - 0.03|010101⟩ + 0.03|010110⟩ + 0.09|011000⟩ - 0.06|011001⟩ + 0.06|011010⟩ + 0.03|011011⟩ + 0.06|011100⟩ - 0.16|011101⟩ + 0.16|011110⟩ + 0.06|011111⟩ + 0.09|100000⟩ - 0.12|100001⟩ + 0.19|100010⟩ + 0.09|100011⟩ + 0.22|100101⟩ - 0.03|100110⟩ + 0.06|100111⟩ + 0.03|101000⟩ - 0.06|101010⟩ + 0.03|101011⟩ - 0.09|101101⟩ - 0.09|101110⟩ - 0.06|101111⟩ - 0.03|110000⟩ + 0.06|110001⟩ - 0.06|110010⟩ - 0.09|110011⟩ - 0.19|110100⟩ - 0.16|110101⟩ - 0.09|110110⟩ + 0.06|110111⟩ + 0.09|111000⟩ + 0.03|111011⟩ + 0.12|111100⟩ - 0.03|111101⟩ + 0.03|111110⟩ - 0.25|111111⟩\n", "|0> state probability to observe: 0.4306640625\n", "-1|110101⟩\n", "|0> state probability to observe: 0.0\n" ] } ], "source": [ "assert np.isclose(circuit.final_state_vector(ignore_terminal_measurements=True, dtype=np.complex64)[0], forrelation)\n", "\n", "s = cirq.Simulator()\n", "for step in s.simulate_moment_steps(circuit):\n", " print(step.dirac_notation())\n", " print(\"|0> state probability to observe: \",\n", " np.abs(step.state_vector(copy=True)[0])**2)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:05.649130Z", "iopub.status.busy": "2024-08-16T10:55:05.648668Z", "iopub.status.idle": "2024-08-16T10:55:05.760857Z", "shell.execute_reply": "2024-08-16T10:55:05.759936Z" }, "id": "9rEqwrI9KM4w" }, "outputs": [ { "data": { "image/png": "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EG4AAEBQIdz4yeTJkxUfH6/IyEglJiZqzZo1djfJFkuXLtUNN9ygtm3bKiQkRPPmzSv3uDFGY8aMUZs2bdSoUSMlJSVpz5499jTWYqmpqbrkkkvUrFkztW7dWjfeeKN27dpVbp+SkhKNHDlSZ511lpo2bapbbrlFOTk5NrXYWlOmTFHPnj09E4r169dPX3zxhefx+nxufmncuHEKCQnRQw895NlWn8/PM888o5CQkHK3rl27eh6vz+dGkg4ePKjf/e53Ouuss9SoUSP16NFDa9eu9TwejJ/LhBs/mDVrllJSUjR27FitX79evXr1UnJysnJzc+1umuWKiorUq1cvTZ48udLHx48fr4kTJ2rq1KlavXq1mjRpouTkZJWUlFjcUustWbJEI0eO1KpVq7Rw4UI5nU5df/31Kioq8uzz8MMP69NPP9Xs2bO1ZMkSZWZm6uabb7ax1dZp3769xo0bp3Xr1mnt2rW65pprNHjwYG3btk1S/T43P/ftt9/qX//6l3r27Flue30/PxdeeKGysrI8t+XLl3seq8/n5ujRo+rfv78aNmyoL774Qtu3b9c//vEPtWzZ0rNPUH4uG5yxvn37mpEjR3ruu1wu07ZtW5Oammpjq+wnycydO9dz3+12m9jYWPPSSy95th07dsxERESY//znPza00F65ublGklmyZIkx5uS5aNiwoZk9e7Znnx07dhhJZuXKlXY101YtW7Y0//73vzk3PyosLDRdunQxCxcuNAMGDDCjR482xvDeGTt2rOnVq1elj9X3c/PYY4+Zyy+/vMrHg/VzmZ6bM+RwOLRu3TolJSV5toWGhiopKUkrV660sWW1T3p6urKzs8udq6ioKCUmJtbLc5Wfny9JatWqlSRp3bp1cjqd5c5P165ddc4559S78+NyuTRz5kwVFRWpX79+nJsfjRw5Ur/+9a/LnQeJ944k7dmzR23btlWnTp105513KiMjQxLn5pNPPlFCQoJuvfVWtW7dWhdddJGmTZvmeTxYP5cJN2fo0KFDcrlciomJKbc9JiZG2dnZNrWqdjp1PjhXJ1enf+ihh9S/f391795d0snzEx4erhYtWpTbtz6dny1btqhp06aKiIjQvffeq7lz56pbt26cG0kzZ87U+vXrlZqaWuGx+n5+EhMTNX36dM2fP19TpkxRenq6rrjiChUWFtb7c7Nv3z5NmTJFXbp00YIFC3TffffpwQcf1DvvvCMpeD+X692q4EBtMHLkSG3durXcuABI559/vjZu3Kj8/Hx9+OGHGjZsmJYsWWJ3s2x34MABjR49WgsXLlRkZKTdzal1fvWrX3n+3LNnTyUmJqpDhw7673//q0aNGtnYMvu53W4lJCTo73//uyTpoosu0tatWzV16lQNGzbM5tYFDj03Zyg6OlphYWEVRt7n5OQoNjbWplbVTqfOR30/V6NGjdJnn32mRYsWqX379p7tsbGxcjgcOnbsWLn969P5CQ8PV+fOndWnTx+lpqaqV69eevXVV+v9uVm3bp1yc3N18cUXq0GDBmrQoIGWLFmiiRMnqkGDBoqJianX5+eXWrRoofPOO0979+6t9++dNm3aqFu3buW2XXDBBZ6yXbB+LhNuzlB4eLj69OmjtLQ0zza32620tDT169fPxpbVPh07dlRsbGy5c1VQUKDVq1fXi3NljNGoUaM0d+5cff311+rYsWO5x/v06aOGDRuWOz+7du1SRkZGvTg/lXG73SotLa335+baa6/Vli1btHHjRs8tISFBd955p+fP9fn8/NLx48f13XffqU2bNvX+vdO/f/8KU07s3r1bHTp0kBTEn8t2j2gOBjNnzjQRERFm+vTpZvv27eaPf/yjadGihcnOzra7aZYrLCw0GzZsMBs2bDCSzCuvvGI2bNhgvv/+e2OMMePGjTMtWrQwH3/8sdm8ebMZPHiw6dixozlx4oTNLQ+8++67z0RFRZnFixebrKwsz624uNizz7333mvOOecc8/XXX5u1a9eafv36mX79+tnYaus8/vjjZsmSJSY9Pd1s3rzZPP744yYkJMR8+eWXxpj6fW4q8/OrpYyp3+fnkUceMYsXLzbp6enmm2++MUlJSSY6Otrk5uYaY+r3uVmzZo1p0KCBeeGFF8yePXvMjBkzTOPGjc3777/v2ScYP5cJN34yadIkc84555jw8HDTt29fs2rVKrubZItFixYZSRVuw4YNM8acvOzw6aefNjExMSYiIsJce+21ZteuXfY22iKVnRdJ5u233/bsc+LECXP//febli1bmsaNG5ubbrrJZGVl2ddoC919992mQ4cOJjw83Jx99tnm2muv9QQbY+r3uanML8NNfT4/Q4YMMW3atDHh4eGmXbt2ZsiQIWbv3r2ex+vzuTHGmE8//dR0797dREREmK5du5o33nij3OPB+LkcYowx9vQZAQAA+B9jbgAAQFAh3AAAgKBCuAEAAEGFcAMAAIIK4QYAAAQVwg0AAAgqhBsAABBUCDcAACCoEG4ABJXs7Gxdd911atKkiVq0aBHQ1woJCdG8efOqfHz//v0KCQnRxo0bA9oOAOURbgBIkvLy8nTffffpnHPOUUREhGJjY5WcnKxvvvnGs8/pvsyrEh8frwkTJvivsdX45z//qaysLG3cuFG7d++25DWrEhcXp6ysLHXv3l2StHjxYoWEhFRYoRqAfzWwuwEAaodbbrlFDodD77zzjjp16qScnBylpaXp8OHDdjetRr777jv16dNHXbp0sbspCgsLU2xsrN3NAOofuxe3AmC/o0ePGklm8eLFVe7ToUOHcgt+dujQwRhjzN69e81vfvMb07p1a9OkSROTkJBgFi5c6HnegAEDKiwWesqyZcvM5ZdfbiIjI0379u3NAw88YI4fP15tW19//XXTqVMn07BhQ3PeeeeZd999t8o2nlqw9ZfKysrMww8/bKKiokyrVq3Mn//8ZzN06FAzePDgcsf65z//We55vXr1MmPHjvXcl2Ref/11M3DgQBMZGWk6duxoZs+e7Xk8PT3dSDIbNmzw/Lmy9s2ePdt0797dREZGmlatWplrr732tOcBQNUoSwFQ06ZN1bRpU82bN0+lpaWV7vPtt99Kkt5++21lZWV57h8/flyDBg1SWlqaNmzYoIEDB+qGG25QRkaGJGnOnDlq3769nnvuOWVlZSkrK0vSyR6WgQMH6pZbbtHmzZs1a9YsLV++XKNGjaqynXPnztXo0aP1yCOPaOvWrfrTn/6k4cOHa9GiRZ42Dhw4ULfddpuysrL06quvVnqcf/zjH5o+fbreeustLV++XEeOHNHcuXN9OndPP/20brnlFm3atEl33nmnbr/9du3YsaPCfnFxcfroo48kSbt27fK0LysrS3fccYfuvvtu7dixQ4sXL9bNN98sw5rGgO/sTlcAaocPP/zQtGzZ0kRGRprLLrvMPPHEE2bTpk3l9pFk5s6de9pjXXjhhWbSpEme+5X1gtxzzz3mj3/8Y7lty5YtM6GhoebEiROVHveyyy4zI0aMKLft1ltvNYMGDfLcHzx4cJU9Nqe0adPGjB8/3nPf6XSa9u3b+9Rzc++995bbJzEx0dx3333GmPI9N8YYs2jRIiPJHD161LP/unXrjCSzf//+atsMwHv03ACQdHLMTWZmpj755BMNHDhQixcv1sUXX6zp06dX+7zjx4/r0Ucf1QUXXKAWLVqoadOm2rFjh6fnpiqbNm3S9OnTPb1GTZs2VXJystxut9LT0yt9zo4dO9S/f/9y2/r3719pT0lV8vPzlZWVpcTERM+2Bg0aKCEhwetj/Fy/fv0q3K9Je3r16qVrr71WPXr00K233qpp06bp6NGjPrUFwEmEGwAekZGRuu666/T0009rxYoVuuuuuzR27Nhqn/Poo49q7ty5+vvf/65ly5Zp48aN6tGjhxwOR7XPO378uP70pz9p48aNntumTZu0Z88enXvuuf78a/kkNDS0QmnI6XT6/XXCwsK0cOFCffHFF+rWrZsmTZqk888/v8qAB+D0CDcAqtStWzcVFRV57jds2FAul6vcPt98843uuusu3XTTTerRo4diY2O1f//+cvuEh4dXeN7FF1+s7du3q3PnzhVu4eHhlbbnggsuKHdp+qnX79atm9d/p6ioKLVp00arV6/2bCsrK9O6devK7Xf22Wd7xgdJUkFBQaWBY9WqVRXuX3DBBZW+9qm/1y/PRUhIiPr3769nn31WGzZsUHh4uM9jgABwKTgASYcPH9att96qu+++Wz179lSzZs20du1ajR8/XoMHD/bsFx8fr7S0NPXv318RERFq2bKlunTpojlz5uiGG25QSEiInn76abnd7nLHj4+P19KlS3X77bcrIiJC0dHReuyxx3TppZdq1KhR+sMf/qAmTZpo+/btWrhwoV577bVK2/nnP/9Zt912my666CIlJSXp008/1Zw5c/TVV1/V6O87evRojRs3Tl26dFHXrl31yiuvVJh75pprrtH06dN1ww03qEWLFhozZozCwsIqHGv27NlKSEjQ5ZdfrhkzZmjNmjV68803K33dDh06KCQkRJ999pkGDRqkRo0aadu2bUpLS9P111+v1q1ba/Xq1crLy6syIAHwgt2DfgDYr6SkxDz++OPm4osvNlFRUaZx48bm/PPPN0899ZQpLi727PfJJ5+Yzp07mwYNGnguBU9PTzdXX321adSokYmLizOvvfaaGTBggBk9erTneStXrjQ9e/Y0ERER5S4FX7NmjbnuuutM06ZNTZMmTUzPnj3NCy+8UG1bq7sU3BjvBhQ7nU4zevRo07x5c9OiRQuTkpJS4VLw/Px8M2TIENO8eXMTFxdnpk+fXumA4smTJ5vrrrvOREREmPj4eDNr1izP478cUGyMMc8995yJjY01ISEhZtiwYWb79u0mOTnZnH322SYiIsKcd9555QZjA6i5EGO43hAA7rrrLh07dsynGZgB1C6MuQEAAEGFcAMAAIIKZSkAABBU6LkBAABBhXADAACCCuEGAAAEFcINAAAIKoQbAAAQVAg3AAAgqBBuAABAUCHcAACAoPL/Ae/0ib2Q/fiWAAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "final_state = circuit.final_state_vector(ignore_terminal_measurements=True, dtype=np.complex64)\n", "plt.fill_between(np.arange(len(final_state)),\n", " np.abs(final_state)**2)\n", "plt.xlabel(\"State of qubits\")\n", "plt.ylabel(\"Probability\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "id": "m5Qzdo8rTPxJ" }, "source": [ "In reality, we can measure the state of qubits only. Each measurement will only produce one state. In order to estimate the probability, we can do 100 repetitions and use the frequency of the 0 state as the approximation of its probability." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:05.764684Z", "iopub.status.busy": "2024-08-16T10:55:05.764053Z", "iopub.status.idle": "2024-08-16T10:55:05.775472Z", "shell.execute_reply": "2024-08-16T10:55:05.774620Z" }, "id": "RS-njXvxM3pA" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "times zero state was measured from 100 measurements:40 - 40.0%\n", "fs and gs is forrelated!\n" ] } ], "source": [ "repetitions = 100\n", "obs = s.run(circuit, repetitions=repetitions)\n", "qubits_name = ','.join(str(q) for q in qubits)\n", "times_zero_was_measured = len(obs.data[obs.data[qubits_name] == 0])\n", "print(\n", " f\"times zero state was measured from {repetitions} measurements:\" +\n", " f\"{times_zero_was_measured} - {float(times_zero_was_measured/repetitions)*100}%\"\n", ")\n", "if float(times_zero_was_measured / repetitions) > 0.05:\n", " print(\"fs and gs is forrelated!\")" ] }, { "cell_type": "markdown", "metadata": { "id": "IHLLADQvT-lK" }, "source": [ "Last, we can randomly draw the functions from either $\\mathcal{U}$ or $\\mathcal{F}$ set to evaluate the confusion matrix of the Fourier Checking algorithm. With the confusion matrix, you should be confident that quantum algorithm instead can solve the Fourier Checking in $O(1)$ time -- even though we need to measure 100 or 1000 times to evaluate the probability, it is irrelevant to the number of states or qubits." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "execution": { "iopub.execute_input": "2024-08-16T10:55:05.778925Z", "iopub.status.busy": "2024-08-16T10:55:05.778463Z", "iopub.status.idle": "2024-08-16T10:55:19.094793Z", "shell.execute_reply": "2024-08-16T10:55:19.094054Z" }, "id": "PTq4ys9PanaM" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Decisionacceptreject
Source
F set100.00NaN
U set5.9494.06
\n", "
" ], "text/plain": [ "Decision accept reject\n", "Source \n", "F set 100.00 NaN\n", "U set 5.94 94.06" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "res = pd.DataFrame()\n", "repetitions = 100\n", "num_rounds = 1000\n", "for _ in range(num_rounds):\n", " if np.random.rand() > 0.5:\n", " fs, gs, _, _ = draw_two_distribution_from_f_set(N)\n", " source = \"F set\"\n", " else:\n", " fs, gs, _, _ = draw_two_distribution_from_u_set(N)\n", " source = \"U set\"\n", "\n", " circuit = cirq.Circuit(fourier_checking_algorithm(qubits, fs, gs))\n", " obs = s.run(circuit, repetitions=repetitions)\n", " times_zero_was_measured = len(obs.data[obs.data[qubits_name] == 0])\n", " decision = \"accept\" if times_zero_was_measured / repetitions > 0.05 else \"reject\"\n", " res=pd.concat([res, pd.DataFrame({\n", " \"Source\": [source],\n", " \"Decision\":[decision],\n", " \"Count\": [1]\n", " })], ignore_index=True)\n", "confusion = res.pivot_table(index=\"Source\", columns=\"Decision\", values=\"Count\", aggfunc=\"sum\")\n", "# Translate the counts into percentage\n", "confusion.div(confusion.sum(axis=1), axis=0).apply(lambda x: round(x, 4) * 100)" ] }, { "cell_type": "markdown", "metadata": { "id": "03GsjDCXst4E" }, "source": [ "# Query Complexity of Quantum Algorithm Versus the Classical one\n", "\n", "After we present the quantum algorithm, it is time to look back to classical algorithm for comparison. It is not hard to give a classical algorithm that solves Fourier Checking using $O(\\sqrt{N}) = O(2^{n/2})$ queries, which is similar as we did in the BPP section.\n", "\n", "For some $K=\\Theta(\\sqrt{N})$, first choose sets $X=\\{x_1,\\ldots, x_K\\}$ and $Y = \\{y_1, \\ldots, y_K\\}$ of $n-$bit strings uniformly at random. Then query $f(x_i)$ and $g(y_i)$ for all $i \\in [K]$. Finally, compute\n", "$$\n", " Z := \\sum_{i,j=1}^K f(x_i) (-1)^{x_i\\cdot y_j} g(y_j)\n", "$$\n", "accept if $|Z|$ is greater than some cutoff $cK$, and reject otherwise. For suitable $K$ and $c$, one can show that this algorithm accepts a forrelated $\\langle f, g \\rangle$ pair with probability at least $2/3$. Comparing this with $O(1)$ complexity in quantum query, we can see an exponential speedup by using quantum computer.\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "id": "HpOFrK4QW5Y4" }, "source": [ "# Further reading\n", "\n", "The Forrelation problem was originally introduced in [1]. Later, a **$k$-fold Forrelation** problem was introduced in [2], which considered the forrelation between $k$ oracle functions. In that paper, it also improved the proof about the separation of forrelation problem from $\\Omega\\left(\\sqrt[4]{N}\\right)$ to $\\tilde{\\Omega}\\left(\\sqrt{N}\\right)$, which can not be further improved. Thus, resolving an open question of Buhrman et al., there is NO partial\n", "Boolean function whose quantum query complexity is constant and whose randomized query complexity is linear. \n", "\n", "[1] *Scott Aaronson. BQP and the Polynomial Hierarchy. STOC ’10, page 141–150, New York, NY, USA, 2010.* [arXiv](https://arxiv.org/pdf/0910.4698.pdf)\n", "\n", "[2] *Scott Aaronson and Andris Ambainis. Forrelation: A problem that optimally separates quantum\n", "from classical computing. SIAM J. Comput., 47(3):982–1038, 2018.* [arXiv](https://arxiv.org/pdf/1411.5729.pdf)" ] } ], "metadata": { "colab": { "collapsed_sections": [], "name": "fourier_checking.ipynb", "toc_visible": true }, "kernelspec": { "display_name": "Python 3", "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.10.14" } }, "nbformat": 4, "nbformat_minor": 0 }