{ "cells": [ { "cell_type": "markdown", "source": [ "# Hands-on 7\n", "## Grover's Algorithm and Amplitude Amplification\n", "\n", "Grover's algorithm is one of the most famous quantum algorithms introduced by Lov Grover in 1996 \\[1\\]. It has initially been proposed for unstructured search problems, i.e. for finding a marked element in a unstructured database. However, Grover's algorithm is now a subroutine to several other algorithms, such as Grover Adaptive Search \\[2\\].\n", "\n", "Qiskit implements Grover's algorithm in the `Grover` class. This class also includes the generalized version, Amplitude Amplification \\[3\\], and allows setting individual iterations and other meta-settings to Grover's algorithm.\n", "\n", "**References:**\n", "\n", "\\[1\\]: L. K. Grover, A fast quantum mechanical algorithm for database search. Proceedings 28th Annual Symposium on\n", "the Theory of Computing (STOC) 1996, pp. 212-219. https://arxiv.org/abs/quant-ph/9605043\n", "\n", "\\[2\\]: A. Gilliam, S. Woerner, C. Gonciulea, Grover Adaptive Search for Constrained Polynomial Binary Optimization.\n", "https://arxiv.org/abs/1912.04088\n", "\n", "\n", "\\[3\\]: Brassard, G., Hoyer, P., Mosca, M., & Tapp, A. (2000). Quantum Amplitude Amplification and Estimation. http://arxiv.org/abs/quant-ph/0005055" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "markdown", "source": [ "### Grover's algorithm\n", "\n", "Grover's algorithm uses the Grover operator $\\mathcal{Q}$ to amplify the amplitudes of the good states:\n", "\n", "$$\n", " \\mathcal{Q} = \\mathcal{A}\\mathcal{S_0}\\mathcal{A}^\\dagger \\mathcal{S_f}\n", "$$\n", "\n", "Here, \n", "* $\\mathcal{A}$ is the initial search state for the algorithm, which is just Hadamards, $H^{\\otimes n}$ for the textbook Grover search, but can be more elaborate for Amplitude Amplification\n", "* $\\mathcal{S_0}$ is the reflection about the all 0 state\n", "$$\n", " |x\\rangle \\mapsto \\begin{cases} -|x\\rangle, &x \\neq 0 \\\\ |x\\rangle, &x = 0\\end{cases}\n", "$$\n", "* $\\mathcal{S_f}$ is the oracle that applies\n", "$$\n", " |x\\rangle \\mapsto (-1)^{f(x)}|x\\rangle\n", "$$\n", " 怀 where $f(x)$ is 1 if $x$ is a good state and otherwise 0.\n", "\n", "In a nutshell, Grover's algorithm applies different powers of $\\mathcal{Q}$ and after each execution checks whether a good solution has been found. \n", "\n", "\n", "#### Running Grover's algorithm\n", "\n", "To run Grover's algorithm with the `Grover` class, firstly, we need to specify an oracle for the circuit of Grover's algorithm. In the following example, we use `QuantumCircuit` as the oracle of Grover's algorithm. However, there are several other class that we can use as the oracle of Grover's algorithm. We talk about them later in this tutorial.\n", "\n", "Note that the oracle for `Grover` must be a _phase-flip_ oracle. That is, it multiplies the amplitudes of the of \"good states\" by a factor of $-1$. We explain later how to convert a _bit-flip_ oracle to a phase-flip oracle. " ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 1, "outputs": [ { "data": { "text/plain": "
", "image/png": "iVBORw0KGgoAAAANSUhEUgAAAdkAAACFCAYAAAAXfII6AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAY/klEQVR4nO3deXhU9b3H8feZSUIIWwMI0SQsiqyJCQmEJSCpLGJbIUWpFvQJESoq4cqjKPFpoLLc0mqlbhRseUBtCHqLBHtt6kZla+NVyKJAoyKJCYh6IRECCWaZc/+YSyCQbcKczEz8vJ7nPEx+c37nfOfwO/nkLDNjmKZpIiIiIm5n83QBIiIi7ZVCVkRExCIKWREREYsoZEVERCyikBUREbGIQlZERMQiClkRERGLKGRFREQs0qKQ/frrr5k1axbXXnstsbGxjBkzhszMTAA6d+7cZN+ioiIiIiJcLqyx5drtdqKjo4mIiGDmzJlUVFS0eh0iIiJWajZkTdMkMTGRG2+8kSNHjrB//35eeeUVjh492hb1XaZjx47k5eVx4MABAgICWL9+vUfqEBERaU6zIfuPf/yDgIAA7rvvvrq2vn37snDhwsvmXbNmDREREURERPD000/XtdfU1DB79myGDBnC7bffTkVFBQCJiYnExsYybNgw/vjHP7pc/Pjx4zl8+DAAtbW1/OIXv2DYsGFMmTKFysrKRtdx9uxZfvzjHxMVFUVERASvvvoqAOnp6cTFxREdHc38+fOpra1tcv2ff/45V111Ff369SM6Opru3btz3XXXcfr0aZdfi4iItENmM5555hlz0aJFjT7fqVMn0zRNc9++fWZERIR55swZs7y83Bw6dKiZk5NjFhYWmoC5d+9e0zRNMzk52XzyySdN0zTNkydPmqZpmhUVFeawYcPMEydOXLbcxtZXXV1tTps2zfzDH/5gFhYWmna73czNzTVN0zRnzpxp/vnPf250HVu3bjXnzZtXt8xvv/3WPHTokPmTn/zErKqqMk3TNO+//37zpZdeMk3TNG+55Rbz2LFjDdaTmJho7t692zRN05wwYYL50UcfNbqtRETk+8XlG58WLFhAVFQUI0eOrNe+d+9efvrTn9KpUyc6d+7MjBkz2LNnDwDh4eHEx8cDcNddd7F3714Ann32WaKiohg9ejQlJSV89tlnza6/srKS6OhoRowYQZ8+fZg7dy4A/fv3Jzo6GoDY2FiKiooaXUdkZCTvvPMOS5YsYc+ePXTr1o0dO3awf/9+Ro4cSXR0NDt27ODIkSMAZGVlcc011zRYz8GDB+uuB//73/9m0KBBLmxNERFpz/yam2HYsGG89tprdT+vXbuWEydOMGLEiBavxDCMy37euXMn7777LtnZ2QQFBZGQkMC5c+eaXdb5a7KX6tChQ91ju91OZWVlo+sYOHAgOTk5ZGVlkZaWxsSJEwkODiYpKYnVq1e3+HVVVlZy7tw5goODKSkpoWfPngQEBLS4v4iItG/NHsnedNNNnDt3jnXr1tW1nb+merHx48ezfft2KioqOHv2LJmZmYwfPx6A4uJisrOzAcjIyGDcuHGcOnWK4OBggoKCKCgo4P3333fXa6rT2Dq+/PJLgoKCuOuuu3jkkUfIyclh4sSJbN26lW+++QaA0tJSvvjiiyaXf+jQIYYMGQI4j2LPPxYREYEWhKxhGGzfvp1du3bRv39/4uLiSEpK4re//W29+WJiYpgzZw5xcXGMGjWKefPmMXz4cAAGDRrE2rVrGTJkCGVlZdx///1MnTqVmpoahgwZQmpqKqNHj3b7i2tsHR9//HHdDU7Lly8nLS2NoUOHsmrVKqZMmcINN9zA5MmTOX78OAA/+tGP+PLLLy9b/sWnijt27EhOTg4FBQVufx0iIuKbDNPUl7aLiIhYQZ/4JCIiYhGFrIiIiEUUsiIiIhZRyIqIiFhEISsiImIRhayIiIhFFLIiIiIWUciKiIhYRCErIiJiEYWsiIiIRRSyIiIiFlHIioiIWEQhKyIiYhGFrIiIiEUUsiIiIhZRyIqIiFhEISsiImIRhayIiIhFFLIiIiIW8fN0AdJ+bNsHx8o8s+7QYJgxonV9H/7kEPnl5e4tqAWiunThqUFD23y94hpPjQ+4sjHiqf3xSvbF9kghK25zrAw+/8bTVbguv7yc3WWlni5DvJSvjg9f3R/bG50uFhERsYhCVkRExCIKWREREYsoZEVERCyikBUREbGIQlZERMQiClkRERGL+GzIVlRU8Pjjj5Obm+uR/iIiIs3x2ZDNy8tj+fLllLfyk1iutL+3qnVA+Tk4V+3pSkTcp6YWyiuhqsbTlYi4xmdDNjc3F8MwiI6O9kh/b3PmHPw1F9Jeg6WvQep/wbNvw4Gjnq6saVtXJfDB9lUtbvcGZnU11felUPvCn+q112Zup/quJMwzZzxUWfvz9WnIyHaO56XbYMl/wabdUHzS05U1zlfHhy/ui77Aa0N23759zJgxg7CwMDp06EBYWBiJiYlUVlYSGRlJSkoKpmnSrVs3DMNg1KhRAOzcuZPExETCw8MJDAwkNDSUefPmcerUqbplN9X/vPT0dOLj4+nUqRMhISEkJydTWuqdH612qgLWvAn/OASVVRfaC0/Ahl3w9gHP1dYeGf7++KU+guONLBy5eQCYhYU4Nr6E/dHFGJ07e7bAdqLoBDz1d/jwCNQ4nG2mCR+VwNNvwcclnq2vMRofcjGvDNm8vDzi4+MJDAxk3bp1vPXWW6xcuZKuXbvSsWNHNm3axODBg5k0aRLZ2dlkZ2eTnp4OQH5+PuPGjWP9+vW8/fbbLFu2jNdff52HH364bvlN9QdYuHAhycnJxMXFkZmZyerVq3nzzTeZNWtWm2+LltjyPpSdvbzdNJ3/ZuXDEX2GqVsZ/fpiuyeJ2t/9HrO0lJrfPIlt+q3Yboj0dGntQq0DNu6C6howL3nOxDm2X9rrPIPjjTQ+5Dyv/IKA9PR0evToQUZGRl1bQkICycnJAAwfPpzi4mJmz57N6NGj6/V98MEH6x47HA7Gjh1Lfn4+O3bsqGtvqv+WLVt4/vnnefHFF0lKSqprDwoK4s4776SoqIh+/fq58+Vekf89DQXHm57HAPZ8Ctf2apOSvjdsidMxP9hHzfwFcFVPbEl3e7qkduPjEjjdRICaOI9uPzgCN3npFxlpfAh46ZFsr169OH78OCkpKeTk5Fz2fEFBARUVFcTExNRrr62tZfPmzYwbN47evXtjt9vx9/dn3bp1dL7oFE1j/QFWrFhBTEwMs2fPpqampm4aOtS5JxcWFgJQVFTEhAkTGDhwIJGRkezZs6dFr80wDLdOP5w2t9l1msA/P/7G7eu+dNq1a2eLtsGlPnj9P1l37w/qTV9+utelZezatbPVde/c2bq6DcPAuCESTp3CNvEmDH9/l/rv3Nn6mtv79NDjf8DhqG1y+zkctTyz6W+W1+Kp8XGlY6Q1+6On90VfmVzhlUeyixYtoqqqipdffpm1a9fSp08f7r33Xh577DFsNhv79+8HnEekF0tKSmLbtm2kpKSwZMkSevbsiZ+fHxMnTiQy8sJpmsb6l5SUUFBQAIB/IztEt27dAJg/fz533HEHDzzwAP/617+YOXMmhYWFBAQEuGcjtJBhs7t1Pk+Im/5L4hLT6rVtXZXgmWJcYBYW4sh4BdsdM3GkZ2AbH4/RS6cL3MGw2S9c72hsHgyvHte+OD58dV/0Zl55JBsQEEBaWhqffvopn332GZMmTSItLY2tW7cCkJOTQ0hICFdffXVdnwMHDrB582aee+45nnjiCW699VbGjBlDVVUV5eXlxMbG1s3bUH+AY8eOAfDCCy/w4YcfNjhFRkZy4sQJ9u7dy9y5zqPIsWPHcs011/Dee+81+9pM03TrlPWXPza7TgMYfn0Pt6/70mnChIRma7HKhAkJra47IcH1us2qaud1thmJ2OcmY8SPofbJNZgOR4uXkZDQ+prb+7TqsfnY7E0fAxg2G7/4+VTLa/HU+LjSMeKp/fFK9kVfmVzhlSF7sQEDBpCamgpATY3zTXKHDh2qO317XnFxMQCDBw+ua6uuruahhx4CqBeyDfUHCA0NBcDPz48RI0Y0OPn7+1NcXEzv3r3p0KFDXd/+/fvzxRdfuOMluyS8B4R3h6bOYJjAuIFtVtL3gmPjJgw/P2x3zwbA/sB9mF99jeO1TA9X1j7E9IUOfs4/EBtjAGMGtFVFrtH4kPO87nTxggULOHv2LJMnTyYsLIzi4mKeeOIJBgwYwLRp0wAIDg5m9+7dZGVl0b17d/r160dUVBSBgYGkpqaydOlSTp48yZo1aygrK8Nut9d7P2xD/UNCQggPD2fy5MksXryY0tJSYmNj+e677ygpKSErK4sNGzbQo0cPD22Zxv18NDzzDlRVX34nJsDIa2FYaJuX1W45cvNwZL2J39pnMfycu5ARFIR9yWJqH0vDNiIGo39/D1fp2zr4w6wx8OJeMMz649rA+fP0WOjuhe+G0fiQixmmq8e+Fnvuued49dVX+eSTTygvLyc8PJzExMS6a6zgvHHpnnvuITc3l3PnzpGZmUliYiKZmZk8+uijHD16lGHDhvHoo4/yxhtvsH//fg4ePFi3jsb6A5SVlbFy5Ur++te/cvToUbp06cKAAQOYOnUqv/rVrwA4ceIEffv2pbS0tO5oduTIkaxatYqbb765bTfY//vqFLyRBwePXviF1CUQfjgEEoaAzbVr9a3y3DvwuYfeKnRdL1g4uXV9J+37H3aXtf17oG8M7s67I0Y1P+P32CfHIesj+OLEhbaQbjAlAmL6tU0NnhofcGVjxFP745Xsi+2R14Wsr5gyZQqJiYl1Nz7dfvvtFBUVtfmNT5f6tgIe//8zUk/9HOxteEFAIesahWzLfXMafv3fzse/n9X05RF3U8i6RiFbn9edLvYV69evZ86cOTz99NMEBASwZcsWjwcswA+CLjxuy4AVsVKvrhcet2XAilwphWwrXXvttezevdvTZYiIiBfTsY6IiIhFFLIiIiIWUciKiIhYRCErIiJiEYWsiIiIRRSyIiIiFlHIioiIWETvkxW3CQ32zXVHdenivkJ8YL3iGk/+P13Juj21P3ry94A3UsiK28wY4ekKWuepQZd/I5PIeb46Pnx1f2xvdLpYRETEIgpZERERiyhkRURELKKQFRERsYhCVkRExCIKWREREYsoZEVERCyikBUREbGIQlZERMQiClkRERGLKGRFREQsopAVERGxiEJWRETEIvoWHnGbbfvgWJln1h0a3PpvHXn4k0Pkl5e7t6AWiOrSpdXf8OKr29oX+eq21rh2jVXjWiErbnOsDD7/xtNVuC6/vJzdZaWeLsMlvrqtfZGvbmuNa++g08UiIiIWUciKiIhYRKeLRcQrVXwHHx2F4hNw/NSF9oxs6NMDIsOgW5Dn6hNpCYWsiHiV05WQlQ/7i6C69vLnPzjinLbtgxvC4cdRcFXXNi9TpEUUsiLiNXKK4C8fQmVV8/M6TMgrhoPH4CfRcOMgMAyrKxRxjUJWRLzCrgLI3O96v+paZ7/Ss5AYo6AV7+KzNz5VVFTw+OOPk5ub65H+IuI+eV+0LmAvtqsA3vu3e+oRcRefDdm8vDyWL19OeSvfbH2l/UXEPcor4S8fND/f07OdU1P+lg9fnWp6HpG25LMhm5ubi2EYREdHe6S/NzpVAW9/fOHng0fB4fBcPSIt8feP4WwLrsG2RK0Dtl/hEbGIO3ltyO7bt48ZM2YQFhZGhw4dCAsLIzExkcrKSiIjI0lJScE0Tbp164ZhGIwaNQqAnTt3kpiYSHh4OIGBgYSGhjJv3jxOnbrw521T/c9LT08nPj6eTp06ERISQnJyMqWl3vnpKaYJb30Mj2+HrI8utP9pF/z6DfjmtMdKa9bWVQl8sH1Vi9u9gVldTfV9KdS+8Kd67bWZ26m+KwnzzBkPVdY4b93OlVWwr9C9yyw4Dic8eILKW7d1U3xxTINvbGuvDNm8vDzi4+MJDAxk3bp1vPXWW6xcuZKuXbvSsWNHNm3axODBg5k0aRLZ2dlkZ2eTnp4OQH5+PuPGjWP9+vW8/fbbLFu2jNdff52HH364bvlN9QdYuHAhycnJxMXFkZmZyerVq3nzzTeZNWtWm2+Lltj1Cfz9I2fYXurkGVj7Lpz9ru3raq8Mf3/8Uh/B8UYWjtw8AMzCQhwbX8L+6GKMzp09W6APOXgMqmrcv9ycIvcvsz3TmLaOV95dnJ6eTo8ePcjIyKhrS0hIIDk5GYDhw4dTXFzM7NmzGT16dL2+Dz74YN1jh8PB2LFjyc/PZ8eOHXXtTfXfsmULzz//PC+++CJJSUl17UFBQdx5550UFRXRr18/d77cK1Jd6zyKbYxpwqlKyD4Mk4a1XV3tndGvL7Z7kqj93e8xnvs9Nb95Etv0W7HdEOnp0nxK8UmLluudJ528msa0NbzySLZXr14cP36clJQUcnJyLnu+oKCAiooKYmJi6rXX1tayefNmxo0bR+/evbHb7fj7+7Nu3To6X/SXWGP9AVasWEFMTAyzZ8+mpqambho61PmtEoWFznNby5YtY+DAgdhsNrZu3erOl++SQ8da9p7CD45YX8v3jS1xOkafcGrmLwC7HVvS3Z4uyedYdZPSV99as9z2TmPa/bzySHbRokVUVVXx8ssvs3btWvr06cO9997LY489hs1mY/9+550Nw4cPr9cvKSmJbdu2kZKSwpIlS+jZsyd+fn5MnDiRyMgLf4011r+kpISCggIA/P39G6ytW7duAEydOpU5c+Zwzz33uPTaDDe/iS9y4n3clLyu2flKjn+LYQS7dd2Xuu2X7xE2JMHlfh+8/p/sz/pdvbbqc2foEzGpxcvYtWsn/zHlhy6vG8D+5G+wRd3gcj/DMDBuiMTcn4Ptzp9hNDJmGrNz506MkaObn7EBrdnW7tjOcGXb+lIzl+3lmoHx9dqau4O4oecXba7/c1HxMQwj7Aqrc/LVbd2acX2lYxq+H+PabOjaXCO8MmQDAgJIS0sjLS2Nw4cPs3r1atLS0rj++uv52c9+Rk5ODiEhIVx99dV1fQ4cOMDmzZvZsGEDc+fOrWv/5z//SXl5ObGxsXVtDfUHOHbsGAAvvPBCg0e5QF1Yjx071m2v90pUlp9odh7TdLRoPk+Jm/5L4hLT6rVtXZXgmWJcYBYW4sh4BdsdM3GkZ2AbH4/Rq5eny2qUN27n2upzliy3xqLltpQ3buuW8LUxDd6/rb0yZC82YMAAUlNT2bhxIzU1zjskDh06VHf69rzi4mIABg8eXNdWXV3NQw89BFAvZBvqDxAaGgqAn58fI0ZY863UrvwF1BLf1cCy15z/NsYwbPx8ygBedPO6L/XcO577LsgJExLYuqp1r2/Svv9x+Xs3zapq5zWrGYnYk5Mwy8qofXIN9t/+GsPWsqswCQkJvNvK/xNf3daXeu1D2PNp/bZLj0rPO38E29jzF4uPuc5t491Xt7Wr49odYxo0ri/ldSG7YMECzp49y+TJkwkLC6O4uJgnnniCAQMGMG3aNACCg4PZvXs3WVlZdO/enX79+hEVFUVgYCCpqaksXbqUkydPsmbNGsrKyrDb7fXeD9tQ/5CQEMLDw5k8eTKLFy+mtLSU2NhYvvvuO0pKSsjKymLDhg306NHDQ1umYR38nDc0/S2/4ecNIKgDjB3QpmW1e46NmzD8/LDd7fzNb3/gPmrmL8DxWib2mbd5uDrfEW7R7hTe3Zrltmca09bwuhufBg8ezOHDh1m0aBE333wzK1asYOrUqWRnZ9fdvLR8+XL69+/PbbfdxpgxY3j//fcJDQ0lIyODr776iunTp/PUU0/xyCOPMHbsWAYNGkRQ0IXvxGqo/3mvvvoqc+bMYf369dxyyy3cfffdbNy4kejoaK8L2PMmDYMfDrnws8GFz2/t0hEWTHT+K+7hyM3DkfUm9tRHMfycf6caQUHYlyzG8XI6ZqGb3/jZjg0LBT+7+5cb3df9y2zPNKatY5juPn/5PZOQkEBKSgq33367p0vhm9POt+r8bzn42SAiDKL7WPNLrCGePNVzXS9YOLl1fVtzutgdbgzuzrsjRjU/YwN8dVs3JCO7ZXe/t/R08fW9YYFr97w0yVe3tca1a9w9rs/zuiNZX7F06VLCwsLIzs5m/vz5hIWF8fnnn3u0pl5dYXoMzJsAc8bDiP5tF7AirfWjKAh0/SbWBtkM5z4g4i287pqsr1i5ciUrV670dBkiPu8HQTBjhPOItiktueFpSgSE6XqseBEdyYqIx8VdC7e4/lblekZfB1P04UTiZXQkKyJe4eZI6NrR+b2yrnyesc2AqZEwKcL5WMSbKGRFxGuMGQADQ+C/c+GjEnA0c1vmoKth2nAItfbDzERaTSErIl6lR2fnjXvfVkDeF84vETh+ynl062+H3l2d112j+8BVXT1drUjTFLIi4pV+EAQJQ5qfT8Sb6cYnERERiyhkRURELKLTxeI2nrz55ErWHdWli/sKaaP1+uq29kW+uq01rr1j3fpYRREREYvodLGIiIhFFLIiIiIWUciKiIhYRCErIiJiEYWsiIiIRRSyIiIiFlHIioiIWEQhKyIiYhGFrIiIiEUUsiIiIhZRyIqIiFhEISsiImIRhayIiIhFFLIiIiIWUciKiIhYRCErIiJiEYWsiIiIRRSyIiIiFvk/YR++yUWNTaQAAAAASUVORK5CYII=\n" }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from qiskit import QuantumCircuit\n", "from qiskit.algorithms import AmplificationProblem\n", "\n", "# the state we desire to find is '11'\n", "good_state = ['11']\n", "\n", "# specify the oracle that marks the state '11' as a good solution\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", "\n", "# define Grover's algorithm\n", "problem = AmplificationProblem(oracle, is_good_state=good_state)\n", "\n", "# now we can have a look at the Grover operator that is used in running the algorithm\n", "# (Algorithm circuits are wrapped in a gate to be appear in composition as a block\n", "# so we have to decompose() the op to see it expanded into its component gates.)\n", "problem.grover_operator.decompose().draw(output='mpl')" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "Then, we specify a backend and call the `run` method of `Grover` with a backend to execute the circuits. The returned result type is a `GroverResult`. \n", "\n", "If the search was successful, the `oracle_evaluation` attribute of the result will be `True`. In this case, the most sampled measurement, `top_measurement`, is one of the \"good states\". Otherwise, `oracle_evaluation` will be False.\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 2, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Result type: \n", "\n", "Success!\n", "Top measurement: 11\n" ] } ], "source": [ "from qiskit import Aer\n", "from qiskit.utils import QuantumInstance\n", "from qiskit.algorithms import Grover\n", "\n", "aer_simulator = Aer.get_backend('aer_simulator')\n", "grover = Grover(quantum_instance=aer_simulator)\n", "result = grover.amplify(problem)\n", "print('Result type:', type(result))\n", "print()\n", "print('Success!' if result.oracle_evaluation else 'Failure!')\n", "print('Top measurement:', result.top_measurement)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "In the example, the result of `top_measurement` is `11` which is one of \"good state\". Thus, we succeeded to find the answer by using `Grover`." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "markdown", "source": [ "### Using the different types of classes as the oracle of `Grover`\n", "In the above example, we used `QuantumCircuit` as the oracle of `Grover`. \n", "However, we can also use `qiskit.quantum_info.Statevector` as oracle.\n", "All the following examples are when $|11\\rangle$ is \"good state\"" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 3, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Result type: \n", "\n", "Success!\n", "Top measurement: 11\n" ] } ], "source": [ "from qiskit.quantum_info import Statevector\n", "oracle = Statevector.from_label('11')\n", "problem = AmplificationProblem(oracle, is_good_state=['11'])\n", "\n", "grover = Grover(quantum_instance=aer_simulator)\n", "result = grover.amplify(problem)\n", "print('Result type:', type(result))\n", "print()\n", "print('Success!' if result.oracle_evaluation else 'Failure!')\n", "print('Top measurement:', result.top_measurement)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "Internally, the statevector is mapped to a quantum circuit:" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 4, "outputs": [ { "data": { "text/plain": "
", "image/png": "iVBORw0KGgoAAAANSUhEUgAAAKoAAACFCAYAAADLjGNhAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAPyklEQVR4nO3deVxV5b7H8Q/sQEBKMXLAHACFGGQUHMpwOBIOdanUpDAxnLWbdW7DuVe7de1olpVmDnlur/TqTTuR0yk8pgYood4DGM4HExARJ1RU2Iyb5/7hcR8REBT2sPT3fr326yXPXns9vwVf17D32s9jo5RSCGHlbC1dgBBNIUEVmiBBFZogQRWaIEEVmiBBFZogQRWaIEEVmtCkoJ47d44XX3wRDw8PQkND6devHxs3bgTA2dn5tq/Ny8vD39//jgtraL06nY6goCD8/f0ZPXo0er3+rvswtalTp/LLL78AYDAYCA4OZuTIkRauSpsaDapSiujoaJ588klycnLIyMhg/fr1FBQUmKO+OhwdHfn11185dOgQ9vb2rFixwiJ1NMXevXvp27cvAIsXL8bHx8fCFWlXo0H9+eefsbe3Z+rUqca2bt268eqrr9ZZ9tNPP8Xf3x9/f38WLVpkbK+uruall17Cx8eHUaNGodfrAYiOjiY0NBQ/Pz9Wrlx5x8UPGDCA3377Dbi+x5o0aRJ+fn5ERkZSVlbWYB+lpaWMGDGCwMBA/P39+fbbbwFYu3Yt4eHhBAUFMWXKFAwGw237P3HiBI888gjdu3cnKCiIdu3a4enpydWrVzl69CheXl7odDoKCgr48ccfmThx4h1vo/gH1YjFixerWbNmNfh869atlVJKpaenK39/f1VSUqKuXbumfH19VWZmpsrNzVWASk1NVUopNWHCBPXxxx8rpZS6ePGiUkopvV6v/Pz8VFFRUZ31NtRfVVWVeuaZZ9SyZctUbm6u0ul0av/+/UoppUaPHq3WrFnTYB8JCQlq4sSJxnUWFxerI0eOqJEjR6rKykqllFLTpk1Tq1evVkopNWzYMHX69Ol664mOjla7du1SSikVERGhDhw4oJRS6pNPPlFfffWVUkqp559/XqWnp6ukpCQ1YsSIBn+XomF3fDE1Y8YMAgMDCQsLq9WemprKs88+S+vWrXF2dua5555j9+7dAHTp0oXHH38cgNjYWFJTUwH4/PPPCQwMpG/fvpw6dYrjx4832n9ZWRlBQUH07t2brl27Eh8fD4C7uztBQUEAhIaGkpeX12AfvXr1Yvv27bz99tvs3r2bNm3asHPnTjIyMggLCyMoKIidO3eSk5MDQGJiIm5ubvXWc/jwYeP58dGjR/H29gZg27ZtREVF8cMPP9C+fXtCQ0Ob+isW9XigsQX8/Pz4/vvvjT8vXbqUoqIievfu3eRObGxs6vycnJzMjh072LNnD05OTgwcOJDy8vJG13XjHPVWrVq1Mv5bp9NRVlbWYB9eXl5kZmaSmJjI7NmzGTJkCC4uLowfP5758+c3ebvKysooLy/HxcWFU6dO4erqir29PXq9nuLiYtzc3FiyZAlbtmwhMTGR8vJyrl69SmxsLGvXrm1yP6IJ56iDBw+mvLyc5cuXG9tunGPebMCAAWzatAm9Xk9paSkbN25kwIABAOTn57Nnzx4AvvnmG5544gmuXLmCi4sLTk5OHDt2jL1797bUNhk11EdhYSFOTk7Exsby5ptvkpmZyZAhQ0hISOD8+fMAXLp0iZMnT952/UeOHDFeIB09etT476SkJAYNGgTA/PnzKSgoIC8vj/Xr1zN48GAJ6V1oNKg2NjZs2rSJlJQU3N3dCQ8PZ/z48SxYsKDWciEhIcTFxREeHk6fPn2YOHEiwcHBAHh7e7N06VJ8fHy4fPky06ZNIyoqiurqanx8fHjnnXeMV8ctqaE+Dh48aLxoev/995k9eza+vr588MEHREZGEhAQwNChQzlz5gwAw4cPp7CwsM76bz7sOzo6kpmZybFjx9i6dStRUVEtvj33Mxul5MbplhYSEsK+ffuws7OzdCn3DAmq0AT5CFVoggRVaIIEVWiCBFVoggRVaIIEVWiCBFVoggRVaIIEVWiCBFVoggRVaIIEVWiCBFVoggRVaIIEVWiCBFVoggRVaIIEVWhCo1+Xvp/8/We4dt7SVdzeg+3Be7ClqzA/CepNrp2HYssMqSUaIYd+oQkSVKEJElShCRJUoQkSVKEJElShCRJUoQkSVKEJElShCVYd1JqaGhYuXEjPnj1xcHAgMDCQlJQUvL29mTx5stnqMNQYWPnDm4x67xGemf0g769+niulRWbrX1h5UOPj45k7dy5Tpkxh69atjBkzhpiYGHJycsw6Jv76pA9JO7yZJa/uY91/XP+MdcG6cWbrX1jxZ/3r1q1j1apVJCcnExERAcCgQYPIzMxkw4YNhISEmK2WxL0riR36Lp0e9gBg0oiPGL+gB+cun6SDSzez1XE/s9o96rx584iKijKG9IYePXpgZ2dHQEAAcH1mwIiICLy8vOjVq5dxJpaWUlJWzPnifHp2/uce3M3VEyeHhzhRmNWifYmGWWVQCwoKOHToEKNHj67zXH5+Pn5+fsZZUKZMmcILL7xAdnY2X375JWPHjqWysrLRPmxsbOo8UlKS6yynr7gGQGvHNrXanR3aoi+/ehdb1zwpKcn11q7VR1NZbVABOnbsWKu9rKyMlJQU42G/qKiI1NRU41xT/fv3x83NjaSkpBarxanVgwCUll2p1V5SXoyTw0Mt1o+4PasMqqurKwDZ2dm12j/66CPOnDljvJDKz8+nQ4cOteaYcnd3b3TaHbg+x+utj4iIgXWWc3ZsS/u2XfntdKax7czFHPTlV/HoFHA3m9csERED661dq4+mssqLKQ8PDwICApg3bx7t2rWjc+fOJCQkkJiYCGD2WfCG953Mt8kLCOwxiIecHuZPiW/T2+spOrbrbtY67mdWuUe1tbXlu+++w8/Pj2nTpjFhwgRcXV2ZMWMGOp3OeCHVtWtXzp07R0VFhfG1ubm5dOvWslfiYwe9Q1+fp5m5OIyYDzpTU2PgnRdlUjNz0tT0PePGjSMrK4sDBw4Y2yIjI4mOjmb69OmkpaUxatQo8vLysLe3v+P1p6+3/q+itH0Ueo+1dBXmZ5WH/oakp6fXmeFvxYoVxMXFsWjRIuzt7Vm3bt1dhVRYN80EtaSkhOzsbKZPn16r3cPDg127dlmoKmEumgmqs7MzBoPB0mUIC7HKiykhbiVBFZogQRWaIEFtpth53dmRUfc91Ybaxd2RoFqRakOVpUuwWpq56teyrBMprNo2m5NnD2NjY0sfn5G8NXYVWSeSeWvl7/i3MV/zPz/9J1dKL/DmmFV89O34f75YKcqr9CyftZ8enYMstg2WJkE1sZzCA/zhv5/itedWMCg4BqVqOJa/z/h8TY2B/zuWyIpZ+9Hp7HCwd2JAwPPG5z9LmEzumYN0bf+YJcq3GhJUE/th7wr6+j7NU2FxxrZAz4G1lpk0fEGd+10B1m6fS9aJZBbPTMPezsHElVo3OUdtJp3OjuqauueW1YYqHtDZcfZyHo+6ejX4elsbWx5p26VO+0/pq9mc9gXz4rfSprVri9asRbJHbaaOLt0pLPqtVltZRQmXr52l08MedHTpzumi4w2voJ473TOyt7Ns82t8OOkn3Fw9TVG25sgetZkie8eRuG8lB3N2Y6gxcE1/mWWbX6N7x170cAtmRN8p7Dmyhe0Za6isrqCiqoysE8kNri+n8AB/XPsCb8es4bGu4ebbECsne9RmGhLyEhVVepZsnMG54pM42jsT4BHB3Ff+gk73AJ5ugfwxPpFVf53N0k2v8oDOjn6+z9Q5T70h9dAGSsuvMO9/Y2q1fz5zD+6deplhi6yTpu5HNTW5H9V6yaFfaIIEVWiCBFVoggRVaIIEVWiCBFVogryPaiLLt7xOdkE6PTqHMONfFlu6HM2TPaoJHC/IpKyihM+m76a6upK/n/qbpUvSPNmjmsDR/L2Eeg0FIKTn7zhycg/eXcLqLJd1Ipn3Vj+LR6dAzl7KxdMtiP+asNnc5WqCBNUESsqK6dTu+qC/rR3akHfucL3L9XJ/Eu8u4Xw4aRsL1r1M/PD5LdK/pWfJNsUM2BJUE2jt0AZ9xfWxU0srruLs2Lbe5c5cyjEG+sKVU7i26dwi/d+Ls2TLOaoJ+Hbrx/7jOwHYf3wHPl37YjBUc/nauVrLnTx7mG4d/TDUGLCxkT/F7chvxwR6PhqCnZ0Dry8bgK2tjse6hnP2ch5f/3V2reXyzh2mewc/qqorKC45z8WrZyxUsfWTu6duYsq7p3Yf+B5nJxeCezTv5K0pd09Z+i4wU9zhJeeoZnLzF/bEnZND/z3uXhkgQ4IqmsySA2TIoV9oYoAMCep9TisDZFj1od9aJu29l908QIb9A61oZefY4AAZDvZOtdpvDJAx95W/mHyADKveo8bHx7NhwwbmzJlDaGgoaWlpxMTEcOHCBd544w2z1ZH063q2pC0lpzCL8io92xZUm63v5mrKABk93IIbfH1jA2QsnpFmlgEyrDao1jRpr7OjC0/3m05lVRmffa+tPfm9MkCG1R76mzpp77vvvouXlxe2trYkJCSYpJYw76cYHBxjnF1aS+6VATKsco96Y9Le119/vc5zt07aGxUVRVxcHK+88oq5y9SEe2WADKsNKjQ8ae+wYcOMbf3797+rPuqb2Xjh1KQG/0DWIiUlmbCYQbdd5tbtGN5nEsP7TGpw+eAegwmemVanPdBzYJ3z8Zcj3+PlyPeaXeMNTf0E3yoP/U2dtFfcP6xyj2qOSXvr+59s6Zs5miIiYiBq+e33QpbejqbUeKesco/a1El7zcVQY6Cyqpyq6koAKqvKqawqv6NpvEXzWOUeFcDLy4ukpKRabePGjcPX1xdHR0ez1rIjYw0L/zzB+POIf7/e/5o/5MpU6GZitUGtT32T9s6ZM4evv/6aCxcucPDgQWbNmkVKSgqeni33/t5TYXG1hjYX5meVh/763Ji099Y3+ufOnUtBQQEVFRVcvHiRgoKCFg3p/ajoymmWbZ7F0fx9vPZFf2YtfYLlW+q+VWhOmtmjyqS95pORvZ1Qr6F0aNuNj6f8jL2dA/O/eYncMwctNpiwZoIqTKO+sQUedGrHzOglOLZyNi6ns7XD1lZnsTo1c+gXpnFjbIFPpiUT4BHBvz63jPLK0lohzSk8wJXSC3Tr4GuxOiWo97lbxxYoLrmAh1ug8fmr+kt8sWkmvx/9laVKBCSo971bxxbIPL6d0J7XhyMyGKr5cF0sk0cupN1DHRtZk2lJUO9zt44tkHl8B16P9gYg5cB3ZJ/6G3/68S1+v3wgR/L2WKxO+V7/TSz90WNTmPp7/SlZfyYicMzdvfgfTPG9ftmjilqaG1JTkbenbvJge0tX0Lim1Gjp7TBF/3LoF5ogh36hCRJUoQkSVKEJElShCRJUoQkSVKEJElShCRJUoQkSVKEJElShCRJUoQkSVKEJElShCRJUoQkSVKEJElShCRJUoQkSVKEJ/w8fHMbJ1gzntQAAAABJRU5ErkJggg==\n" }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "problem.grover_operator.oracle.decompose().draw(output='mpl')" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "Qiskit allows for an easy construction of more complex oracles:\n", "* `PhaseOracle`: for parsing logical expressions such as `'~a | b'`. This is especially useful for solving 3-SAT problems.\n", "\n", "Here we'll use the `PhaseOracle` for the simple example of finding the state $|11\\rangle$, which corresponds to `'a & b'`." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 5, "outputs": [ { "data": { "text/plain": "
", "image/png": "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\n" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from qiskit.circuit.library.phase_oracle import PhaseOracle\n", "from qiskit.exceptions import MissingOptionalLibraryError\n", "\n", "# `Oracle` (`PhaseOracle`) as the `oracle` argument\n", "expression = '(a & b)'\n", "try:\n", " oracle = PhaseOracle(expression)\n", " problem = AmplificationProblem(oracle)\n", " display(problem.grover_operator.oracle.decompose().draw(output='mpl'))\n", "except MissingOptionalLibraryError as ex:\n", " print(ex)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "You can observe, that this oracle is actually implemented with three qubits instead of two!\n", "\n", "That is because the `PhaseOracle` is not a phase-flip oracle (which flips the phase of the good state) but a bit-flip oracle. This means it flips the state of an auxiliary qubit if the other qubits satisfy the condition.\n", "For Grover's algorithm, however, we require a phase-flip oracle. To convert the bit-flip oracle to a phase-flip oracle we sandwich the controlled-NOT by $X$ and $H$ gates, as you can see in the circuit above.\n", "\n", "**Note:** This transformation from a bit-flip to a phase-flip oracle holds generally and you can use this to convert your oracle to the right representation." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "markdown", "source": [ "### Amplitude amplification\n", "Grover's algorithm uses Hadamard gates to create the uniform superposition of all the states at the beginning of the Grover operator $\\mathcal{Q}$. If some information on the good states is available, it might be useful to not start in a uniform superposition but only initialize specific states. This, generalized, version of Grover's algorithm is referred to _Amplitude Amplification_.\n", "\n", "In Qiskit, the initial superposition state can easily be adjusted by setting the `state_preparation` argument.\n", "\n", "#### State preparation\n", "\n", "A `state_preparation` argument is used to specify a quantum circuit that prepares a quantum state for the start point of the amplitude amplification.\n", "By default, a circuit with $H^{\\otimes n}$ is used to prepare uniform superposition (so it will be Grover's search). The diffusion circuit of the amplitude amplification reflects `state_preparation` automatically." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 6, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "state preparation circuit:\n" ] }, { "data": { "text/plain": "
", "image/png": "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\n" }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "\n", "# Specifying `state_preparation` \n", "# to prepare a superposition of |01>, |10>, and |11>\n", "oracle = QuantumCircuit(3)\n", "oracle.h(2)\n", "oracle.ccx(0,1,2)\n", "oracle.h(2)\n", "\n", "theta = 2 * np.arccos(1 / np.sqrt(3))\n", "state_preparation = QuantumCircuit(3)\n", "state_preparation.ry(theta, 0)\n", "state_preparation.ch(0,1)\n", "state_preparation.x(1)\n", "state_preparation.h(2)\n", "\n", "# we only care about the first two bits being in state 1, thus add both possibilities for the last qubit\n", "problem = AmplificationProblem(oracle, state_preparation=state_preparation, is_good_state=['110', '111'])\n", "\n", "# state_preparation\n", "print('state preparation circuit:')\n", "problem.grover_operator.state_preparation.draw(output='mpl')" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": 7, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Success!\n", "Top measurement: 111\n" ] } ], "source": [ "grover = Grover(quantum_instance=aer_simulator)\n", "result = grover.amplify(problem)\n", "print('Success!' if result.oracle_evaluation else 'Failure!')\n", "print('Top measurement:', result.top_measurement)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "#### Full flexibility\n", "\n", "For more advanced use, it is also possible to specify the entire Grover operator by setting the `grover_operator` argument. This might be useful if you know more efficient implementation for $\\mathcal{Q}$ than the default construction via zero reflection, oracle and state preparation.\n", "\n", "The `qiskit.circuit.library.GroverOperator` can be a good starting point and offers more options for an automated construction of the Grover operator. You can for instance \n", "* set the `mcx_mode` \n", "* ignore qubits in the zero reflection by setting `reflection_qubits`\n", "* explicitly exchange the $\\mathcal{S_f}, \\mathcal{S_0}$ and $\\mathcal{A}$ operations using the `oracle`, `zero_reflection` and `state_preparation` arguments" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "markdown", "source": [ "For instance, imagine the good state is a three qubit state $|111\\rangle$ but we used 2 additional qubits as auxiliary qubits. " ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 8, "outputs": [ { "data": { "text/plain": "
", "image/png": "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\n" }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from qiskit.circuit.library import GroverOperator, ZGate\n", "\n", "oracle = QuantumCircuit(5)\n", "oracle.append(ZGate().control(2), [0, 1, 2])\n", "oracle.draw(output='mpl')" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "Then, per default, the Grover operator implements the zero reflection on all five qubits." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 9, "outputs": [ { "data": { "text/plain": "
", "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmEAAAENCAYAAABHK7L3AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAA8lUlEQVR4nO3de1TVdb7/8efeoCJK5mWMBjAsmlDEC15HS5mjlnPmN4mXrJW5CGvsApysHLUZskjPOFMNzKoUm/Fk05CX8lKd4tjFRMvsIgIzXig1DDXLUsZB8QLs/fuD3MrI1f2Fz3ezX4+1XAs/fD/7+95vP7x9871th9vtdiMiIiIiLcppOgARERERf6QmTERERMQANWEiIiIiBqgJExERETFATZiIiIiIAWrCRERERAxQEyYiIiJigJowEREREQMa1YR9++233H777Vx99dUMHDiQn/70p6xbtw6Ajh071jt3//799OnTp8mB1fW6AQEB9O/fnz59+nDLLbdQXl5+yfsQERERMaXBJsztdpOQkMDIkSP58ssvycvLY+XKlRw8eLAl4rtI+/btKSgoYMeOHbRt25YlS5YYiUNERETEGw02Ye+//z5t27bl3nvv9YxdddVVpKamXrRtRkYGffr0oU+fPvzpT3/yjFdWVjJ16lR69erF5MmTKS8vByAhIYGBAwcSExPDn//85yYHf8MNN7B3714Aqqqq+NWvfkVMTAw33ngjp06dqnMfJ0+e5Be/+AX9+vWjT58+rFq1CoDs7GyGDBlC//79ueeee6iqqqp3//v27eNHP/oRkZGR9O/fny5dunDNNdfwr3/9q8nvRURERPxLg03Yzp07iYuLa/CF8vLyWLZsGZ988gkff/wxf/nLX8jPzwfg888/5/7772f37t1cdtllLF68GIAXXniBvLw8tm3bxjPPPMPRo0cbHXhlZSX/93//R2xsLAB79uwhOTmZnTt3cvnll7NmzZo697F+/Xp+/OMfU1hYyI4dOxg3bhy7d+9m1apVbNmyhYKCAgICAnj55ZcB+M///E++/vrri2K45ppruP766/nb3/5GQUEBffv25bXXXuOyyy5r9PsQERER/9TkC/OTk5Pp168fgwcPrjH+4YcfMmHCBDp06EDHjh2ZOHEiH3zwAQARERGMGDECgDvuuIMPP/wQgGeeeYZ+/foxbNgwDhw4wJ49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\n" }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grover_op = GroverOperator(oracle, insert_barriers=True)\n", "grover_op.decompose().draw(output='mpl')" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "But we know that we only need to consider the first three:" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 10, "outputs": [ { "data": { "text/plain": "
", "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmEAAAENCAYAAABHK7L3AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAA2GklEQVR4nO3dfVzV9f3/8ccBVETJTGcUYFg0QSURLxNTNrVs+36T1Fm3zBtiZTPwmzZLa6ShfufWluzWUnRz2hqp5FXbrzFXmWiZViKwecGmhQMdZilzJF5wcX5/kCf5ilx4Pp7353Ce99vN2/B9Pu/zeZ1Xb157+bk6DqfT6UREREREPMrPdAAiIiIivkhNmIiIiIgBasJEREREDFATJiIiImKAmjARERERA9SEiYiIiBigJkxERETEADVhIiIiIgY0qwn7/PPPeeihh7j11lvp378/d955J5s3bwagY8eOjc49cuQIffr0aXFgV3pff39/YmNj6dOnDz/4wQ+orKy86n2IiIiImNJkE+Z0OklMTGT48OF89tln5OXlsW7dOo4ePeqJ+C7Tvn17CgoK2LdvH23btmX58uVG4hARERFxR5NN2HvvvUfbtm354Q9/6Bq75ZZbmDFjxmXbLlmyhD59+tCnTx9++ctfusarq6uZNGkS0dHRTJgwgcrKSgASExPp378/vXv35te//nWLg7/rrrs4fPgwADU1NTz22GP07t2bu+++m7Nnz15xH2fOnOH73/8+ffv2pU+fPmRnZwOQlZXFoEGDiI2N5fHHH6empqbR/X/66ad861vfIiIigtjYWG644QZuu+02/vOf/7T4s4iIiIhvabIJ279/P3FxcU2+UV5eHqtXr+ajjz5i9+7d/OY3vyE/Px+Av//97zzxxBMcPHiQ6667jmXLlgGwatUq8vLy2LNnDy+//DInT55sduDV1dX8+c9/JiYmBoBDhw6RkpLC/v37uf7669m4ceMV97FlyxZuvvlmCgsL2bdvH2PGjOHgwYNkZ2ezc+dOCgoK8Pf35/XXXwfge9/7Hv/6178ui+G2225j2LBh/P73v6egoIA77riDN998k+uuu67Zn0NERER8U4svzE9JSaFv374MHDiw3vgHH3zA/fffT4cOHejYsSPjxo3j/fffByA8PJz4+HgAHn74YT744AMAXn75Zfr27cuQIUMoLS3l0KFDTe7/7NmzxMbGMmDAALp3784jjzwCQI8ePYiNjQWgf//+HDly5Ir7iImJ4Z133mHOnDm8//77dOrUia1bt5KXl8fAgQOJjY1l69atfPbZZwDk5ORw8803NxjP/v37XdejHTx4kJ49e7YgmyIiIuKrApraoHfv3q6jSgBLly7lyy+/ZMCAAc3eicPhuOzvubm5vPvuu+zatYugoCASEhI4d+5ck+918Zqw/6tdu3aun/39/Tl79uwV9/Htb3+bvXv3kpOTQ1paGiNHjqRz584kJSWxePHiZn+us2fPcu7cOTp37kxpaSldu3albdu2zZ4vIiIivqvJI2Hf/e53OXfuHJmZma6xi9d0Xequu+7izTffpLKykjNnzrB582buuusuAEpKSti1axcAa9asYdiwYZw+fZrOnTsTFBREUVERu3fvtuozuVxpH//6178ICgri4Ycf5umnn2bv3r2MHDmSDRs2cOLECQBOnTrFP//5z0bf/8CBA0RHRwN1R8Eu/iwiIiLSlCabMIfDwZtvvsn27dvp0aMHgwYNIikpiZ/97Gf1touLi2PKlCkMGjSIwYMH8+ijj9KvXz8AevbsydKlS4mOjqa8vJzp06czZswYqquriY6OZu7cuQwZMsTyD3elffztb39zXYCfnp5OWloavXr1YtGiRdx9993ccccdjB49mrKyMuDK14Rdeiqyffv27N27l6KiIss/h4iIiLQ+DqfT6TQdhIiIiIiv0RPzRURERAxQEyYiIiJigJowEREREQPUhImIiIgYoCZMRERExAA1YSIiIiIGqAkTERERMUBNmIiIiIgBasJEREREDFATJiIiImKAmjARERERA9SEiYiIiBgQYDoA8Q1FRUVNbvPKK6+Qmpra6DZRUVFWhdRqKdci4g7VEM/RkTCxjaVLl5oOwWco1yLiDtUQa6gJExERETFATZiIiIiIAWrCxDY2bNhgOgSfoVyLiDtUQ6yhJkxERETEADVhYhsTJkwwHYLPUK5FxB2qIdbQIyrE523aA8fKzew7tDOMG2Bm3yb86O8HKKyo8Ph++wYH81LPXh7fr7SMqfUBWiPewlS9vla1Wk2Y+Lxj5fDpCdNR+IbCigp2lJ8yHYbYlNaHNKW11WudjhTbSElJMR2Cz1CuRcQdqiHWUBMmttHU05fFOsq1iLhDNcQaasLENoYPH246BJ+hXIuI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PP300wwdOpSePXsSFBTk2kdD8y/Kzs5mypQpLF++nHvvvZfJkyezatUqYmNjXY+x2LZtG59++im33XYbERER7N69myeeeIKXXnrJs8lqZaKjo02H4DOUaxFxh2qINWx/TZg3SEhI0DVhTdA1Bp6jXIuIO1RDPMd2R8JEREREfIHtrgnzRro2zBoJCQmmQ/AZyrWIuEM1xBo6HSke0ZzD282hw9tNU65FxB2qIZ6j05FiG9OnTzcdgs9QrkXEHaoh1lATJrah07qeo1yLiDtUQ6yhJkxERETEADVhIiIiIgaoCRPbaOqZM2Id5VpE3KEaYg01YWIbb7zxhukQfIZyLSLuUA2xhpowsY358+ebDsFnKNci4g7VEGuoCRMRERExQE2YiIiIiAFqwsQ2li1bZjoEn6Fci4g7VEOsoSZMbKN3796mQ/AZyrWIuEM1xBpqwsQ2RowYYToEn6Fci4g7VEOsoSZMRERExIAA0wGIb4iKimpym/nz5zdrO2mcci0i7lAN8RyH0+l0mg5CRERExNfodKSIiIiIAWrCRERERAxQEyYiIiJigJowEREREQPUhImIiIgYoCZMRERExAA1YSIiIiIGqAkTERERMUBNmIiIiIgBasJEREREDPj/fTRBVcuNatcAAAAASUVORK5CYII=\n" }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "grover_op = GroverOperator(oracle, reflection_qubits=[0, 1, 2], insert_barriers=True)\n", "grover_op.decompose().draw(output='mpl')" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "### Dive into other arguments of `Grover`\n", "`Grover` has arguments other than `oracle` and `state_preparation`. We will explain them in this section.\n", "\n", "#### Specifying `good_state`\n", "`good_state` is used to check whether the measurement result is correct or not internally. It can be a list of binary strings, a list of integer, `Statevector`, and Callable. If the input is a list of bitstrings, each bitstrings in the list represents a good state. If the input is a list of integer, each integer represent the index of the good state to be $|1\\rangle$. If it is a `Statevector`, it represents a superposition of all good states.\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 11, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "# a list of binary strings good state\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", "good_state = ['11', '00']\n", "problem = AmplificationProblem(oracle, is_good_state=good_state)\n", "print(problem.is_good_state('11'))" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": 12, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "# a list of integer good state\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", "good_state = [0, 1]\n", "problem = AmplificationProblem(oracle, is_good_state=good_state)\n", "print(problem.is_good_state('11'))" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": 13, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "from qiskit.quantum_info import Statevector\n", "\n", "# `Statevector` good state\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", "good_state = Statevector.from_label('11')\n", "problem = AmplificationProblem(oracle, is_good_state=good_state)\n", "print(problem.is_good_state('11'))" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": 14, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n" ] } ], "source": [ "# Callable good state\n", "def callable_good_state(bitstr):\n", " if bitstr == \"11\":\n", " return True\n", " return False\n", "\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", "problem = AmplificationProblem(oracle, is_good_state=good_state)\n", "print(problem.is_good_state('11'))" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "#### The number of `iterations`\n", "\n", "The number of repetition of applying the Grover operator is important to obtain the correct result with Grover's algorithm. The number of iteration can be set by the `iteration` argument of `Grover`. The following inputs are supported:\n", "* an integer to specify a single power of the Grover operator that's applied\n", "* or a list of integers, in which all these different powers of the Grover operator are run consecutively and after each time we check if a correct solution has been found\n", "\n", "Additionally there is the `sample_from_iterations` argument. When it is `True`, instead of the specific power in `iterations`, a random integer between 0 and the value in `iteration` is used as the power Grover's operator. This approach is useful when we don't even know the number of solution.\n", "\n", "For more details of the algorithm using `sample_from_iterations`, see [4].\n", "\n", "**References:**\n", "\n", "[4]: Boyer et al., Tight bounds on quantum searching [arxiv:quant-ph/9605034](https://arxiv.org/abs/quant-ph/9605034)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 15, "outputs": [], "source": [ "# integer iteration\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", "problem = AmplificationProblem(oracle, is_good_state=['11'])\n", "grover = Grover(iterations=1)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": 16, "outputs": [], "source": [ "# list iteration\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", "problem = AmplificationProblem(oracle, is_good_state=['11'])\n", "grover = Grover(iterations=[1, 2, 3])" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": 17, "outputs": [], "source": [ "# using sample_from_iterations\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", "problem = AmplificationProblem(oracle, is_good_state=['11'])\n", "grover = Grover(iterations=[1, 2, 3], sample_from_iterations=True)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "When the number of solutions is known, we can also use a static method `optimal_num_iterations` to find the optimal number of iterations. Note that the output iterations is an approximate value. When the number of qubits is small, the output iterations may not be optimal.\n" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 18, "outputs": [ { "data": { "text/plain": "12" }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "iterations = Grover.optimal_num_iterations(num_solutions=1, num_qubits=8)\n", "iterations" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "#### Applying `post_processing`\n", "We can apply an optional post processing to the top measurement for ease of readability. It can be used e.g. to convert from the bit-representation of the measurement `[1, 0, 1]` to a DIMACS CNF format `[1, -2, 3]`." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 19, "outputs": [ { "data": { "text/plain": "[1, -2, 3]" }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def to_DIAMACS_CNF_format(bit_rep):\n", " return [index+1 if val==1 else -1 * (index + 1) for index, val in enumerate(bit_rep)]\n", "\n", "oracle = QuantumCircuit(2)\n", "oracle.cz(0, 1)\n", "problem = AmplificationProblem(oracle, is_good_state=['11'], post_processing=to_DIAMACS_CNF_format)\n", "problem.post_processing([1, 0, 1])" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "## Grover's algorithm examples\n", "\n", "This notebook has examples demonstrating how to use the Qiskit [Grover](https://qiskit.org/documentation/stubs/qiskit.algorithms.Grover.html) search algorithm, with different oracles." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 20, "outputs": [], "source": [ "import pylab\n", "import numpy as np\n", "from qiskit import Aer\n", "from qiskit.utils import QuantumInstance\n", "from qiskit.tools.visualization import plot_histogram\n", "from qiskit.algorithms import Grover, AmplificationProblem\n", "from qiskit.circuit.library.phase_oracle import PhaseOracle" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "### Finding solutions to 3-SAT problems\n", "\n", "Let's look at an example 3-Satisfiability (3-SAT) problem and walk-through how we can use Quantum Search to find its satisfying solutions. 3-SAT problems are usually expressed in [Conjunctive Normal Forms (CNF)](https://en.wikipedia.org/wiki/Conjunctive_normal_form) and written in the [DIMACS-CNF](http://www.satcompetition.org/2009/format-benchmarks2009.html) format. For example:" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 21, "outputs": [], "source": [ "input_3sat_instance = '''\n", "c example DIMACS-CNF 3-SAT\n", "p cnf 3 5\n", "-1 -2 -3 0\n", "1 -2 3 0\n", "1 2 -3 0\n", "1 -2 -3 0\n", "-1 2 3 0\n", "'''" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "The CNF of this 3-SAT instance contains 3 variables and 5 clauses:\n", "\n", "$(\\neg v_1 \\vee \\neg v_2 \\vee \\neg v_3) \\wedge (v_1 \\vee \\neg v_2 \\vee v_3) \\wedge (v_1 \\vee v_2 \\vee \\neg v_3) \\wedge (v_1 \\vee \\neg v_2 \\vee \\neg v_3) \\wedge (\\neg v_1 \\vee v_2 \\vee v_3)$\n", "\n", "It can be verified that this 3-SAT problem instance has three satisfying solutions:\n", "\n", "$(v_1, v_2, v_3) = (T, F, T)$ or $(F, F, F)$ or $(T, T, F)$\n", "\n", "Or, expressed using the DIMACS notation:\n", "\n", "`1 -2 3`, or `-1 -2 -3`, or `1 2 -3`.\n", "\n", "With this example problem input, we then create the corresponding `oracle` for our `Grover` search. In particular, we use the `PhaseOracle` component, which supports parsing DIMACS-CNF format strings and constructing the corresponding oracle circuit." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 22, "outputs": [], "source": [ "import os\n", "import tempfile\n", "from qiskit.exceptions import MissingOptionalLibraryError\n", "\n", "fp = tempfile.NamedTemporaryFile(mode='w+t', delete=False)\n", "fp.write(input_3sat_instance)\n", "file_name = fp.name\n", "fp.close()\n", "oracle = None\n", "try:\n", " oracle = PhaseOracle.from_dimacs_file(file_name)\n", "except MissingOptionalLibraryError as ex:\n", " print(ex)\n", "finally:\n", " os.remove(file_name)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "The `oracle` can now be used to create an Grover instance:" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 23, "outputs": [], "source": [ "problem = None\n", "if oracle is not None:\n", " problem = AmplificationProblem(oracle, is_good_state=oracle.evaluate_bitstring)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "We can then configure the backend and run the Grover instance to get the result:" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 24, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "011\n" ] } ], "source": [ "backend = Aer.get_backend('aer_simulator')\n", "quantum_instance = QuantumInstance(backend, shots=1024)\n", "grover = Grover(quantum_instance=quantum_instance)\n", "result = None\n", "if problem is not None:\n", " result = grover.amplify(problem)\n", " print(result.assignment)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "As seen above, a satisfying solution to the specified 3-SAT problem is obtained. And it is indeed one of the three satisfying solutions.\n", "\n", "Since we used the `'aer_simulator'`, the complete measurement result is also returned, as shown in the plot below, where it can be seen that the binary strings `000`, `011`, and `101` (note the bit order in each string), corresponding to the three satisfying solutions all have high probabilities associated with them." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 25, "outputs": [ { "data": { "text/plain": "
", "image/png": "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f+W92NqUNHdzO9tcMm/ePAYPHszgwYMZNGgQzzzzTN1zfvWrX1FUVMTAgQM5++yz2bp1a6pORzLchAkTuPbaa+tqlYlycnJ46623qKioYN68eSxatCgNEUqyJOtiq9bKlSt58803k36xpaS5G2tJc8nAgQMpKyuru/902WWXUV1dTWVlJffeey9lZWUsWrSImpoapk6dmo7TkyTJz89n9erVdY8rKirIz89vtEx1dTX//Oc/6dy5M3PnzuWGG26gsLCQu+++m4kTJzJ58uTtnrv33ntzzDHHMH369OSfjGSFpi62ADZv3sxpp53G3XffTceOHZMaS8oXoZbMkdhcAtQ1lwwYMKCuzLPPPsuECROA0Fxy1VVX4e7stddedWW2bt263f2n6upqtmzZwh577MFnn31Gjx49UnNCkhKHHXYYy5cvp7y8nPz8fKZOncpjjz22XZlx48bx+9//nmHDhvHUU09x7LHHYma88sordWUmTJhA+/btueqqq/joo4/YY4892HvvvdmyZQszZsz4yv0syW7NudgqKCj4ysXWU089xQ033MDGjRtp06YNe+65J1dddRXbtm3jtNNO45xzzuHUU09N+nkoae7GGmoumTt3bqNlEptLunTpwty5c7noootYtWoVjz76KLm5ueTn53P99dfTq1cv2rVrx+jRoxk9enRKz0uSKzc3l8mTJzNmzBhqamq46KKLKCoq4pZbbqG4uJhx48Zx8cUXc95559G3b1/22WefHbY2fPjhh1xwwQXU1NTwxRdfcOaZZ3LSSSel6IwkFZJxseXuXHzxxfTv35/rrrsuJeehpCk7raSkhMWLF/POO+9wwQUXcMIJJ7BlyxaeffZZysvL2XvvvTnjjDOYMmUK5557brrDlVY0duxYxo4du922W2+9te73PffckyeffLLJY9S2YAAccsghvPnmm60ao2SWZFxsvfrqqzz66KMcfPDBDB48GICJEyd+5b3ZqueRtCNLxmtJc0mi/v370759exYtWkR5eTm9e/dm3333BeDUU0/ltddeU9IUkVa/2Bo+fHhd79pUUUeg3Vhic8nnn3/O1KlTGTdu3HZlaptLgO2aS8rLy6murgZg1apV/OMf/6CwsJBevXrx+uuv89lnn+HuvPTSS/Tv3z8p8Sej5+9FF11E165dGThwYFJiFpHspqS5G0tsLunfvz9n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\n" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if result is not None:\n", " display(plot_histogram(result.circuit_results[0]))" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "## Boolean Logical Expressions\n", "\n", "Qiskit's `Grover` can also be used to perform Quantum Search on an `Oracle` constructed from other means, in addition to DIMACS. For example, the `PhaseOracle` can actually be configured using arbitrary Boolean logical expressions, as demonstrated below." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": 26, "outputs": [ { "data": { "text/plain": "
", "image/png": "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2LBh5csSqdbb3w4rnb+bo446ilWrVtG6dWvOOuusSA+sUrG/bZKq/f3ejzvuOD7++GOefPLJyA5kr7jiClq0aEGPHj3S8p5ifxNApL+bH//4x1x00UUMGzYssvIqaVaDir7omzdv5pVXXmHixIkMHDiQb775hqeeeiqhL0ysbt260aBBAxYtWgTAlVdeybx585g+fTqNGzemS5cukb6ndJ19r169mvnz59O1a9eky1bR9i6zcuVKNm7cyPnnnw9EsyMvKiqiefPmjBs3jmnTpnHBBRewefNmnn32WYYOHbpX7KFDh/L3v/8dgBdeeIGTTz4Z5xwzZsyguLiY4uJiRo4cya9//Wt+/vOfY2ZceeWVNG7cmGOPPTbS7e2co2PHjqxatYrdu3eze/du1q9fn/IOK8xOMIyqfjePPvooF198cfnvJqoDK+cc9913H8899xyPP/54peVPdpuU/S2LGeXvfe7cuezYsYMLL7yQu+66K7ID2csvv5wpU6Yk+vGF1rdvX5YvX05RURHffvttpL+bbt26MWrUqEjLq6QZQipHQrFiv+hvvPEGHTp0YMiQIXz66aeceOKJzJgxI6EvTFFRUfkXe+XKlXzyySe0b98egHXr1gG+Fd/EiRP56U9/Gt0GIT1nEQAjR45k1KhRrF+/vjxOVDsWgA8++ICmTZvSsmXLpN53RTvykpIS5s+fzw033MBLL73E1KlTyc3NZfjw4eTl5TF69Gj+9a9/AX7ntnHjRjp16sQDDzyw35al7777Lk8++STvvfcehYWF9O7dm9dffz2y7Z2fn8+0adNo1qwZJ598Mu+++27KO6yynaBzjpUrV5Z/p6P83TRq1IhatWoxbNgwZs2aFfrzK1PZgdXMmTNZvHgxjRs35sEHH+TNN9+MZCdetk2aNWvGsmXLmDBhAmeccUakv/e5c+fStm1b3n77bS699NLIDmQHDhxIkyZNEt7GYWVlZfHII49w2mmn0a1bt0h/N2+99Vb5GfTrr78eTYHN7JCdjj32WAtj9+7d1qFDB1uxYoXt2rXLevbsaYsWLdprnUceecSuueYaMzN75pln7PzzzzczsxUrVtju3bvNzKy4uNhat25t69evt/fee8+6d+9u33zzjU2aNMkaNmxoTZs2td/+9rdmZnb77bfbK6+8YmZmO3bssPPOO886duxoffv2tc8++8zM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\n" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "expression = '(w ^ x) & ~(y ^ z) & (x & y & z)'\n", "try:\n", " oracle = PhaseOracle(expression)\n", " problem = AmplificationProblem(oracle, is_good_state=oracle.evaluate_bitstring)\n", " grover = Grover(quantum_instance=QuantumInstance(Aer.get_backend('aer_simulator'), shots=1024))\n", " result = grover.amplify(problem)\n", " display(plot_histogram(result.circuit_results[0]))\n", "except MissingOptionalLibraryError as ex:\n", " print(ex)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "In the example above, the input Boolean logical expression `'(w ^ x) & ~(y ^ z) & (x & y & z)'` should be quite self-explanatory, where `^`, `~`, and `&` represent the Boolean logical XOR, NOT, and AND operators, respectively. It should be quite easy to figure out the satisfying solution by examining its parts: `w ^ x` calls for `w` and `x` taking different values; `~(y ^ z)` requires `y` and `z` be the same; `x & y & z` dictates all three to be `True`. Putting these together, we get the satisfying solution `(w, x, y, z) = (False, True, True, True)`, which our `Grover`'s result agrees with." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "markdown", "source": [ "## Quantum Amplitude Estimation\n", "\n", "Given an operator $\\mathcal{A}$ that acts as\n", "\n", "$$\n", " \\mathcal{A}|0\\rangle = \\sqrt{1 - a}|\\Psi_0\\rangle + \\sqrt{a}|\\Psi_1\\rangle\n", "$$\n", "\n", "Quantum Amplitude Estimation (QAE) is the task of finding an estimate for the amplitude $a$ of the state $|\\Psi_1\\rangle$:\n", "\n", "$$\n", " a = |\\langle\\Psi_1 | \\Psi_1\\rangle|^2.\n", "$$\n", "\n", "This task has first been investigated by Brassard et al. [1] in 2000 and their algorithm uses a combination of the Grover operator \n", "\n", "$$\n", " \\mathcal{Q} = \\mathcal{A}\\mathcal{S}_0\\mathcal{A}^\\dagger\\mathcal{S}_{\\Psi_1}\n", "$$\n", "\n", "where $\\mathcal{S}_0$ and $\\mathcal{S}_{\\Psi_1}$ are reflections about the $|0\\rangle$ and $|\\Psi_1\\rangle$ states, respectively, and phase estimation. However this algorithm, called `AmplitudeEstimation` in Qiskit, requires large circuits and is computationally expensive. Therefore, other variants of QAE have been proposed, which we will showcase in this tutorial for a simple example.\n", "\n", "In our example, $\\mathcal{A}$ describes a Bernoulli random variable with (assumed to be unknown) success probability $p$:\n", "\n", "$$\n", " \\mathcal{A}|0\\rangle = \\sqrt{1 - p}|0\\rangle + \\sqrt{p}|1\\rangle.\n", "$$\n", "\n", "On a quantum computer, we can model this operator with a rotation around the $Y$-axis of a single qubit\n", "\n", "$$\n", "\\mathcal{A} = R_Y(\\theta_p), \\theta_p = 2\\sin^{-1}(\\sqrt{p}).\n", "$$\n", "\n", "The Grover operator for this case is particularly simple\n", "\n", "$$\n", "\\mathcal{Q} = R_Y(2\\theta_p),\n", "$$\n", "\n", "whose powers are very easy to calculate: $\\mathcal{Q}^k = R_Y(2k\\theta_p)$." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "markdown", "source": [ "We'll fix the probability we want to estimate to $p = 0.2$." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "p = 0.2" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "Now we can define circuits for $\\mathcal{A}$ and $\\mathcal{Q}$. " ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "import numpy as np\n", "from qiskit.circuit import QuantumCircuit\n", "\n", "\n", "class BernoulliA(QuantumCircuit):\n", " \"\"\"A circuit representing the Bernoulli A operator.\"\"\"\n", "\n", " def __init__(self, probability):\n", " super().__init__(1) # circuit on 1 qubit\n", "\n", " theta_p = 2 * np.arcsin(np.sqrt(probability))\n", " self.ry(theta_p, 0)\n", "\n", "\n", "class BernoulliQ(QuantumCircuit):\n", " \"\"\"A circuit representing the Bernoulli Q operator.\"\"\"\n", "\n", " def __init__(self, probability):\n", " super().__init__(1) # circuit on 1 qubit\n", "\n", " self._theta_p = 2 * np.arcsin(np.sqrt(probability))\n", " self.ry(2 * self._theta_p, 0)\n", "\n", " def power(self, k):\n", " # implement the efficient power of Q\n", " q_k = QuantumCircuit(1)\n", " q_k.ry(2 * k * self._theta_p, 0)\n", " return q_k" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "A = BernoulliA(p)\n", "Q = BernoulliQ(p)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "### Qiskit's Amplitude Estimation workflow" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "markdown", "source": [ "Qiskit implements several QAE algorithms that all derive from the `AmplitudeEstimator` interface. In the initializer we specify algorithm specific settings and the `estimate` method, which does all the work, takes an `EstimationProblem` as input and returns an `AmplitudeEstimationResult` object. Since all QAE variants follow the same interface, we can use them all to solve the same problem instance. \n", "\n", "Next, we'll run all different QAE algorithms. To do so, we first define the estimation problem which will contain the $\\mathcal{A}$ and $\\mathcal{Q}$ operators as well as how to identify the $|\\Psi_1\\rangle$ state, which in this simple example is just $|1\\rangle$." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "from qiskit.algorithms import EstimationProblem\n", "\n", "problem = EstimationProblem(\n", " state_preparation=A, # A operator\n", " grover_operator=Q, # Q operator\n", " objective_qubits=[0], # the \"good\" state Psi1 is identified as measuring |1> in qubit 0\n", ")" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "To execute circuits we'll use Qiskit's statevector simulator." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "from qiskit import BasicAer\n", "from qiskit.utils import QuantumInstance\n", "\n", "backend = BasicAer.get_backend(\"statevector_simulator\")\n", "quantum_instance = QuantumInstance(backend)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "### Canonical AE\n", "\n", "Now let's solve this with the original QAE implementation by Brassard et al. [1]." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "from qiskit.algorithms import AmplitudeEstimation\n", "\n", "ae = AmplitudeEstimation(\n", " num_eval_qubits=3, # the number of evaluation qubits specifies circuit width and accuracy\n", " quantum_instance=quantum_instance,\n", ")" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "With the algorithm defined, we can call the `estimate` method and provide it with the problem to solve." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "ae_result = ae.estimate(problem)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "The estimate is available in the `estimation` key:" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "print(ae_result.estimation)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "We see that this is not a very good estimate for our target of $p=0.2$! That's due to the fact the canonical AE is restricted to a discrete grid, specified by the number of evaluation qubits:" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "\n", "# plot estimated values\n", "gridpoints = list(ae_result.samples.keys())\n", "probabilities = list(ae_result.samples.values())\n", "\n", "plt.bar(gridpoints, probabilities, width=0.5 / len(probabilities))\n", "plt.axvline(p, color=\"r\", ls=\"--\")\n", "plt.xticks(size=15)\n", "plt.yticks([0, 0.25, 0.5, 0.75, 1], size=15)\n", "plt.title(\"Estimated Values\", size=15)\n", "plt.ylabel(\"Probability\", size=15)\n", "plt.xlabel(r\"Amplitude $a$\", size=15)\n", "plt.ylim((0, 1))\n", "plt.grid()\n", "plt.show()" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "To improve the estimate we can interpolate the measurement probabilities and compute the maximum likelihood estimator that produces this probability distribution:" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "print(\"Interpolated MLE estimator:\", ae_result.mle)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "We can have a look at the circuit that AE executes:" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "ae_circuit = ae.construct_circuit(problem)\n", "ae_circuit.decompose().draw(\n", " \"mpl\", style=\"iqx\"\n", ") # decompose 1 level: exposes the Phase estimation circuit!" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "from qiskit import transpile\n", "\n", "\n", "basis_gates = [\"h\", \"ry\", \"cry\", \"cx\", \"ccx\", \"p\", \"cp\", \"x\", \"s\", \"sdg\", \"y\", \"t\", \"cz\"]\n", "transpile(ae_circuit, basis_gates=basis_gates, optimization_level=2).draw(\"mpl\", style=\"iqx\")" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "### Iterative Amplitude Estimation\n", "\n", "See [2]." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "from qiskit.algorithms import IterativeAmplitudeEstimation\n", "\n", "iae = IterativeAmplitudeEstimation(\n", " epsilon_target=0.01, # target accuracy\n", " alpha=0.05, # width of the confidence interval\n", " quantum_instance=quantum_instance,\n", ")\n", "iae_result = iae.estimate(problem)\n", "\n", "print(\"Estimate:\", iae_result.estimation)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "The circuits here only consist of Grover powers and are much cheaper!" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "iae_circuit = iae.construct_circuit(problem, k=3)\n", "iae_circuit.draw(\"mpl\", style=\"iqx\")" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "### Maximum Likelihood Amplitude Estimation\n", "\n", "See [3]." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "from qiskit.algorithms import MaximumLikelihoodAmplitudeEstimation\n", "\n", "mlae = MaximumLikelihoodAmplitudeEstimation(\n", " evaluation_schedule=3, quantum_instance=quantum_instance # log2 of the maximal Grover power\n", ")\n", "mlae_result = mlae.estimate(problem)\n", "\n", "print(\"Estimate:\", mlae_result.estimation)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "### Faster Amplitude Estimation\n", "\n", "See [4]." ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "from qiskit.algorithms import FasterAmplitudeEstimation\n", "\n", "fae = FasterAmplitudeEstimation(\n", " delta=0.01, # target accuracy\n", " maxiter=3, # determines the maximal power of the Grover operator\n", " quantum_instance=quantum_instance,\n", ")\n", "fae_result = fae.estimate(problem)\n", "\n", "print(\"Estimate:\", fae_result.estimation)" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%%\n" } } }, { "cell_type": "markdown", "source": [ "### References\n", "\n", "[1] Quantum Amplitude Amplification and Estimation. Brassard et al (2000). https://arxiv.org/abs/quant-ph/0005055\n", "\n", "[2] Iterative Quantum Amplitude Estimation. Grinko, D., Gacon, J., Zoufal, C., & Woerner, S. (2019). https://arxiv.org/abs/1912.05559\n", "\n", "[3] Amplitude Estimation without Phase Estimation. Suzuki, Y., Uno, S., Raymond, R., Tanaka, T., Onodera, T., & Yamamoto, N. (2019). https://arxiv.org/abs/1904.10246\n", "\n", "[4] Faster Amplitude Estimation. K. Nakaji (2020). https://arxiv.org/pdf/2003.02417.pdf" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } }, { "cell_type": "markdown", "source": [ "## Send it after class\n", "\n", "Suppose we have a random variable $X$ described by a certain probability distribution over $N$ different outcomes, and a function $f:\\{0,\\dots,N\\} \\mapsto [0,1]$ defined over this distribution. How can we use quantum computers to evaluate\n", "1. Expectation value of $X$\n", "2. Variance of $X$\n", "Tip: The probability distribution is represented in our quantum computer by a quantum state over $n=āŒˆ\\log NāŒ‰$ qubits as $ \\left|\\psi\\right\\rangle = \\sum_{i=0}^{N-1} \\sqrt{p_i} \\left|i\\right\\rangle $. You can quantize the function $f$ using an ancilla qubit as $F: \\left|i\\right\\rangle \\left|0\\right\\rangle \\mapsto \\left|i\\right\\rangle \\left( \\sqrt{1-f(i) } \\left|0\\right\\rangle +\\sqrt{f(i) } \\left|1\\right\\rangle \\right)$" ], "metadata": { "collapsed": false, "pycharm": { "name": "#%% md\n" } } } ], "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.9" }, "nbdime-conflicts": { "local_diff": [ { "key": "language_info", "op": "add", "value": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.7" } } ], "remote_diff": [ { "key": "language_info", "op": "add", "value": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" } } ] } }, "nbformat": 4, "nbformat_minor": 5 }