{ "cells": [ { "cell_type": "code", "execution_count": 29, "id": "043d7c67-77f3-4195-918d-5b01b680451f", "metadata": {}, "outputs": [], "source": [ "from qiskit import *\n", "from qiskit.quantum_info import Operator\n", "from qiskit_aer import AerSimulator\n", "from qiskit.visualization import plot_histogram\n", "import numpy as np\n", "\n", "\n", "from IPython.display import Image" ] }, { "cell_type": "markdown", "id": "626d16af-6d0e-47b7-9271-c88899f30c73", "metadata": {}, "source": [ "# Grover's Algorithm" ] }, { "cell_type": "markdown", "id": "637c8466-3502-428b-9d50-a7a6da4de774", "metadata": {}, "source": [ "All images were stolen from the Qiskit textbook (link in your course's README page). The chapter on Grover's algorithm might even help with this exercise! \n", "\n", "In this notebook, we will use Qiskit to implement Grover's algorithm. As you learned in class, Grover's algorithm yields a quadratic speedup in unstructured search problems. Concretely, suppose we were given a list of $N$ items, represented as boxes below:" ] }, { "cell_type": "code", "execution_count": 5, "id": "0292d049-6d30-48bd-8ec7-db9e207420d0", "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Image(url=\"grover_list.png\", width=800, height=400)" ] }, { "cell_type": "markdown", "id": "ef7d284c-d717-4a2b-bee4-0b06dccc1b26", "metadata": {}, "source": [ "One item---the ``winner'' $\\omega$ coloured purple above---is the marked item we're searching for. Classically, finding $\\omega$ would require that we check $O(N)$ boxes. On a quantum computer, the same task can be accomplished in $O(\\sqrt{N})$ steps using Grover's amplitude amplification trick. At a high level, the algorithm involves three steps: state preparation, application of the oracle, and application of the diffuser:" ] }, { "cell_type": "code", "execution_count": 7, "id": "8aefa899-0cbc-46d2-a53a-62c949910f71", "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Image(url=\"grover_circuit_high_level.png\", width=1000, height=400)" ] }, { "cell_type": "markdown", "id": "6861b28c-c1f1-45f7-aa69-7c10774f1e52", "metadata": {}, "source": [ "The first step, state preparation, is a step you've seen before: We create a uniform superposition state $\\vert s\\rangle=H^{\\otimes n}\\ket{0}$ by applying Hadamards to all $n$ qubits initialized in $\\vert 0\\rangle$. Geometrically, we can visualize this state as a vector in a two-dimensional plane spanned by $\\vert\\omega\\rangle$, representing the marked element $\\omega$, and the state $\\ket{s'}$ obtained by subtracting $\\vert \\omega\\rangle$ from $\\vert s\\rangle$ and renormalizing. Concretely, we have \n", "\n", "$$\\vert s\\rangle=\\sin{\\theta}\\vert \\omega\\rangle + \\cos{\\theta}\\vert s'\\rangle,$$\n", "\n", "where the angle $\\theta$ is given by\n", "\n", "$$\\theta=\\mathrm{arcsin}\\langle s\\vert \\omega\\rangle=\\mathrm{arcsin}(1/\\sqrt{N}).$$\n", "\n", "Here, $N=2^n$ is the dimension of the $n$-qubit Hilbert space." ] }, { "cell_type": "code", "execution_count": 8, "id": "7e6a56ab-4d21-48b1-bdff-b662c0f1d3d0", "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Image(url=\"grover_step1.jpg\", width=1000, height=400)" ] }, { "cell_type": "markdown", "id": "74e6312d-ade1-4e80-8cb2-d5a4dbabdf6e", "metadata": {}, "source": [ "The oracle $U_f$ imparts a $\\pi$ phase shift (minus sign) to the marked element $\\vert \\omega\\rangle$, leaving all other states unchanged. This corresponds to a reflection of $\\vert s\\rangle$ about $\\vert s'\\rangle$. The negative amplitude of $\\vert \\omega\\rangle$ also implies that the average amplitude (indicated by a dashed line below) has been reduced from its original value of $1/\\sqrt{N}$. " ] }, { "cell_type": "code", "execution_count": 9, "id": "3616ec93-7cc3-4abf-8e2b-b17df8a75a26", "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Image(url=\"grover_step2.jpg\", width=1000, height=400)" ] }, { "cell_type": "markdown", "id": "b329f170-5c8b-4829-8d16-42270ab5fc33", "metadata": {}, "source": [ "Finally, we apply the diffuser $U_s=2\\vert s\\rangle\\langle s \\vert-1$, which implements an additional reflection about the state $\\vert s\\rangle$. The net effect of the oracle and diffuser is to rotate the initial state $\\vert s\\rangle$ towards the marked element $\\vert \\omega\\rangle$, effectively amplifying the amplitude of $\\vert \\omega\\rangle$ relative to all other unmarked states." ] }, { "cell_type": "code", "execution_count": 12, "id": "1c333685-bb80-4e1b-b3a2-13dc6673f64b", "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Image(url=\"grover_step3.jpg\", width=1000, height=400)" ] }, { "cell_type": "markdown", "id": "cbab24ca-c425-4234-8e6f-137cb08a89b1", "metadata": {}, "source": [ "For $k$ marked elements, the optimal number of repetitions is given by $$r=\\left\\lfloor\\frac{\\pi}{4}\\sqrt{\\frac{N}{k}}\\right\\rfloor,$$\n", "\n", "where $\\lfloor \\rfloor$ is the floor function. Note the $\\sqrt{N}$ scaling." ] }, { "cell_type": "markdown", "id": "cfe9c9a9-a46a-4f1c-9dfb-2854e1af7e9b", "metadata": {}, "source": [ "Now, let's implement both the oracle and diffuser in Qiskit. The function ```oracle``` below takes two arguments, ```n``` and ```marked_items```. The first is the number of qubits in the circuit, while the second is a list containing the indices of marked elements. To define the oracle, create an identity matrix of dimension $2^n$, and flip the signs of all diagonal elements contained in the list ```marked_items```." ] }, { "cell_type": "code", "execution_count": 32, "id": "22cf5f65-cee8-40d1-add1-76b9fae0f45c", "metadata": {}, "outputs": [], "source": [ "def oracle(n, marked_items):\n", " \n", " # Create an n-qubit quantum circuit\n", " qc = QuantumCircuit(n, name='Oracle')\n", "\n", " ### YOUR CODE GOES HERE - START\n", " \n", " \n", " ### YOUR CODE GOES HERE - END\n", "\n", " # This converts your matrix into an operator and appends it to the circuit. Do not alter this line.\n", " qc.unitary(Operator(oracle), range(n))\n", " \n", " return qc" ] }, { "cell_type": "markdown", "id": "7809fbf9-597e-4c52-9320-dccb31eb5607", "metadata": {}, "source": [ "The purpose of the diffuser is to reflect all amplitudes about the average amplitude. One way to do this (see Qiskit textbook) is to apply Hadamards to all qubits, followed by the oracle with only the state $\\vert0\\rangle^{\\otimes n}$ as the marked element, i.e. ```marked_items=[0]```. Following the application of the oracle, Hadamards are once again applied to all qubits. A helpful function for applying a pre-defined operator is ```qc.append(operator, indices)```, where ```operator``` is the operator and ```indices``` is a list of qubits to which the operator should be applied. For instance, let's say we've defined a three-qubit operator called ```myunitary``` that we want to apply to qubits 0, 3, and 4. This can be done with the line ```qc.append(myunitary, [0,3,4])```." ] }, { "cell_type": "code", "execution_count": 33, "id": "728f1c28-8e89-4943-addb-168baf20a714", "metadata": {}, "outputs": [], "source": [ "def diffuser(n, name='Diffuser'):\n", " \n", " # Create an n-qubit quantum circuit\n", " qc = QuantumCircuit(n, name='Diffuser')\n", " \n", " ### YOUR CODE GOES HERE - START\n", "\n", " \n", " ### YOUR CODE GOES HERE - END\n", " \n", " return qc" ] }, { "cell_type": "markdown", "id": "5029bf7f-74fc-485e-aab4-f1ef74c13935", "metadata": {}, "source": [ "Next, let's define a function that calculates $r$, the optimal number of repetitions. Your job is to code the formula for $r$ given above. The function ```np.floor``` may be helpful." ] }, { "cell_type": "code", "execution_count": 34, "id": "97c1eb1a-f562-48ef-8074-31aa1f8550f1", "metadata": {}, "outputs": [], "source": [ "def optimal_r(n, marked_items):\n", " k = len(marked_items)\n", "\n", " ### YOUR CODE GOES HERE - START\n", "\n", " ### YOUR CODE GOES HERE - END\n", " \n", " return r" ] }, { "cell_type": "markdown", "id": "0681841d-5672-41b5-b8b6-4989e22f63da", "metadata": {}, "source": [ "We can finally put all of the pieces together. Let's use the functions you wrote above to run Grover's algorithm for six qubits ($n=6$) and the marked items 10 and 32. Note that these marked items correspond to the bitstrings 001010 and 100000, respectively. You don't need to modify the code below -- just run it." ] }, { "cell_type": "code", "execution_count": 52, "id": "7f81c298-521a-4fe1-8625-0ecf771d3633", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The optimal number of repetitions is r = 4\n" ] }, { "data": { "text/html": [ "
     ┌───┐┌─────────┐┌───────────┐┌─────────┐┌───────────┐┌─────────┐»\n",
       "q_0: ┤ H ├┤0        ├┤0          ├┤0        ├┤0          ├┤0        ├»\n",
       "     ├───┤│         ││           ││         ││           ││         │»\n",
       "q_1: ┤ H ├┤1        ├┤1          ├┤1        ├┤1          ├┤1        ├»\n",
       "     ├───┤│         ││           ││         ││           ││         │»\n",
       "q_2: ┤ H ├┤2        ├┤2          ├┤2        ├┤2          ├┤2        ├»\n",
       "     ├───┤│  Oracle ││  Diffuser ││  Oracle ││  Diffuser ││  Oracle │»\n",
       "q_3: ┤ H ├┤3        ├┤3          ├┤3        ├┤3          ├┤3        ├»\n",
       "     ├───┤│         ││           ││         ││           ││         │»\n",
       "q_4: ┤ H ├┤4        ├┤4          ├┤4        ├┤4          ├┤4        ├»\n",
       "     ├───┤│         ││           ││         ││           ││         │»\n",
       "q_5: ┤ H ├┤5        ├┤5          ├┤5        ├┤5          ├┤5        ├»\n",
       "     └───┘└─────────┘└───────────┘└─────────┘└───────────┘└─────────┘»\n",
       "c: 6/════════════════════════════════════════════════════════════════»\n",
       "                                                                     »\n",
       "«     ┌───────────┐┌─────────┐┌───────────┐┌─┐               \n",
       "«q_0: ┤0          ├┤0        ├┤0          ├┤M├───────────────\n",
       "«     │           ││         ││           │└╥┘┌─┐            \n",
       "«q_1: ┤1          ├┤1        ├┤1          ├─╫─┤M├────────────\n",
       "«     │           ││         ││           │ ║ └╥┘┌─┐         \n",
       "«q_2: ┤2          ├┤2        ├┤2          ├─╫──╫─┤M├─────────\n",
       "«     │  Diffuser ││  Oracle ││  Diffuser │ ║  ║ └╥┘┌─┐      \n",
       "«q_3: ┤3          ├┤3        ├┤3          ├─╫──╫──╫─┤M├──────\n",
       "«     │           ││         ││           │ ║  ║  ║ └╥┘┌─┐   \n",
       "«q_4: ┤4          ├┤4        ├┤4          ├─╫──╫──╫──╫─┤M├───\n",
       "«     │           ││         ││           │ ║  ║  ║  ║ └╥┘┌─┐\n",
       "«q_5: ┤5          ├┤5        ├┤5          ├─╫──╫──╫──╫──╫─┤M├\n",
       "«     └───────────┘└─────────┘└───────────┘ ║  ║  ║  ║  ║ └╥┘\n",
       "«c: 6/══════════════════════════════════════╩══╩══╩══╩══╩══╩═\n",
       "«                                           0  1  2  3  4  5 
" ], "text/plain": [ " ┌───┐┌─────────┐┌───────────┐┌─────────┐┌───────────┐┌─────────┐»\n", "q_0: ┤ H ├┤0 ├┤0 ├┤0 ├┤0 ├┤0 ├»\n", " ├───┤│ ││ ││ ││ ││ │»\n", "q_1: ┤ H ├┤1 ├┤1 ├┤1 ├┤1 ├┤1 ├»\n", " ├───┤│ ││ ││ ││ ││ │»\n", "q_2: ┤ H ├┤2 ├┤2 ├┤2 ├┤2 ├┤2 ├»\n", " ├───┤│ Oracle ││ Diffuser ││ Oracle ││ Diffuser ││ Oracle │»\n", "q_3: ┤ H ├┤3 ├┤3 ├┤3 ├┤3 ├┤3 ├»\n", " ├───┤│ ││ ││ ││ ││ │»\n", "q_4: ┤ H ├┤4 ├┤4 ├┤4 ├┤4 ├┤4 ├»\n", " ├───┤│ ││ ││ ││ ││ │»\n", "q_5: ┤ H ├┤5 ├┤5 ├┤5 ├┤5 ├┤5 ├»\n", " └───┘└─────────┘└───────────┘└─────────┘└───────────┘└─────────┘»\n", "c: 6/════════════════════════════════════════════════════════════════»\n", " »\n", "« ┌───────────┐┌─────────┐┌───────────┐┌─┐ \n", "«q_0: ┤0 ├┤0 ├┤0 ├┤M├───────────────\n", "« │ ││ ││ │└╥┘┌─┐ \n", "«q_1: ┤1 ├┤1 ├┤1 ├─╫─┤M├────────────\n", "« │ ││ ││ │ ║ └╥┘┌─┐ \n", "«q_2: ┤2 ├┤2 ├┤2 ├─╫──╫─┤M├─────────\n", "« │ Diffuser ││ Oracle ││ Diffuser │ ║ ║ └╥┘┌─┐ \n", "«q_3: ┤3 ├┤3 ├┤3 ├─╫──╫──╫─┤M├──────\n", "« │ ││ ││ │ ║ ║ ║ └╥┘┌─┐ \n", "«q_4: ┤4 ├┤4 ├┤4 ├─╫──╫──╫──╫─┤M├───\n", "« │ ││ ││ │ ║ ║ ║ ║ └╥┘┌─┐\n", "«q_5: ┤5 ├┤5 ├┤5 ├─╫──╫──╫──╫──╫─┤M├\n", "« └───────────┘└─────────┘└───────────┘ ║ ║ ║ ║ ║ └╥┘\n", "«c: 6/══════════════════════════════════════╩══╩══╩══╩══╩══╩═\n", "« 0 1 2 3 4 5 " ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def full_algorithm(n, marked_items):\n", " \n", " qc = QuantumCircuit(n, n)\n", " r = optimal_r(n, marked_items)\n", " print('The optimal number of repetitions is r =', r)\n", " \n", " # Step 1: State preparation\n", " qc.h(range(n))\n", " \n", " # Steps 2 and 3, repeated r times: \n", " for _ in range(r):\n", " qc.append(oracle(n, marked_items), range(n))\n", " qc.append(diffuser(n), range(n))\n", " \n", " # Measure all qubits\n", " qc.measure(range(n), range(n))\n", " \n", " return qc\n", "\n", "grover = full_algorithm(6, [10, 32])\n", "grover.draw()" ] }, { "cell_type": "markdown", "id": "b8549077-0b75-41b7-a73d-a74cf2ffc182", "metadata": {}, "source": [ "Let's simulate the outcomes using the code below. If you've done everything correctly, most of the counts should be clustered about the two marked elements, ```001010``` and ```100000```." ] }, { "cell_type": "code", "execution_count": 48, "id": "d8083ade-cc89-465f-844b-a8ff5228ec4b", "metadata": {}, "outputs": [ { "data": { "image/png": "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90qS3N3d7YHcarVq/Pjx8vf3148//ujkSgse+9jBwTvvvKMvv/xSaWlpqlixosLCwhQZGam4uDht27ZNcXFxqlChgrPLxG0Mw5BhGA5HxB45ckTVq1fXkSNHVLFiRSdWh1vZbDa99957WrZsmVJTU1W5cmWeZy6A10bXcvnyZQ0cOFDx8fF64okn1LlzZ9WvX18lS5aUJB04cEBRUVHav3+/KlWq5ORqCxbBDtns3btXK1eu1M6dO5WUlKTffvtNNWvW1P/93/+pcePGzi4Pd2H877QLb7/9tt59910dOXLE2SUhB4cOHdLKlSu1fft2Xbp0ScePH+d5VsTx2uhaTp06pbffflsbN26Up6enKlWqJH9/f1mtVm3cuFH+/v769ttvnV1mgSPYQdLN02MYhmHfH0G6uWXh1KlTCg8Pl8RJOYuau53SJC0tTSdOnFCVKlXuc2W4nWEYOnv2rL788ku5u7urZs2aqlmzpoKCgmQYho4fP67w8HBOUVME8dro+n788UetXLlSBw4c0IULF3Tu3Dk98cQTevTRRxUaGurs8gocwa6YO378uCIjIx3G0tLS5Obm5vBChqIjp55x3rqi7f3339f777+vjIwMXb16VefOnVNERIR69Oih5557jvBdBPHa6JpSU1O1efNmfffddypfvrxq166tevXqydfXV6mpqbp06ZJCQkKcXWahItgVc+Hh4YqIiFDXrl3Vp08fVatWzX5d1lFfv/76qyIjI1WiRAlnlYlb3KlnWU/nI0eOKCIiwuGkxXCeMmXKaMaMGWrfvr2qVKmiU6dOad68eZo7d65+//13zZgxQ6NGjZLVaiWcFxG8NrqmAQMG6LvvvlOlSpV09OhRXbx4UTVq1FD//v01ZsyYYvENFBwVW4ytXLlSly5dUuXKlbVy5Ur16NFD3bt316effqrz58/Lzc1Nbm5uioqK0vr1651dLnT3nlksFlksFkVFRWnDhg3OLheSVq1apbJly+qpp55SlSpVlJmZqfLly+vvf/+7jh8/rn/84x965513dODAAUJdEcFro2v67LPPtGPHDi1btkzr16/X77//rl27dqlVq1Z68803Va1aNa1du9bZZRY6ttgVY6+88oqOHDmiyZMnKykpSVu3btWOHTt04MABZWRk6KGHHlJISIjefvttXb9+3dnlQvTMFW3atEnDhg3TvHnz1KxZM0k3T5GRmZmpkiVL6vz58+rTp48aN26smTNnOrlaSDzPXFW/fv0UGBio999/X4Zh2E9tIklXrlzRsGHDlJSUpJiYGPu4GbGjQDEWFRWl69evq0aNGrJYLGrSpInOnDmjXbt26ccff9RPP/2khQsXavjw4c4uFf9Dz1xP48aNFRgYqMGDB2vWrFnq1q2bPDw85OHhIUkKDAxUeHi4Ll++7NxCYcfzzDU9+OCDWrFihWw2m9zc3GS1WpWeni6bzSZvb2+NGjVKw4YNU2xsrDp37uzscgsNW+wg6eZZuW8/6mvz5s1q2bKltm3bpkaNGjmxOuQkMzPT4V0nPSu6Ll68qFGjRmn37t2KjIxU8+bN1apVK9WrV0+ffvqppkyZopUrVyo6OtrZpeI2vDa6jvj4eLVo0ULNmzfXK6+8Yt9CniU1NVVhYWFas2aNGjZs6KQqCx/72BVTGRkZDpezXriyDu13c3PTiRMnFBgYyAtXEZK107Yke6i79eTE9Kzosdls8vPz08yZMzVy5Eh5e3vrm2++Ue/eveXt7a33339fY8aMIdQVEbw2uq769esrNjZWaWlpGjlypPr166e33npL+/btU3x8vIYPHy5/f39ThzqJLXbF2m+//SYfHx9dvXpVfn5+euCBBxyuX716tRITE/X44487qULcKiMj465HTX777bdKTEzUwIED72NlyE1OPUtKStKBAweUkpIiT09P+fv7q3r16k6sErfjtdG1/fLLL1q5cqU2b96s06dPa//+/UpNTVX37t31zDPPqH379s4usVAR7IqhTZs2ae7cufr666917do1RUVF6aGHHtKf//xntWzZUoGBgc4uEXdgs9lkGIapd/41m8zMTGVmZtq/rxJFE6+NruvMmTO6evWqSpcuLU9PTwUEBOjKlSs6cuSIDMNQiRIlVKVKFftXipkZwa4YqlWrlqpVq6ahQ4eqTJky+vrrr+2Hhrdo0UJvvPGGypUrl23fEjhPnz591KxZMw0aNMjhy8YzMjLsp15ITk5WiRIlisULlyvIrWe3nuQ2KSlJpUqVsh9IAefitdE1vf/++5o/f7727t0rT09P1a9fX9HR0ercubNatGhhn5f1dYumZ6BY2bhxoxEYGGikp6dnu+6bb74x6tata9SuXds4c+aME6pDTjZt2mRYLBajQoUKho+Pj9G+fXtj6dKlhs1ms8+5fv260a9fP2P79u1OrBRZ6Jnr4bXRNa1fv94ICwszXnrpJePQoUPG6tWrjREjRhg1atQwypUrZ7z00ks59tTM+EygmDl16pQCAwP166+/SpJSUlKUnp4uSeratatWrlyp1NRUU34xsqtat26dOnbsqHnz5untt9+Wj4+PRo8eraCgID3++OOKi4vTvn379O9//1s1a9Z0drkQPXNFvDa6pk8++UTdunXTjBkzVK1aNXXs2FEfffSR9uzZo7///e+aN2+eRowY4ewy7yuCXTHTtWtXSdKnn34qSfLy8pKHh4d9H6AKFSqoSZMm2rZtmzPLxC08PDxUuXJlRUdHa8iQIfrggw+0bNkyvfjiizpz5oz69OmjRo0aqUuXLvL29nZ2uRA9c0W8NrqmEiVK6PLly0pNTZUk3bhxw/5R+VNPPaXXX39dmzdv1r59+5xc6X3k7E2GuH+yPgaaN2+e4ePjY1SrVs147bXXjGPHjtnn7N692wgPDze++OILJ1WJ2127ds2Ij4/PNp6WlmacPHnSWLZsmWGxWIxVq1Y5oTrk5Nq1a8bPP/+cbZyeFU28Nrqu1atXGwEBAcayZcscxrM+fr127ZoRHh5ubNiwwRnlOQUHTxRTu3bt0scff6xt27bp/Pnz8vHxUWRkpA4ePKjatWvr66+/dnaJuEcrV65U7969s51/C85h3LaDdtZRzG5ubvZxelZ08droOgzDUGpqqiZMmKD33ntPjRs31qBBg9SnTx/5+fnp4sWL+uqrr/T8888rOTnZ2eXeNwS7YubWPzoXL17U3r17dfjwYR09elQnT55Uhw4d1KNHD/n4+Di5Utyr999/X6dOndKMGTOcXQpukZGRIYvFku3bQSwWiz744AN6VsTw2ujaYmJi9Nlnn2n37t26cOGCAgMD5eHhoRs3bmjYsGEaO3ass0u8bwh2xUzWNxdwLi3XkRUGcjtM32az6caNGypVqtR9rgy3u3jxor7++mstXLhQgYGBioiIULVq1fTnP/9ZNWrUsM8zDEMpKSn0rAjhtdF1Xbt2TaVLl9b169e1a9cuHTx4UEePHlVqaqqGDh2qatWqFavzfhLsionY2Fg1bdrUYUft27copKamytPT01kl4jY59ez2kJeens450IqQ3r1769ChQ2rYsKGSk5OVmJiolJQUBQUFqXfv3nriiScIDkUMr42u6cCBA5o9e7Z+/vlnValSRREREWrSpIlatGihgIAAZ5fnVLzCFAOHDh1Sp06dFBISoh49emjVqlWSbn4HYtYLV3p6uhYtWqSDBw86s1T8T249u3U/rfT0dC1cuJCeFREHDhxQbGysli5dqoULF2r58uX69ttvNXHiRJUtW1bPP/+8nnnmGaWlpYn300UDr42u6ddff1WvXr10+PBhdezYURkZGdqyZYumTZumZ555RmvXrnV2iU5FsCsGvvzySzVs2FCzZs1SZmam+vTpI39/fz399NPauXOnJCkhIUFPPfUUHw0VEfTM9cTFxalu3bqqVauWpJtbfR544AH17NlTn3/+uZYtW6YVK1YoPj6+eJz93gXwPHNNb775pqpXr65vvvlG06ZN03/+8x8tW7ZMf/3rX3XhwgX16tVLc+fOdXaZTsNHscXASy+9pOTkZE2bNk0PPPCAfvnlF61evVpLly7VTz/9pCpVqsjf31/Jycnau3evs8uF6Jkr+vHHH9WzZ0/NmDFDgwYNknRza09mZqZKliyp9PR09ejRQzVr1tTs2bOdXC0knmeuqkuXLmrcuLEmTZqU40FK48eP13//+1999913xTOQ3/cTrOC+yszMNDZt2mQsXrw423WXL182tm7daowdO9awWCzGvHnznFAhbkfPXNeTTz5plClTxnj11VeNq1evZru+Xr16xjvvvOOEynA7nmeu66233jIiIyONw4cP28dSU1ONGzduGIZhGPv37zcqVKhgfP/9984q0anYYlfM5PTl1evXr1fbtm119erV4vnupoijZ67lzTff1DvvvKPExEQ1b95cvXv3VokSJbR06VL99ttvio+Pp2dFkJHDF8TzPCuajh07pt69eyspKUmTJk3S4MGDHa7fu3evHnzwQV2+fLlY9o1gV0xlZmbad8R/8803tXHjRk68WcTRs6LNZrPZj3jdv3+//vvf/2rNmjXasmWLPD091aFDBw0ePFjNmzd3cqWQbgY5438njs4Nz7OiJyuAJycna/z48Vq6dKkMw1D79u3VoUMH7dmzR3FxcapXr54+++wzZ5frFAQ7k9u/f7/279+vpKQkeXl5qWnTpqpYsaLDnD179uiBBx7INg7noGfmYLPZlJaWppIlS+rSpUvy9vbOtuUVRduuXbvk4+PD86wI27t3r7799lt99913io+PV6VKlfT444+rd+/eCgkJcXZ5TkGwM7HXXntNn3/+uX799VeVL19e/v7+MgxDUVFRGjBggJo1a8Y5tYoYeuZ6EhMT5e/vn+uRrjl9xAfnulvPUDTZbDatWLFCFy5c0LVr1xQZGamWLVvKz8/PPicpKUm+vr5OrNL5CHYmdeHCBVWoUEGzZs3SU089pVOnTunHH3/U1q1btXPnTl2/fl3Tp09Xq1atHD5CgvPQM9dz6dIl1alTR23atNEjjzyiZs2aqUyZMtnmbdq0SVWrVlVwcPD9LxIO8tKzypUrKzQ09P4XiWyuXLmiYcOGacOGDXJ3d1f58uVls9lUsmRJtW7dWo8++qj9VEPF/s3UfT5YA/fJhx9+aDz00EM5Xrd7926jb9++hre3t/Hrr7/e58qQG3rmet59913D29vbaNGiheHu7m6UK1fOeP75541t27YZKSkphmEYxokTJ4wqVaoYBw4ccHK1MAx65qqmTp1q/OlPfzJ++OEHwzAM4+DBg8aSJUuMkSNHGo0aNTK6d+9unDt3zslVFg285Tcpf39/JSYmatOmTZJu7nifmZkpSapbt64WLVqk2rVra/Xq1c4sE7egZ67nwIEDeuSRR/Ttt9/q+PHj+utf/6rvv/9eTZs2VaNGjfTGG2/ok08+0fnz5x2+KxbOQ89c0+rVqzVkyBA1bNhQklS9enU9+uijevvttzVr1iwdOnRIAwcOdHKVRQPBzqS6du2qyMhIzZ49WwcOHJDVapXVarV/lZGnp6esVqsuXLjg5EqRhZ65lvT0dDVt2lS1atWSl5eXwsLCNH78eO3evVs//fST2rVrp/fff1/Tpk3TmDFjnF0uRM9cVUZGhurUqaMvv/xSiYmJkv7/G1+r1armzZvro48+0unTp7Vr1y4nV+t87GNnQsb/9i/YvHmzRo0apb1796pLly568sknVa9ePSUmJmrz5s2aOHGifv75Z1WoUMHZJRd79Mw1paen68qVK/Lz81NmZqb99BlZ+z/+/PPPatCggU6cOKHy5cs7uVpI9MxVbdu2TY8//rj69++vv/3tbwoICHC4/uTJk6pZs6YOHTqkcuXKOanKooFj700oa6fRunXras2aNdq5c6cWLVqkxx9/XGlpaQoNDZXVatXkyZMJCEUEPXM9hmHIw8NDly5dUnp6usOBEVkHt3zzzTcqX748AaGIoGeuyTAMNWzYUOPHj9fLL7+sDz74QP369dOjjz6q8PBwxcfHa+XKlapZs2axD3USW+xM59y5c1q0aJFmz56tgIAAlShRQqGhoeratavatm2ry5cv6/jx42revDlH6BUR9Mz13Nqz0NBQubm5KSQkRH379lXv3r1VunRpSdKqVav0wAMPqGXLlk6uGPTMHC5fvqwFCxZoyZIlio+Pl4+Pj0qWLKmGDRtqwoQJaty4sbNLdDqCnckMHjxYBw8eVPfu3eXv769Lly4pPj5e+/fvV2hoqKZNm6ZGjRo5u0zcgp65npx69vPPP2v//v0KCwvTuHHj1KFDB2eXiVvQM9eUkpIiLy8vhzHDMJSSkqKrV6/aT9ZOoPv/CHYmYhiGvL29FRMToxYtWtjHTp06pR07dmjevHn65Zdf9K9//UtRUVFOrhYSPXNFufXs9OnT2rFjh+bOnaujR49qyZIl9KyIoGeua8yYMWrWrJkaNGigkJAQeXp6Zptz6dIllS1blvPX/Q9HxZrI/v37VbFiRYdffIvFovDwcD388MNavny5ypYtq3/9619OrBK3omeuJ7eelS9fXr1799by5cvl7e1Nz4oQeuaalixZojlz5uiRRx5R69atNWHCBK1fv16///670tPTJUnJyckaOnSo9uzZQ6j7H4KdiVSqVEnBwcEaM2aMjh49KpvN5nB9iRIlNGjQIH377bdOqhC3o2euh565Hnrmmr7//ns9/fTTOnDggIYNG6bly5erbdu26tKli2bNmqWff/5Zy5Yt06pVq1S3bl1nl1tkEOxMxMvLS1OnTtXVq1c1cOBALVmyRGfPnlVKSoqkm/sqbNy4UXXq1HFypchCz1wPPXM99Mz1ZGRkqFKlSipTpowqV66sV155RceOHVN8fLwaNmyo1157TS1atNCIESM4MfFt2MfOhPbs2aOpU6dq5cqVeuCBB9SsWTMFBQVpzZo1CgkJ0aeffsq7myKGnrkeeuZ66JlruXz5sn7//XdVr15daWlp8vDwcPi49fPPP9fAgQP1888/q169ek6stGgh2JnYuXPn9M033+irr75SyZIlVadOHfXt25evySnC6JnroWeuh565LpvNJsMwZLVa9c9//lPPP/+8rl+/7uyyihSCXTGRdfJNuA565nromeuhZ65r9uzZyszM1Lhx45xdSpFCsAMAAC4nPT1dVquVYH4bgh0AAIBJEHMBAABMgmAHAABgEgQ7AAAAkyDYAQAAmATBDgAAwCQIdgAAACZBsAMAADAJgh0AAIBJEOwAAABM4v8BCR2OucqEOQUAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "backend = AerSimulator()\n", "\n", "circuit = transpile(grover, backend)\n", "job = backend.run(circuit, shots=2000)\n", "counts = job.result().get_counts()\n", "plot_histogram(counts)" ] }, { "cell_type": "code", "execution_count": null, "id": "d17721b4-c7e7-424f-b9c2-1653c33c320d", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.13.2" } }, "nbformat": 4, "nbformat_minor": 5 }