{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "66dd0a62-b0ca-4de6-a2e9-d75cfb08c72c",
      "metadata": {},
      "source": [
        "---\n",
        "title: Quantum phase estimation\n",
        "description: This course you will learn about the QFT, which plays a key role in many quantum algorithms\n",
        "---\n",
        "\n",
        "# Quantum algorithms: Phase estimation\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Kento Ueda (15 May 2024)\n",
        "\n",
        "  This notebook provides the fundamental concepts and implementation of the Quantum Fourier Transformation (QFT) and Quantum Phase Estimation (QPE).\n",
        "\n",
        "  [Download the pdf](https://ibm.ent.box.com/public/static/srgnll6u8ame7gk186pkthq7erc7l6rw.zip) of the original lecture. Note that some code snippets might become deprecated since these are static images.\n",
        "\n",
        "  *Approximate QPU time to run this experiment is 7 seconds.*\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6b326b7f-2b9d-4f13-ab8c-5b19e0fa6659",
      "metadata": {},
      "source": [
        "## 1. Introduction\n",
        "\n",
        "**Quantum Fourier Transformation (QFT)**\n",
        "\n",
        "The Quantum Fourier Transformation is the quantum counterpart of the classical discrete Fourier transform. It is a linear transformation applied to the quantum states, mapping computational bases into their Fourier basis representations. The QFT plays a key role in many quantum algorithms, offering an efficient method to extract periodicity information from quantum states.\n",
        "The QFT can be implemented with $O(N^2)$ operations with quantum gates such as Hadamard gates and Control-Phase gates for $N$ qubits, enabling exponential speedup over classical Fourier transformation.\n",
        "\n",
        "* **Applications**: It is a foundational part in quantum algorithms such as Shor's algorithm for factoring large integers and discrete logarithm.\n",
        "\n",
        "**Quantum Phase Estimation (QPE)**\n",
        "\n",
        "Quantum Phase Estimation is a quantum algorithm used to estimate the phase associated with an eigenvector of a unitary operator. This algorithm provides a bridge between the abstract mathematical properties of quantum states and their computational applications.\n",
        "\n",
        "* **Applications**: It can solve problems such as finding eigenvalues of unitary matrices and simulating quantum systems.\n",
        "\n",
        "Together, QFT and QPE form the essential backbone of many quantum algorithms solving problems that are infeasible for classical computers. By the end of this notebook, you will gain an understanding of how these techniques are implemented.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4ba7fd89-5a7a-4e9b-9cbd-686f8aa743c6",
      "metadata": {},
      "source": [
        "## 2. Basic of Quantum Fourier Transformation (QFT)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "96a21cdf-3862-4524-a270-9ca6b2b2aa10",
      "metadata": {
        "tags": []
      },
      "outputs": [],
      "source": [
        "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
        "from qiskit_aer import AerSimulator\n",
        "from qiskit.visualization import plot_histogram, plot_bloch_multivector\n",
        "from qiskit.quantum_info import Statevector\n",
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "from qiskit_ibm_runtime import Sampler\n",
        "\n",
        "from numpy import pi"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4ecd8e59-2f2d-4208-9659-43e73658ca3d",
      "metadata": {},
      "source": [
        "From the analogy with the discrete Fourier transform, the QFT acts on a quantum state $\\vert X\\rangle = \\sum_{j=0}^{N-1} x_j \\vert j \\rangle$ for $N$ qubits and maps it to the quantum state $\\vert Y\\rangle = \\sum_{k=0}^{N-1} y_k \\vert k \\rangle$.\n",
        "\n",
        "$$\n",
        "QFT_{N}: \\vert j \\rangle \\mapsto \\frac{1}{\\sqrt{N}}\\sum_{k=0}^{N-1}\\omega_N^{jk} \\vert k \\rangle\n",
        "$$\n",
        "\n",
        "where $\\omega_N^{jk} = e^{2\\pi i \\frac{jk}{N}}$.\n",
        "\n",
        "Or the unitary matrix representation:\n",
        "\n",
        "$$\n",
        "U_{QFT} = \\frac{1}{\\sqrt{N}} \\sum_{j=0}^{N-1} \\sum_{k=0}^{N-1} \\omega_N^{jk} \\vert k \\rangle \\langle j \\vert\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "eb849035-3f71-4e68-b522-535b77c4bf45",
      "metadata": {},
      "source": [
        "### 2.1. Intuition <a id=\"intuition\" />\n",
        "\n",
        "The quantum Fourier transform (QFT) transforms between two bases, the computational (Z) basis, and the Fourier basis. But what does the Fourier basis mean in this context? You likely recall that the Fourier transform $F(\\omega)$ of a function $f(x)$ describes the convolution of $f(x)$ onto a sinusoidal function with frequency $\\omega$. In Layman's terms: the Fourier transform is a function describing how much of each frequency $\\omega$ we would need to build up a function $f(x)$ out of sine functions (or cosine functions). To get a better sense for what the QFT means in this context, consider the stepped images below which show a number encoded in binary, using four qubits:\n",
        "\n",
        "<IBMVideo id=\"134399598\" title=\"This short video shows how four qubits precessing at different rates can be used to encode digits.\" />\n",
        "\n",
        "In the computational basis, we store numbers in binary using the states $|0\\rangle$ and $|1\\rangle$.\n",
        "\n",
        "Note the frequency with which the different qubits change; the leftmost qubit flips with every increment in the number, the next with every 2 increments, the third with every 4 increments, and so on.\n",
        "\n",
        "If we apply a quantum Fourier transform to these states, we map\n",
        "\n",
        "$$\n",
        "|\\text{State in Computational Basis}\\rangle \\quad \\xrightarrow[]{\\text{QFT}} \\quad |\\text{State in Fourier Basis}\\rangle\n",
        "$$\n",
        "\n",
        "$$\n",
        "\\text{QFT}|x\\rangle = |\\widetilde{x}\\rangle\n",
        "$$\n",
        "\n",
        "(We often denote states in the Fourier basis using the tilde (\\~)).\n",
        "\n",
        "In the Fourier basis, we store numbers using different rotations around the Z-axis:\n",
        "\n",
        "IFRAME\n",
        "\n",
        "The number we want to store dictates the angle at which each qubit is rotated around the Z-axis. In the state $|\\widetilde{0}\\rangle$, all qubits are in the state $|{+}\\rangle$. As seen in the example above, to encode the state $|\\widetilde{5}\\rangle$ on 4 qubits, we rotated the leftmost qubit by $\\tfrac{5}{2^n} = \\tfrac{5}{16}$ full turns ($\\tfrac{5}{16}\\times 2\\pi$ radians). The next qubit is turned double this ($\\tfrac{10}{16}\\times 2\\pi$ radians, or $10/16$ full turns), this angle is then doubled for the qubit after, and so on.\n",
        "\n",
        "Again, note the frequency with which each qubit changes. The leftmost qubit (`qubit 0`) in this case has the lowest frequency, and the rightmost the highest.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3981876d-a714-46e5-bf4c-7c7cf364e6f4",
      "metadata": {},
      "source": [
        "### 2.2 Example: 1-qubit QFT\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "78e5e1f3-f361-4549-b76e-f13981c8d17d",
      "metadata": {},
      "source": [
        "Let's consider the case of $N = 2^1 = 2$.\n",
        "\n",
        "The unitary matrix can be written:\n",
        "\n",
        "$$\n",
        "\\begin{aligned}\n",
        "U_{QFT} & = \\frac{1}{\\sqrt{2}} \\sum_{j=0}^{1} \\sum_{k=0}^{1} \\omega_2^{jk} \\vert k \\rangle \\langle j \\vert\n",
        "\\\\\n",
        "& = \\frac{1}{\\sqrt{2}} (\\omega_2^{0} \\vert 0 \\rangle \\langle 0 \\vert + \\omega_2^{0} \\vert 0 \\rangle \\langle 1 \\vert + \\omega_2^{0} \\vert 1 \\rangle \\langle 0 \\vert + \\omega_2^{1} \\vert 1 \\rangle \\langle 1 \\vert)\n",
        "\\\\\n",
        "& = \\frac{1}{\\sqrt{2}} (\\vert 0 \\rangle \\langle 0 \\vert + \\vert 0 \\rangle \\langle 1 \\vert + \\vert 1 \\rangle \\langle 0 \\vert - \\vert 1 \\rangle \\langle 1 \\vert)\n",
        "\\\\\n",
        "& = H\n",
        "\\end{aligned}\n",
        "$$\n",
        "\n",
        "This operation is the result of applying the Hadamard gate ($H$).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "30607575-56dc-48f6-b30d-7939616c8be5",
      "metadata": {},
      "source": [
        "### 2.3 Product representation of QFT\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4c438de4-643b-440f-8b0f-d98aed062a55",
      "metadata": {},
      "source": [
        "Let's generalize a transformation for $N = 2^n$, $QFT_{N}$ acting on the state $\\vert x \\rangle = \\vert x_1\\ldots x_n \\rangle$.\n",
        "\n",
        "$$\n",
        "\\begin{aligned}\n",
        "QFT_N\\vert x \\rangle & = \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1}\\omega_N^{xy} \\vert y \\rangle\n",
        "\\\\\n",
        "& = \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} e^{2 \\pi i xy / 2^n} \\vert y \\rangle ~\\text{since}\\: \\omega_N^{xy} = e^{2\\pi i \\frac{xy}{N}} \\:\\text{and}\\: N = 2^n\n",
        "\\\\\n",
        "& = \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} e^{2 \\pi i \\left(\\sum_{k=1}^n y_k/2^k\\right) x} \\vert y_1 \\ldots y_n \\rangle \\:\\text{rewriting in fractional binary notation}\\: y = y_1\\ldots y_n, y/2^n = \\sum_{k=1}^n y_k/2^k\n",
        "\\\\\n",
        "& = \\frac{1}{\\sqrt{N}} \\sum_{y=0}^{N-1} \\prod_{k=1}^n e^{2 \\pi i x y_k/2^k } \\vert y_1 \\ldots y_n \\rangle \\:\\text{after expanding the exponential of a sum to a product of exponentials,}\n",
        "\\\\\n",
        "& = \\frac{1}{\\sqrt{N}} \\bigotimes_{k=1}^n  \\left(\\vert0\\rangle + e^{2 \\pi i x /2^k } \\vert1\\rangle \\right) \\:\\text{after rearranging the sum and products, and expanding}\n",
        "\\sum_{y=0}^{N-1} = \\sum_{y_1=0}^{1}\\sum_{y_2=0}^{1}\\ldots\\sum_{y_n=0}^{1}\n",
        "\\\\\n",
        "& = \\frac{1}{\\sqrt{N}}\n",
        "\\left(\\vert0\\rangle + e^{\\frac{2\\pi i}{2}x} \\vert1\\rangle\\right)\n",
        "\\otimes\n",
        "\\left(\\vert0\\rangle + e^{\\frac{2\\pi i}{2^2}x} \\vert1\\rangle\\right)\n",
        "\\otimes\n",
        "\\ldots\n",
        "\\otimes\n",
        "\\left(\\vert0\\rangle + e^{\\frac{2\\pi i}{2^{n-1}}x} \\vert1\\rangle\\right)\n",
        "\\otimes\n",
        "\\left(\\vert0\\rangle + e^{\\frac{2\\pi i}{2^n}x} \\vert1\\rangle\\right)\n",
        "\\end{aligned}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "235156fd-c8eb-48bf-b40b-6bf4b90111a7",
      "metadata": {},
      "source": [
        "### 2.4 Example: Circuit construction of 3 qubits QFT\n",
        "\n",
        "From the above description, it might not be clear how to construct a QFT circuit. For now, simply note that we expect three qubits to have phases that evolve at different \"rates\". Understand exactly how this is translated into a circuit is left as an exercise to the reader. There are multiple diagrams and examples in the lecture pdf. Additional resources include [this lesson](/learning/courses/fundamentals-of-quantum-algorithms/phase-estimation-and-factoring/introduction) from the Fundamentals of quantum algorithms course.\n",
        "\n",
        "We will demonstrate QFT using simulators only, and thus we will not use the Qiskit patterns framework until we move on to quantum phase estimation.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "57feef7e-6d5d-494a-99d0-d544338b9cc5",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Prepare for 3 qubits circuit\n",
        "qr = QuantumRegister(3)\n",
        "cr = ClassicalRegister(3)\n",
        "qc = QuantumCircuit(qr, cr)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "153fe2ee-74a0-4514-910f-78b27dbccfae",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/98cc96b3-f2d8-4d0d-bb57-186ea0919f53-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc.h(2)\n",
        "qc.cp(pi / 2, 1, 2)  # Controlled-phase gate from qubit 1 to qubit 2\n",
        "qc.cp(pi / 4, 0, 2)  # Controlled-phase gate from qubit 0 to qubit 2\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "dbc06a28-ea0f-4df5-8894-eb1e697be17c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/eaff67fa-82f9-4402-8fa5-d0f0af824616-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc.h(1)\n",
        "qc.cp(pi / 2, 0, 1)  # Controlled-phase gate from qubit 0 to qubit 1\n",
        "\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "e515ca3e-8c9c-4add-ac47-2eee4b74c8db",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/43e09a6b-ea86-4f02-9e3a-82317c3b787f-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc.h(0)\n",
        "\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "429af74c-958f-474c-98b6-b62a74162f89",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/d7dd1cae-f463-4308-866c-8267e015c6ff-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc.swap(0, 2)\n",
        "\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "14577557-d3f0-4dac-b4fd-999e3ff0a71c",
      "metadata": {},
      "source": [
        "We try to apply QFT to $|5\\rangle$ as an example.\n",
        "\n",
        "First, we confirm the binary notation of the integer 5 and create the circuit encoding the state 5:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "6bb9a51b-1877-423a-bc7e-2779f79baf44",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'0b101'"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "bin(5)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "a7ee2436-a40b-416a-898f-5fc7199a03e5",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/db631de5-4619-4e8c-b9d1-c6197650ae33-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(3)\n",
        "\n",
        "qc.x(0)\n",
        "qc.x(2)\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ab705285-2ebf-47d1-be2a-21ab4660cef1",
      "metadata": {},
      "source": [
        "We check the quantum states using the Aer simulator:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "dc6a6dbd-6ccf-45e7-900f-225b588ceb48",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/83f34fc7-21f3-408b-9beb-a146cb77d27c-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "statevector = Statevector(qc)\n",
        "plot_bloch_multivector(statevector)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8a315ea8-192e-413b-bc74-ad6ee8d08bf7",
      "metadata": {},
      "source": [
        "Finally, we add QFT and view the final state of our qubits:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "20ca9b30-76fe-4668-ab66-ad2f3e0283e6",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/524f24ae-3d86-4be4-99cc-c0c8557b8393-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc.h(2)\n",
        "qc.cp(pi / 2, 1, 2)\n",
        "qc.cp(pi / 4, 0, 2)\n",
        "\n",
        "qc.h(1)\n",
        "qc.cp(pi / 2, 0, 1)\n",
        "\n",
        "qc.h(0)\n",
        "\n",
        "qc.swap(0, 2)\n",
        "\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "fdf78c16-cfd1-47b6-b27b-37eb87f8a31e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/cf4d7152-bb06-4017-922a-5fa97075a67f-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "statevector = Statevector(qc)\n",
        "plot_bloch_multivector(statevector)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ebc9f18e-9c99-4ff5-bbe3-20a6afcdd92e",
      "metadata": {},
      "source": [
        "We can see out QFT function has worked correctly. Qubit 0 has been rotated by $\\tfrac{5}{8}$ of a full turn, qubit 1 by $\\tfrac{10}{8}$ full turns (equivalent to $\\tfrac{1}{4}$ of a full turn), and qubit 2 by $\\tfrac{20}{8}$ full turns (equivalent to $\\tfrac{1}{2}$ of a full turn).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a3cfb19a-150d-481a-a209-f981f8d50d4b",
      "metadata": {},
      "source": [
        "### 2.5 Exercise: QFT\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d813d45e-7f63-48a4-8c45-dec6164e6773",
      "metadata": {},
      "source": [
        "(1) Implement QFT of 4 qubits.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "48e9721d-2805-4671-a9bb-1e12aae9ff2d",
      "metadata": {},
      "outputs": [],
      "source": [
        "##your code goes here##"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b52d373d-d30f-43a3-9935-83fe5724a2c0",
      "metadata": {},
      "source": [
        "(2) Apply QFT to $|14\\rangle$, simulate and plot the statevector using the Bloch sphere.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "788a81f6-c4d0-420d-843e-be516dad713a",
      "metadata": {},
      "outputs": [],
      "source": [
        "##your code goes here##"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "da1819ca-5c78-48dd-a81f-8cdb31a9425a",
      "metadata": {},
      "source": [
        "#### Solution of the exercise: QFT\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "66481390-e98d-463a-889b-fb0817e7eada",
      "metadata": {},
      "source": [
        "(1)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "87f940ef-a728-4a3e-9ec0-0a97e320514c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/02e1d50b-6555-4a1e-a2b9-ba77c77840a1-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qr = QuantumRegister(4)\n",
        "cr = ClassicalRegister(4)\n",
        "qc = QuantumCircuit(qr, cr)\n",
        "\n",
        "qc.h(3)\n",
        "qc.cp(pi / 2, 2, 3)\n",
        "qc.cp(pi / 4, 1, 3)\n",
        "qc.cp(pi / 8, 0, 3)\n",
        "\n",
        "qc.h(2)\n",
        "qc.cp(pi / 2, 1, 2)\n",
        "qc.cp(pi / 4, 0, 2)\n",
        "\n",
        "qc.h(1)\n",
        "qc.cp(pi / 2, 0, 1)\n",
        "\n",
        "qc.h(0)\n",
        "\n",
        "qc.swap(0, 3)\n",
        "qc.swap(1, 2)\n",
        "\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f9fe9c49-0cef-477b-9fad-0a37156c1815",
      "metadata": {},
      "source": [
        "(2)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "75cad1d3-4799-49d6-abcc-e6f981cf90f1",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'0b1110'"
            ]
          },
          "execution_count": 14,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "bin(14)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "05f1ccb5-6d7d-42aa-bc8c-a636315b6959",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/a01ee72e-8486-426d-a654-21b272b958ff-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(4)\n",
        "\n",
        "qc.x(1)\n",
        "qc.x(2)\n",
        "qc.x(3)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "422a90c9-69d5-431d-b9a6-25b2b473ae2b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/db8a6229-a864-4f5e-889b-8ccd5561eddb-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 16,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc.h(3)\n",
        "qc.cp(pi / 2, 2, 3)\n",
        "qc.cp(pi / 4, 1, 3)\n",
        "qc.cp(pi / 8, 0, 3)\n",
        "\n",
        "qc.h(2)\n",
        "qc.cp(pi / 2, 1, 2)\n",
        "qc.cp(pi / 4, 0, 2)\n",
        "\n",
        "qc.h(1)\n",
        "qc.cp(pi / 2, 0, 1)\n",
        "qc.h(0)\n",
        "\n",
        "qc.swap(0, 3)\n",
        "qc.swap(1, 2)\n",
        "\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "933ae1e8-f0cc-494e-a3b3-a2473b27d13c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/0d0af6c8-73e7-4e49-9d81-75446373d6c8-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "statevector = Statevector(qc)\n",
        "plot_bloch_multivector(statevector)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "05d6482b-0e97-4df8-8920-d195cbd334ff",
      "metadata": {},
      "source": [
        "## 3. Basics of Quantum Phase Estimation (QPE)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d0afcf26-86c5-42c1-8027-21b492433082",
      "metadata": {},
      "source": [
        "Given a unitary operation $U$, the QPE estimates $\\theta$ in $U\\vert\\psi \\rangle =e^{\\boldsymbol{2\\pi i} \\theta }|\\psi \\rangle$ since $U$ is unitary, all of its eigenvalues have a norm of 1.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dbaa4d5a-04a7-4ac3-b6e7-c91063992616",
      "metadata": {},
      "source": [
        "### 3.1 Procedure\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cd1d152e-d7fd-41cc-b147-8a33ecb69fa9",
      "metadata": {},
      "source": [
        "#### 1. Setup\n",
        "\n",
        "$\\vert\\psi\\rangle$ is in one set of qubit registers. An additional set of $n$ qubits form the counting register on which we will store the value $2^n\\theta$:\n",
        "\n",
        "$$\n",
        "|\\psi_0\\rangle = \\lvert 0 \\rangle^{\\otimes n} \\lvert \\psi \\rangle\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1557ea00-366d-4ec4-a2cb-1f845cbd3e50",
      "metadata": {},
      "source": [
        "#### 2. Superposition\n",
        "\n",
        "Apply a $n$-bit Hadamard gate operation $H^{\\otimes n}$ on the counting register:\n",
        "\n",
        "$$\n",
        "|\\psi_1\\rangle = {\\frac {1}{2^{\\frac {n}{2}}}}\\left(|0\\rangle +|1\\rangle \\right)^{\\otimes n} \\lvert \\psi \\rangle\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "61518599-fc54-4d15-aa32-c0a7e66759b7",
      "metadata": {},
      "source": [
        "#### 3. Controlled Unitary operations\n",
        "\n",
        "We need to introduce the controlled unitary $CU$ that applies the unitary operator $U$ on the target register only if its corresponding control bit is $|1\\rangle$. Since $U$ is a unitary operator with eigenvector $|\\psi\\rangle$ such that $U|\\psi \\rangle =e^{\\boldsymbol{2\\pi i} \\theta }|\\psi \\rangle$, this means:\n",
        "\n",
        "$$\n",
        "U^{2^{j}}|\\psi \\rangle =U^{2^{j}-1}U|\\psi \\rangle =U^{2^{j}-1}e^{2\\pi i\\theta }|\\psi \\rangle =\\cdots =e^{2\\pi i2^{j}\\theta }|\\psi \\rangle\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "18e0cdf2-278d-4ff1-a3aa-ad4cc9f95cca",
      "metadata": {},
      "source": [
        "### 3.2 Example: T-gate QPE\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "19722262-d7fa-4928-bb37-68c54de681e1",
      "metadata": {},
      "source": [
        "Let's use $T$ gate as an example of QPE and estimate its phase $\\theta$.\n",
        "\n",
        "$$\n",
        "T|1\\rangle =\n",
        "\\begin{pmatrix}\n",
        "1 & 0\\\\\n",
        "0 & e^\\frac{i\\pi}{4}\\\\\n",
        "\\end{pmatrix}\n",
        "\\begin{pmatrix}\n",
        "0\\\\\n",
        "1\\\\\n",
        "\\end{pmatrix}\n",
        "= e^\\frac{i\\pi}{4}|1\\rangle\n",
        "$$\n",
        "\n",
        "We expect to find:\n",
        "\n",
        "$$\n",
        "\\theta = \\frac{1}{8}\n",
        "$$\n",
        "\n",
        "where\n",
        "\n",
        "$$\n",
        "T|1\\rangle = e^{2i\\pi\\theta}|1\\rangle\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a8e0002a-9e8b-416b-9725-02c424126f6e",
      "metadata": {},
      "source": [
        "We initialize $\\vert\\psi\\rangle = \\vert1\\rangle$ of the eigenvector of $T$ gate by applying an $X$ gate:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "id": "ef895407-9a5c-4e09-9d5c-038a0fb58af8",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/2334e6e2-7ae2-4d4c-9014-3e6041f37ee7-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 18,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qpe = QuantumCircuit(4, 3)\n",
        "qpe.x(3)\n",
        "qpe.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9ed123a3-fd68-4dff-a9c2-c459c21b6c15",
      "metadata": {},
      "source": [
        "Next, we apply Hadamard gates to the counting qubits:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "id": "7f37e6ca-ff13-4e8d-9229-3982c03ea730",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/9c020053-c369-4cc4-829e-72246d79f82c-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 19,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "for qubit in range(3):\n",
        "    qpe.h(qubit)\n",
        "qpe.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "98bc7af7-4d85-4c92-89db-9025bf45b904",
      "metadata": {},
      "source": [
        "We perform the controlled unitary operations:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "id": "311f7dfa-aa2f-4502-a42d-5ba84b1a60f2",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/0b3bedfc-be73-427d-9eed-22a2d7df60cd-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 20,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "repetitions = 1\n",
        "for counting_qubit in range(3):\n",
        "    for i in range(repetitions):\n",
        "        qpe.cp(pi / 4, counting_qubit, 3)  # This is C-U\n",
        "    repetitions *= 2\n",
        "qpe.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2089b52d-657a-44bd-b48f-471a909a8d3c",
      "metadata": {},
      "source": [
        "We apply the inverse quantum Fourier transformation to convert the state of the counting register, then measure the counting register:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "id": "0ccdf70f-6640-4b19-8801-9f8c787a7098",
      "metadata": {
        "tags": []
      },
      "outputs": [],
      "source": [
        "from qiskit.circuit.library import QFT"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "c035e156-13c4-4dd1-9f68-a0ed9e85886f",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/df8ada87-4279-47bb-acd5-cb432bdfc998-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 22,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Apply inverse QFT\n",
        "qpe.append(QFT(3, inverse=True), [0, 1, 2])\n",
        "qpe.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "id": "6f3d55bc-1141-4aa4-a488-fbf8d6cbf2f3",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/5fcc8195-8fc9-47bc-9ef3-9d9d444db812-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 23,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "for n in range(3):\n",
        "    qpe.measure(n, n)\n",
        "qpe.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5398ebda-6aab-4145-9468-ca306616dcda",
      "metadata": {},
      "source": [
        "We can simulate using Aer simulator:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "id": "c4d4f9ff-4c03-4596-a93f-4e72f2c7c8df",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/b0152311-8f60-4c11-a10e-a35691c0ece5-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 24,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "aer_sim = AerSimulator()\n",
        "shots = 2048\n",
        "\n",
        "pm = generate_preset_pass_manager(backend=aer_sim, optimization_level=1)\n",
        "t_qpe = pm.run(qpe)\n",
        "\n",
        "sampler = Sampler(mode=aer_sim)\n",
        "job = sampler.run([t_qpe], shots=shots)\n",
        "result = job.result()\n",
        "answer = result[0].data.c.get_counts()\n",
        "\n",
        "plot_histogram(answer)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bdb646b0-e8e6-4dc7-9a15-43f9c7bb624e",
      "metadata": {},
      "source": [
        "We see we get one result (`001`) with certainty, which translates to the decimal: `1`. We now need to divide our result (`1`) by $2^n$ to get $\\theta$:\n",
        "\n",
        "$$\n",
        "\\theta = \\frac{1}{2^3} = \\frac{1}{8}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d22d8e1a-6b71-4776-a0c0-10d9d245f32d",
      "metadata": {},
      "source": [
        "Shor's algorithm allows us to factorize a number by building a circuit with $\\theta$ unknown and obtaining $\\theta$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "83631cc9-90e8-43c3-935e-1dfc3120f2da",
      "metadata": {},
      "source": [
        "### 3.3 Exercise\n",
        "\n",
        "Estimate $\\theta = 1/3$ using 3 qubits for counting and a qubit for an eigenvector.\n",
        "\n",
        "$P|1\\rangle = e^{i\\lambda}|1\\rangle$. Since we want to implement $U|1\\rangle = e^{2\\pi i \\tfrac{1}{3}}|1\\rangle$, we need to set $\\lambda = \\tfrac{2 \\pi}{3}$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "bf0be770-efb5-4290-b378-3e77da6810a5",
      "metadata": {},
      "outputs": [],
      "source": [
        "##your code goes here##"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "efba73b8-49aa-4eb4-8979-80d48ab5d747",
      "metadata": {},
      "source": [
        "#### Solution of the exercise: $\\theta = 1/3$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "id": "6791c2a8-e835-43a4-9f0a-2709fd85f8cd",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/9cb90eab-e6ce-4456-b73e-e4082fed2850-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 25,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Create and set up circuit\n",
        "qpe = QuantumCircuit(4, 3)\n",
        "\n",
        "# Apply H-Gates to counting qubits:\n",
        "for qubit in range(3):\n",
        "    qpe.h(qubit)\n",
        "\n",
        "# Prepare our eigenstate |psi>:\n",
        "qpe.x(3)\n",
        "\n",
        "# Do the controlled-U operations:\n",
        "angle = 2 * pi / 3\n",
        "repetitions = 1\n",
        "for counting_qubit in range(3):\n",
        "    for i in range(repetitions):\n",
        "        qpe.cp(angle, counting_qubit, 3)\n",
        "    repetitions *= 2\n",
        "\n",
        "# Do the inverse QFT:\n",
        "qpe.append(QFT(3, inverse=True), [0, 1, 2])\n",
        "\n",
        "for n in range(3):\n",
        "    qpe.measure(n, n)\n",
        "\n",
        "qpe.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "id": "ede6461a-1fbd-4c68-8bd0-63242a894963",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/e118815f-5d92-4ea1-9849-b178ef84d8a4-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 26,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "aer_sim = AerSimulator()\n",
        "shots = 4096\n",
        "\n",
        "pm = generate_preset_pass_manager(backend=aer_sim, optimization_level=1)\n",
        "t_qpe = pm.run(qpe)\n",
        "\n",
        "sampler = Sampler(mode=aer_sim)\n",
        "job = sampler.run([t_qpe], shots=shots)\n",
        "result = job.result()\n",
        "answer = result[0].data.c.get_counts()\n",
        "\n",
        "plot_histogram(answer)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "93964c68-402e-400f-afce-aba86b8553c7",
      "metadata": {},
      "source": [
        "## 4. Execution using the Qiskit Runtime Sampler primitive\n",
        "\n",
        "We will perform QPE using the real quantum device and follow 4 steps of Qiskit patterns.\n",
        "\n",
        "1. Map the problem to a quantum-native format\n",
        "2. Optimize the circuits\n",
        "3. Execute the target circuit\n",
        "4. Post-process the results\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "id": "180b6914-c35a-436b-a887-c49593c5ef7d",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "from qiskit_ibm_runtime import Sampler"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f8107b9f-aada-46ee-bfdd-5fea58935872",
      "metadata": {
        "tags": []
      },
      "outputs": [],
      "source": [
        "# Loading your IBM Quantum&reg; account(s)\n",
        "\n",
        "service = QiskitRuntimeService()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2de29c5e-0917-4b97-99cd-a7f34b9eb2c6",
      "metadata": {},
      "source": [
        "### 4.1 Step 1: Map problem to quantum circuits and operators\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 29,
      "id": "693b7d04-9f11-4359-bff5-9e4f38997a0c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/70c92e35-0e13-4552-99be-50d6950dfedc-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 29,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qpe = QuantumCircuit(4, 3)\n",
        "qpe.x(3)\n",
        "for qubit in range(3):\n",
        "    qpe.h(qubit)\n",
        "repetitions = 1\n",
        "for counting_qubit in range(3):\n",
        "    for i in range(repetitions):\n",
        "        qpe.cp(pi / 4, counting_qubit, 3)  # This is C-U\n",
        "    repetitions *= 2\n",
        "qpe.append(QFT(3, inverse=True), [0, 1, 2])\n",
        "for n in range(3):\n",
        "    qpe.measure(n, n)\n",
        "qpe.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 30,
      "id": "04898923-ac54-4741-9f3b-ab53811d1afa",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "<IBMBackend('ibm_strasbourg')>\n"
          ]
        }
      ],
      "source": [
        "backend = service.least_busy(simulator=False, operational=True, min_num_qubits=4)\n",
        "\n",
        "print(backend)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "30f764ed-7f4b-494a-935d-195ccfb40a82",
      "metadata": {},
      "source": [
        "### 4.2 Step 2: Optimize for target hardware\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 31,
      "id": "3025a167-13f6-4dca-8311-57e247995bc9",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/d4d57d21-00c6-4144-aa3e-4a467a065078-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 31,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Transpile the circuit into basis gates executable on the hardware\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=2)\n",
        "qc_compiled = pm.run(qpe)\n",
        "\n",
        "qc_compiled.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5e0090dd-bc6a-4ac5-9846-7cd1cfba9b2f",
      "metadata": {},
      "source": [
        "### 4.3 Step 3: Execute on target hardware\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 32,
      "id": "0c1ad7d6-332d-4694-a0fd-da2c6788fcf8",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "job id: d13p4zb5z6q00087ag00\n"
          ]
        }
      ],
      "source": [
        "real_sampler = Sampler(mode=backend)\n",
        "job = real_sampler.run([qc_compiled], shots=1024)\n",
        "job_id = job.job_id()\n",
        "print(\"job id:\", job_id)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 35,
      "id": "6ed22c42-bd9e-4dfb-a7d0-9e8839727900",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'DONE'"
            ]
          },
          "execution_count": 35,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "job = service.job(job_id)  # Input your job-id between the quotations\n",
        "job.status()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 36,
      "id": "9d66b35f-baa5-4a42-9c62-ab647cd6ecdb",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "PrimitiveResult([SamplerPubResult(data=DataBin(c=BitArray(<shape=(), num_shots=1024, num_bits=3>)), metadata={'circuit_metadata': {}})], metadata={'execution': {'execution_spans': ExecutionSpans([DoubleSliceSpan(<start='2025-06-09 22:39:00', stop='2025-06-09 22:39:00', size=1024>)])}, 'version': 2})\n"
          ]
        }
      ],
      "source": [
        "result_real = job.result()\n",
        "print(result_real)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "98bedc55-7a33-4b74-bc50-1b84d220893c",
      "metadata": {},
      "source": [
        "### 4.4 Step 4: Post-process the results\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 37,
      "id": "0459489d-ac26-4479-85ef-8f81a42dfe58",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/quantum-phase-estimation/extracted-outputs/bd9181eb-dc1e-42e1-bdcf-3bb6b128538d-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 37,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import plot_histogram\n",
        "\n",
        "plot_histogram(result_real[0].data.c.get_counts())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 38,
      "id": "619db29e-d932-4b6a-b656-da9095538e9b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'2.0.2'"
            ]
          },
          "execution_count": 38,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# See the version of Qiskit\n",
        "import qiskit\n",
        "\n",
        "qiskit.__version__"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "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"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "state": {},
        "version_major": 2,
        "version_minor": 0
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}