{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "4233533a-fcd2-4bd7-bcb8-8e0be95326e6",
      "metadata": {},
      "source": [
        "---\n",
        "title: Bits, gates, and circuits\n",
        "description: you will learn quantum computation with circuit model using quantum bits (qubits) and gates.\n",
        "---\n",
        "\n",
        "# Quantum bits, gates, and circuits\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Kifumi Numata (19 Apr 2024)\n",
        "\n",
        "  Click [here](https://ibm.ent.box.com/public/static/vee9e1kkxxiih5g8yqdhoo6t0o3dw7xf.zip) to download the pdf 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 5 seconds.*\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ec475aee-075f-4411-8dbe-8a427865714b",
      "metadata": {},
      "source": [
        "## 1. Introduction\n",
        "\n",
        "Bits, gates, and circuits are the basic building blocks of quantum computing. You will learn quantum computation with the circuit model using quantum bits and gates, and also review the superposition, measurement, and entanglement.\n",
        "\n",
        "In this lesson you will learn:\n",
        "\n",
        "* Single-qubit gates\n",
        "* Bloch sphere\n",
        "* Superposition\n",
        "* Measurement\n",
        "* Two-qubit gates and entanglement state\n",
        "\n",
        "At the end of this lecture, you will learn about circuit depth, which is essential for utility-scale quantum computing.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ed761072-54aa-47af-a2e1-a5c40a0471d1",
      "metadata": {},
      "source": [
        "## 2. Computation as a diagram\n",
        "\n",
        "When using qubits or bits, we need to manipulate them in order to turn the inputs we have into the outputs we need. For the simplest programs with very few bits, it is useful to represent this process in a diagram known as a *circuit diagram*.\n",
        "\n",
        "The bottom-left figure is an example of a classical circuit, and the bottom-right figure is an example of a quantum circuit. In both cases, the inputs are on the left and the outputs are on the right, while the operations are represented by symbols. The symbols used for the operations are called “gates”, mostly for historical reasons.\n",
        "\n",
        "![\"classical logic and quantum circuit\"](https://eu-de.quantum.cloud.ibm.com/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/classical-vs-quantum.avif)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "87f8d07a-1544-4acb-82fb-3a43f1a99f8c",
      "metadata": {},
      "source": [
        "## 3. Single-qubit quantum gate\n",
        "\n",
        "### 3.1 Quantum state and Bloch sphere\n",
        "\n",
        "A qubit's state is represented as a superposition of $|0\\rangle$ and $|1\\rangle$. An arbitrary quantum state is represented as\n",
        "\n",
        "$$\n",
        "|\\psi\\rangle =\\alpha|0\\rangle+ \\beta|1\\rangle\n",
        "$$\n",
        "\n",
        "where $\\alpha$ and $\\beta$ are complex numbers such that $|\\alpha|^2+|\\beta|^2=1$.\n",
        "\n",
        "$|0\\rangle$ and $|1\\rangle$ are vectors in the two-dimensional complex vector space:\n",
        "\n",
        "$$\n",
        "|0\\rangle = \\begin{pmatrix}\n",
        "1 \\\\0\n",
        "\\end{pmatrix},\n",
        "|1\\rangle = \\begin{pmatrix}\n",
        "0\\\\1\n",
        "\\end{pmatrix}\n",
        "$$\n",
        "\n",
        "Therefore, an arbitrary quantum state is also represented as\n",
        "\n",
        "$$\n",
        "|\\psi\\rangle = \\alpha\\begin{pmatrix}\n",
        "1 \\\\ 0\n",
        "\\end{pmatrix} + \\beta\\begin{pmatrix}0\\\\\n",
        "1\n",
        "\\end{pmatrix} = \\begin{pmatrix}\n",
        "\\alpha \\\\ \\beta\n",
        "\\end{pmatrix}\n",
        "$$\n",
        "\n",
        "From this, we can see that the state of a quantum bit is a unit vector in a two-dimensional complex inner product space with an orthonormal basis of $|0\\rangle$ and $|1\\rangle$. It is normalized to 1.\n",
        "\n",
        "$$\n",
        "\\langle\\psi|\\psi\\rangle = \\begin{pmatrix}\n",
        "\\alpha^* & \\beta^*\n",
        "\\end{pmatrix}\n",
        "\\begin{pmatrix}\n",
        "\\alpha \\\\\n",
        "\\beta\n",
        "\\end{pmatrix} = 1\n",
        "$$\n",
        "\n",
        "$ |\\psi\\rangle =\\begin{pmatrix}\n",
        "\\alpha \\\\ \\beta\n",
        "\\end{pmatrix}$ is also called the statevector.\n",
        "\n",
        "A single-qubit quantum state is also represented as\n",
        "\n",
        "$$\n",
        "|\\psi\\rangle\n",
        "=\\cos\\frac{\\theta}{2}|0\\rangle+e^{i\\varphi}\\sin\\frac{\\theta}{2}|1\\rangle\n",
        "=\\left( \\begin{pmatrix} \\cos\\frac{\\theta}{2}\\\\ e^{i\\varphi}\\sin\\frac{\\theta}{2}\n",
        "\\end{pmatrix}\\right)\n",
        "$$\n",
        "\n",
        "where $\\theta$ and $\\varphi$ are the angles of the Bloch sphere in the following figure.\n",
        "\n",
        "![Bloch sphere](https://eu-de.quantum.cloud.ibm.com/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/bloch.avif)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "86a3a654-3fb7-492c-bf4b-ecf23b4b71a6",
      "metadata": {},
      "source": [
        "In the next few code cells, we will build up basic calculations from constituent pieces in Qiskit. We'll construct an empty circuit and then add quantum operations, discussing the gates and visualizing their effects as we go.\n",
        "You can run the cell by \"Shift\" + \"Enter\". Import the libraries first.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "113bc3fe-3295-4524-9bf8-c1f36e51554b",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Import the qiskit library\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit_aer import AerSimulator\n",
        "from qiskit.quantum_info import Statevector\n",
        "from qiskit.visualization import plot_bloch_multivector\n",
        "from qiskit_ibm_runtime import Sampler\n",
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "from qiskit.visualization import plot_histogram"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dbb2272c-996f-46a9-b5b0-f62d60c4deb3",
      "metadata": {},
      "source": [
        "#### Prepare the quantum circuit\n",
        "\n",
        "We will create and draw a single-qubit circuit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "fdef9137-9e39-4b05-afa9-9091766053f6",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/fdef9137-9e39-4b05-afa9-9091766053f6-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Create the single-qubit quantum circuit\n",
        "qc = QuantumCircuit(1)\n",
        "\n",
        "# Draw the circuit\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "50ffcbab-e427-4582-9864-92e1491544a1",
      "metadata": {},
      "source": [
        "#### X gate\n",
        "\n",
        "The X gate is a $\\pi$ rotation around the $x$ axis of the Bloch sphere.\n",
        "Applying the X gate to $|0\\rangle$ results in $|1\\rangle$, and applying the X gate to $|1\\rangle$ results in $|0\\rangle$, so it is an operation similar to the classical NOT gate, and is also known as bit flip. The matrix representation of the X gate is below.\n",
        "\n",
        "$$\n",
        "X = \\begin{pmatrix}\n",
        "0 & 1 \\\\\n",
        "1 & 0 \\\\\n",
        "\\end{pmatrix}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "b3468430-0cbc-44ab-bd21-901436662a4b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/b3468430-0cbc-44ab-bd21-901436662a4b-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(1)  # Prepare the single-qubit quantum circuit\n",
        "\n",
        "# Apply a X gate to qubit 0\n",
        "qc.x(0)\n",
        "\n",
        "# Draw the circuit\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c944e04b-09b3-429b-82d8-12be6b94d86d",
      "metadata": {},
      "source": [
        "In IBM Quantum®, the initial state is set to $|0\\rangle$, so the quantum circuit above in matrix representation is\n",
        "\n",
        "$$\n",
        "X|0\\rangle=  \\begin{pmatrix}\n",
        "0 & 1 \\\\\n",
        "1 & 0\n",
        "\\end{pmatrix}\n",
        "\\begin{pmatrix}\n",
        "1 \\\\ 0\n",
        "\\end{pmatrix}\n",
        " =\\begin{pmatrix}\n",
        "0 \\\\ 1\n",
        "\\end{pmatrix} = |1\\rangle\n",
        "$$\n",
        "\n",
        "Next, let's run this circuit using a statevector simulator.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "efb727e8-f51e-4903-aa0f-e4c099316815",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Statevector([0.+0.j, 1.+0.j],\n",
            "            dims=(2,))\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/efb727e8-f51e-4903-aa0f-e4c099316815-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# See the statevector\n",
        "out_vector = Statevector(qc)\n",
        "print(out_vector)\n",
        "\n",
        "# Draw a Bloch sphere\n",
        "plot_bloch_multivector(out_vector)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b4262b2d-10d8-42a8-b632-4d4872ccc3c3",
      "metadata": {},
      "source": [
        "Vertical vector is displayed as row vector, with complex numbers (the imaginary part is indexed by $j$ ).\n",
        "\n",
        "#### H gate\n",
        "\n",
        "The Hadamard gate is a $\\pi$ rotation around an axis halfway between the $x$ and $z$ axes on the Bloch sphere. Applying the H gate to $|0\\rangle$ creates a superposition state such as $\\frac{|0\\rangle + |1\\rangle}{\\sqrt{2}}$. The matrix representation of the H gate is below.\n",
        "\n",
        "$$\n",
        "H = \\frac{1}{\\sqrt{2}}\\begin{pmatrix}\n",
        "1 & 1 \\\\\n",
        "1 & -1 \\\\\n",
        "\\end{pmatrix}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "574c35f0-26a9-423a-8d65-7140ba7398e3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/574c35f0-26a9-423a-8d65-7140ba7398e3-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(1)  # Create the single-qubit quantum circuit\n",
        "\n",
        "# Apply an Hadamard gate to qubit 0\n",
        "qc.h(0)\n",
        "\n",
        "# Draw the circuit\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "7adf0e93-6db3-4aa8-800f-c91c8cc46001",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Statevector([0.70710678+0.j, 0.70710678+0.j],\n",
            "            dims=(2,))\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/7adf0e93-6db3-4aa8-800f-c91c8cc46001-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# See the statevector\n",
        "out_vector = Statevector(qc)\n",
        "print(out_vector)\n",
        "\n",
        "# Draw a Bloch sphere\n",
        "plot_bloch_multivector(out_vector)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2c9b271a-7dcd-426f-b79d-378575f41dfb",
      "metadata": {},
      "source": [
        "This is\n",
        "\n",
        "$$\n",
        "H|0\\rangle= \\frac{1}{\\sqrt{2}} \\begin{pmatrix}\n",
        "1 & 1 \\\\\n",
        "1 & -1\n",
        "\\end{pmatrix}\n",
        "\\begin{pmatrix}\n",
        "1 \\\\0\n",
        "\\end{pmatrix}\n",
        " =\\frac{1}{\\sqrt{2}}\\begin{pmatrix}\n",
        "1 \\\\\n",
        "1\n",
        "\\end{pmatrix}\n",
        "=\\begin{pmatrix}\n",
        "0.707 \\\\\n",
        "0.707\n",
        "\\end{pmatrix}\n",
        "=\\frac{1}{\\sqrt{2}}(|0\\rangle+|1\\rangle)\n",
        "$$\n",
        "\n",
        "This superposition state is so common and important, that it is given its own symbol:\n",
        "\n",
        "$$\n",
        "|+\\rangle \\equiv \\frac{1}{\\sqrt{2}}(|0\\rangle+|1\\rangle).\n",
        "$$\n",
        "\n",
        "By applying the $H$ gate on the $|0\\rangle$, we created a superposition of $|0\\rangle$ and $|1\\rangle$ where measurement in the computational basis (along z in the Bloch sphere picture) would give you each state with equal probabilities.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "07fdfe64-f6ae-4995-8857-e6559ae4a3b6",
      "metadata": {},
      "source": [
        "#### $|-\\rangle$ state\n",
        "\n",
        "You might have guessed that there is a corresponding  $|-\\rangle$ state:\n",
        "\n",
        "$$\n",
        "|-\\rangle \\equiv \\frac{|0\\rangle -|1\\rangle}{\\sqrt{2}}.\n",
        "$$\n",
        "\n",
        "To create this state, first apply an X gate to make $|1\\rangle$, then apply an H gate.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "b8e96fc4-6708-415e-b8fc-ac69eaeae750",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/b8e96fc4-6708-415e-b8fc-ac69eaeae750-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(1)  # Create the single-qubit quantum circuit\n",
        "\n",
        "# Apply a X gate to qubit 0\n",
        "qc.x(0)\n",
        "\n",
        "# Apply an Hadamard gate to qubit 0\n",
        "qc.h(0)\n",
        "\n",
        "# draw the circuit\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "f42b82aa-7a15-4f81-8530-b997d4c6e0de",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Statevector([ 0.70710678+0.j, -0.70710678+0.j],\n",
            "            dims=(2,))\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/f42b82aa-7a15-4f81-8530-b997d4c6e0de-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# See the statevector\n",
        "out_vector = Statevector(qc)\n",
        "print(out_vector)\n",
        "\n",
        "# Draw a Bloch sphere\n",
        "plot_bloch_multivector(out_vector)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2d27e9ca-67be-4c69-8930-b70bbdf03b8d",
      "metadata": {},
      "source": [
        "This is\n",
        "\n",
        "$$\n",
        "H|1\\rangle= \\frac{1}{\\sqrt{2}} \\begin{pmatrix}\n",
        "1 & 1 \\\\\\\n",
        "1 & -1\n",
        "\\end{pmatrix}\n",
        "\\begin{pmatrix}\n",
        "0 \\\\\\\n",
        "1\n",
        "\\end{pmatrix}\n",
        " =\\frac{1}{\\sqrt{2}}\\begin{pmatrix}\n",
        "1 \\\\\\\n",
        "-1\n",
        "\\end{pmatrix}\n",
        "=\\begin{pmatrix}\n",
        "0.707 \\\\\\\n",
        "-0.707\n",
        "\\end{pmatrix}\n",
        "=\\frac{1}{\\sqrt{2}}(|0\\rangle-|1\\rangle) = |-\\rangle\n",
        "$$\n",
        "\n",
        "Applying the $H$ gate on $|1\\rangle$ results in an equal superposition of $|0\\rangle$ and $|1\\rangle$, but the sign of $|1\\rangle$ is negative.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bbc2aac6-cf44-45dd-a635-7b75fa197262",
      "metadata": {},
      "source": [
        "### 3.2 Single-qubit quantum state and unitary evolution\n",
        "\n",
        "The actions of all the gates we have seen so far have been *unitary*, which means they can be represented by a unitary operator. In other words, the output state can be obtained by acting on the initial state with a unitary matrix:\n",
        "\n",
        "$$\n",
        "|\\psi^{'}\\rangle = U|\\psi\\rangle\n",
        "$$\n",
        "\n",
        "A unitary matrix is a matrix satisfying\n",
        "\n",
        "$$\n",
        "U^{\\dagger}U =U U^{\\dagger} = I.\n",
        "$$\n",
        "\n",
        "In terms of quantum computer operation, we would say that applying a quantum gate to the qubit evolves the quantum state. Common single-qubit gates include the following.\n",
        "\n",
        "Pauli gates:\n",
        "\n",
        "$$\n",
        "X = \\begin{pmatrix}\n",
        "0 & 1 \\\\\n",
        "1 & 0 \\\\\n",
        "\\end{pmatrix}\n",
        "= |0\\rangle \\langle 1|+|1\\rangle \\langle 0|\n",
        "$$\n",
        "\n",
        "$$\n",
        "Y = \\begin{pmatrix}\n",
        "0 & -i \\\\\n",
        "i & 0 \\\\\n",
        "\\end{pmatrix}\n",
        "= -i|0\\rangle \\langle 1|+i|1\\rangle \\langle 0|\n",
        "$$\n",
        "\n",
        "$$\n",
        "Z = \\begin{pmatrix}\n",
        "1 & 0 \\\\\n",
        "0 & -1 \\\\\n",
        "\\end{pmatrix}\n",
        "= |0\\rangle \\langle 0|-|1\\rangle \\langle 1|\n",
        "$$\n",
        "\n",
        "where the outer product was calculated as follows:\n",
        "\n",
        "$$\n",
        "|0\\rangle \\langle 0|=\n",
        "\\begin{bmatrix}\n",
        "1 \\\\\n",
        "0\n",
        "\\end{bmatrix}\n",
        "\\begin{bmatrix}\n",
        "1 & 0\n",
        "\\end{bmatrix}\n",
        "=\\begin{bmatrix}\n",
        "1 & 0 \\\\\n",
        "0 & 0 \\\\\n",
        "\\end{bmatrix}, \\quad\n",
        "|1\\rangle \\langle 0|=\n",
        "\\begin{bmatrix}\n",
        "0 \\\\\n",
        "1\n",
        "\\end{bmatrix}\n",
        "\\begin{bmatrix}\n",
        "1 & 0\n",
        "\\end{bmatrix}\n",
        "=\\begin{bmatrix}\n",
        "0 & 0 \\\\\n",
        "1 & 0 \\\\\n",
        "\\end{bmatrix}, \\quad\n",
        "$$\n",
        "\n",
        "$$\n",
        "|0\\rangle \\langle 1|=\n",
        "\\begin{bmatrix}\n",
        "1 \\\\\n",
        "0\n",
        "\\end{bmatrix}\n",
        "\\begin{bmatrix}\n",
        "0 & 1\n",
        "\\end{bmatrix}\n",
        "=\\begin{bmatrix}\n",
        "0 & 1 \\\\\n",
        "0 & 0 \\\\\n",
        "\\end{bmatrix}, \\quad\n",
        "|1\\rangle \\langle 1|=\n",
        "\\begin{bmatrix}\n",
        "0 \\\\\n",
        "1\n",
        "\\end{bmatrix}\n",
        "\\begin{bmatrix}\n",
        "0 & 1\n",
        "\\end{bmatrix}\n",
        "=\\begin{bmatrix}\n",
        "0 & 0 \\\\\n",
        "0 & 1 \\\\\n",
        "\\end{bmatrix}, \\quad\n",
        "$$\n",
        "\n",
        "Other typical single-qubit gates:\n",
        "\n",
        "$$\n",
        "H= \\frac{1}{\\sqrt{2}}\\begin{bmatrix}\n",
        "1 & 1 \\\\\n",
        "1 & -1 \\\\\n",
        "\\end{bmatrix},\\quad\n",
        "S = \\begin{bmatrix}\n",
        "1 & 0 \\\\\n",
        "0 & i \\\\\n",
        "\\end{bmatrix}, \\quad\n",
        "T = \\begin{bmatrix}\n",
        "1 & 0 \\\\\n",
        "0 & exp(i\\pi/4) \\\\\n",
        "\\end{bmatrix}\n",
        "$$\n",
        "\n",
        "$$\n",
        "R_x(\\theta) = e^{-i\\theta X/2} = cos\\frac{\\theta}{2}I - i sin \\frac{\\theta}{2}X = \\begin{bmatrix}\n",
        "cos\\frac{\\theta}{2} &  -i sin \\frac{\\theta}{2} \\\\\n",
        "-i sin \\frac{\\theta}{2} & cos\\frac{\\theta}{2} \\\\\n",
        "\\end{bmatrix}\n",
        "$$\n",
        "\n",
        "$$\n",
        "R_y(\\theta) = e^{-i\\theta Y/2} = cos\\frac{\\theta}{2}I - i sin \\frac{\\theta}{2}Y = \\begin{bmatrix}\n",
        "cos\\frac{\\theta}{2} &  - sin \\frac{\\theta}{2} \\\\\n",
        "sin \\frac{\\theta}{2} & cos\\frac{\\theta}{2} \\\\\n",
        "\\end{bmatrix}\n",
        "$$\n",
        "\n",
        "$$\n",
        "R_z(\\theta) = e^{-i\\theta Z/2} = cos\\frac{\\theta}{2}I - i sin \\frac{\\theta}{2}Z = \\begin{bmatrix}\n",
        "e^{-i\\theta /2} &  0 \\\\\n",
        "0 & e^{i\\theta /2} \\\\\n",
        "\\end{bmatrix}\n",
        "$$\n",
        "\n",
        "The meaning and use of these are described in more detail in the [Basics of Quantum Information](/learning/courses/basics-of-quantum-information) course.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "39da8188-4ea3-420a-8467-29dd249ca93b",
      "metadata": {},
      "source": [
        "### Exercise 1\n",
        "\n",
        "Use Qiskit to create quantum circuits that prepare the states described below. Then run each circuit using the statevector simulator and display the resulting state on the Bloch sphere. As a bonus, see if you can anticipate what the final state should be based on intuition about the gates and rotations in the Bloch sphere.\n",
        "\n",
        "(1) $XX|0\\rangle$\n",
        "\n",
        "(2) $HH|0\\rangle$\n",
        "\n",
        "(3) $HZH|0\\rangle$\n",
        "\n",
        "Tips: Z gate can be used by\n",
        "\n",
        "qc.z(0)\n",
        "\n",
        "**Solution:**\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "148fdaf9-0398-4dd3-84b3-1a71a4f5d34e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/148fdaf9-0398-4dd3-84b3-1a71a4f5d34e-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "### (1) XX|0> ###\n",
        "\n",
        "# Create the single-qubit quantum circuit\n",
        "qc = QuantumCircuit(1)  ##your code goes here##\n",
        "\n",
        "# Add a X gate to qubit 0\n",
        "qc.x(0)  ##your code goes here##\n",
        "\n",
        "# Add a X gate to qubit 0\n",
        "qc.x(0)  ##your code goes here##\n",
        "\n",
        "# Draw a circuit\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "4720c4a0-acc7-46cc-b8ba-be2ca87ab976",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Statevector([1.+0.j, 0.+0.j],\n",
            "            dims=(2,))\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/4720c4a0-acc7-46cc-b8ba-be2ca87ab976-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# See the statevector\n",
        "out_vector = Statevector(qc)\n",
        "print(out_vector)\n",
        "\n",
        "# Draw a Bloch sphere\n",
        "plot_bloch_multivector(out_vector)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "361c09fe-c206-4355-b827-da7ede0848de",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/361c09fe-c206-4355-b827-da7ede0848de-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "### (2) HH|0> ###\n",
        "##your code goes here##\n",
        "qc = QuantumCircuit(1)\n",
        "qc.h(0)\n",
        "qc.h(0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "a4976a54-77e2-42b5-b492-49c8cdaf9c9f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Statevector([1.+0.j, 0.+0.j],\n",
            "            dims=(2,))\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/a4976a54-77e2-42b5-b492-49c8cdaf9c9f-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 14,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# See the statevector\n",
        "out_vector = Statevector(qc)\n",
        "print(out_vector)\n",
        "\n",
        "# Draw a Bloch sphere\n",
        "plot_bloch_multivector(out_vector)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "cd01ed0c-8f9e-4689-b1ae-f028d588f81a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/cd01ed0c-8f9e-4689-b1ae-f028d588f81a-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "### (3) HZH|0> ###\n",
        "##your code goes here##\n",
        "qc = QuantumCircuit(1)\n",
        "qc.h(0)\n",
        "qc.z(0)\n",
        "qc.h(0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "4bc91c2a-e097-44db-95bb-acf0d0ea0844",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Statevector([0.+0.j, 1.+0.j],\n",
            "            dims=(2,))\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/4bc91c2a-e097-44db-95bb-acf0d0ea0844-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 16,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# See the statevector\n",
        "out_vector = Statevector(qc)\n",
        "print(out_vector)\n",
        "\n",
        "# Draw a Bloch sphere\n",
        "plot_bloch_multivector(out_vector)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "59f4ee8b-7243-418c-8094-ae52e750fac1",
      "metadata": {},
      "source": [
        "### 3.3 Measurement\n",
        "\n",
        "Measurement is theoretically a very complicated topic. But in practical terms, making a measurement along $z$ (as all IBM® quantum computers do) simply forces the qubit’s state $\\alpha|0\\rangle+\\beta|1\\rangle \\quad (s.t.|\\alpha|^2+|\\beta|^2=1)$ either to $|0\\rangle$ or to $|1\\rangle,$ and we observe the outcome.\n",
        "\n",
        "* $|\\alpha|^2$ is the probability we will get $|0\\rangle$ when we measure.\n",
        "* $|\\beta|^2$ is the probability we will get $|1\\rangle$ when we measure.\n",
        "\n",
        "So, $\\alpha$ and $\\beta$ are called probability amplitudes. (see \"Born rule\")\n",
        "\n",
        "For example, $\\frac{\\sqrt{2}}{2}|0\\rangle+\\frac{\\sqrt{2}}{2}|1\\rangle$ has an equal probability of becoming $|0\\rangle$ or $|1\\rangle$ upon measurement. $\\frac{\\sqrt{3}}{2}|0\\rangle-\\frac{1}{2}i|1\\rangle$ has a 75% chance of becoming $|0\\rangle$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fb2c925a-e906-467b-b971-4663eb4751c5",
      "metadata": {},
      "source": [
        "#### Qiskit Aer Simulator\n",
        "\n",
        "Next, let's measure a circuit that prepares the equal probability superposition above.\n",
        "We should add the measurement gates, as the Qiskit Aer simulator simulates an ideal (with no noise) quantum hardware by default. Note: The Aer simulator can also apply a noise model based on real quantum computer. We will return to noise models later.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "3956e602-9f1b-4083-b58d-26c91b50b75e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/3956e602-9f1b-4083-b58d-26c91b50b75e-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Create a new circuit with one qubits (first argument) and one classical bits (second argument)\n",
        "qc = QuantumCircuit(1, 1)\n",
        "qc.h(0)\n",
        "qc.measure(0, 0)  # Add the measurement gate\n",
        "\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "95abf094-bd82-4a4a-ad12-29bec082d9c8",
      "metadata": {},
      "source": [
        "We are now ready to run our circuit on the Aer simulator. In this example, we will apply the default shots=1024, which means we will measure 1024 times. Then we will plot those counts in a histogram.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "id": "7cb7c5ab-7b12-4f77-aaca-1d7e6cff213c",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "{'0': 521, '1': 503}\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/7cb7c5ab-7b12-4f77-aaca-1d7e6cff213c-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 18,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Run the circuit on a simulator to get the results\n",
        "# Define backend\n",
        "backend = AerSimulator()\n",
        "\n",
        "# Transpile to backend\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "isa_qc = pm.run(qc)\n",
        "\n",
        "# Run the job\n",
        "sampler = Sampler(mode=backend)\n",
        "job = sampler.run([isa_qc])\n",
        "result = job.result()\n",
        "\n",
        "# Print the results\n",
        "counts = result[0].data.c.get_counts()\n",
        "print(counts)\n",
        "\n",
        "# Plot the counts in a histogram\n",
        "plot_histogram(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ea8c3435-8e76-4f04-9d50-d1eb575158d3",
      "metadata": {},
      "source": [
        "We see that 0s and 1s were measured with a probability of almost 50% each. Although noise has not been simulated here, the states are still probabilistic. So while we expect roughly a 50-50 distribution, we will rarely find exactly that. Just as 100 flips of a coin would rarely yield exactly 50 instances of each side.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "33d5a0ef-4eca-46d0-9c87-2f42b9a70ebb",
      "metadata": {},
      "source": [
        "## 4. Multi-qubit quantum gate and entanglement\n",
        "\n",
        "### 4.1 Multi-qubit quantum circuit\n",
        "\n",
        "We can create a two-qubit quantum circuit with following code. We will apply an H gate to each qubit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "id": "e880f7eb-108c-4387-8ef4-97219fd5691c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/e880f7eb-108c-4387-8ef4-97219fd5691c-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 19,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Create the two qubits quantum circuit\n",
        "qc = QuantumCircuit(2)\n",
        "\n",
        "# Apply an H gate to qubit 0\n",
        "qc.h(0)\n",
        "\n",
        "# Apply an H gate to qubit 1\n",
        "qc.h(1)\n",
        "\n",
        "# Draw the circuit\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "id": "28c4fdb1-122b-4399-a3ee-a24f6b2d36ca",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Statevector([0.5+0.j, 0.5+0.j, 0.5+0.j, 0.5+0.j],\n",
            "            dims=(2, 2))\n"
          ]
        }
      ],
      "source": [
        "# See the statevector\n",
        "out_vector = Statevector(qc)\n",
        "print(out_vector)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fa6412ee",
      "metadata": {},
      "source": [
        "#### Note: Qiskit bit ordering\n",
        "\n",
        "Qiskit uses **Little Endian** notation when ordering qubits and bits, meaning **qubit 0 is the rightmost bit** in the bitstrings. Example: $|01\\rangle$ means q0 is $|1\\rangle$ and q1 is $|0\\rangle$. Be careful because some literature in quantum computing use the Big Endian notation (qubit 0 is the leftmost bit) and a great deal of quantum mechanics literature does, too.\n",
        "\n",
        "Another thing to notice is that when representing a quantum circuit, $|q_0\\rangle$ is always placed at the top of the circuit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "905f20cf-3836-4766-bca1-05a4bd220d64",
      "metadata": {},
      "source": [
        "With this in mind, the quantum state of the above circuit can be written as a tensor product of single-qubit quantum state.\n",
        "\n",
        "$|q1\\rangle \\otimes|q0\\rangle = (a|0\\rangle+b|1\\rangle) \\otimes (c|0\\rangle+d|1\\rangle)$\n",
        "\n",
        "$= ac|0\\rangle|0\\rangle+ad|0\\rangle|1\\rangle+bc|1\\rangle|0\\rangle+bd|1\\rangle|1\\rangle$\n",
        "\n",
        "$= ac|00\\rangle+ad|01\\rangle+bc|10\\rangle+bd|11\\rangle$\n",
        "\n",
        "( $|ac|^2+ |ad|^2+ |bc|^2+ |bd|^2=1$ )\n",
        "\n",
        "The initial state of Qiskit is $|0\\rangle|0\\rangle=|00\\rangle$, so by applying $H$ to each qubit, it changes to a state of equal superposition.\n",
        "\n",
        "$H|0\\rangle \\otimes H|0\\rangle=\\frac{1}{\\sqrt{2}}(|0\\rangle+|1\\rangle) \\otimes \\frac{1}{\\sqrt{2}}(|0\\rangle+|1\\rangle) = \\frac{1}{2}(|00\\rangle+|01\\rangle+|10\\rangle+|11\\rangle)$\n",
        "\n",
        "$$\n",
        "=\\frac{1}{2}\\left( \\begin{pmatrix} 1 \\\\ 1 \\end{pmatrix} \\otimes \\begin{pmatrix} 1 \\\\ 1 \\end{pmatrix}\\right) = \\frac{1}{2}\\begin{pmatrix} 1 \\\\ 1 \\\\ 1 \\\\ 1 \\end{pmatrix}=\\frac{1}{2}\\left(\\begin{pmatrix} 1 \\\\ 0 \\\\ 0 \\\\ 0 \\end{pmatrix}+\\begin{pmatrix} 0 \\\\ 1 \\\\ 0 \\\\ 0 \\end{pmatrix}+\\begin{pmatrix} 0 \\\\ 0 \\\\ 1 \\\\ 0 \\end{pmatrix}+\\begin{pmatrix} 0 \\\\ 0 \\\\ 0 \\\\ 1 \\end{pmatrix}\\right)\n",
        "$$\n",
        "\n",
        "The measurement rule is also same as a single qubit case, the probability of measuring $|00\\rangle$ is $|ac|^2$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "id": "ebdf591f-18d0-4fd1-a3a3-b1cdac13bd97",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/ebdf591f-18d0-4fd1-a3a3-b1cdac13bd97-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 21,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Draw a Bloch sphere\n",
        "plot_bloch_multivector(out_vector)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "528cbdb3-eb30-42f2-a493-00ed22c09056",
      "metadata": {},
      "source": [
        "Next, let's measure this circuit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "2afdd5ac-e51a-4d94-9307-955cc8fbf821",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/2afdd5ac-e51a-4d94-9307-955cc8fbf821-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 22,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Create a new circuit with two qubits (first argument) and two classical bits (second argument)\n",
        "qc = QuantumCircuit(2, 2)\n",
        "\n",
        "# Apply the gates\n",
        "qc.h(0)\n",
        "qc.h(1)\n",
        "\n",
        "# Add the measurement gates\n",
        "qc.measure(0, 0)  # Measure qubit 0 and save the result in bit 0\n",
        "qc.measure(1, 1)  # Measure qubit 1 and save the result in bit 1\n",
        "\n",
        "# Draw the circuit\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e94b24d5-1c35-46f4-a7f7-fd4849f10473",
      "metadata": {},
      "source": [
        "Now, we will use a Aer simulator, again, to experimentally verify that the relative probabilities of all possible output states are roughly equal.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "id": "060512ac-a106-4ecd-94f5-119048a08467",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "{'10': 262, '01': 246, '00': 265, '11': 251}\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/060512ac-a106-4ecd-94f5-119048a08467-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 23,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Run the circuit on a simulator to get the results\n",
        "# Define backend\n",
        "backend = AerSimulator()\n",
        "\n",
        "# Transpile to backend\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "isa_qc = pm.run(qc)\n",
        "\n",
        "# Run the job\n",
        "sampler = Sampler(mode=backend)\n",
        "job = sampler.run([isa_qc])\n",
        "result = job.result()\n",
        "\n",
        "# Print the results\n",
        "counts = result[0].data.c.get_counts()\n",
        "print(counts)\n",
        "\n",
        "# Plot the counts in a histogram\n",
        "plot_histogram(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c4875883-3bb3-4537-aa6e-0d46b67c49e3",
      "metadata": {},
      "source": [
        "As expected, the states $|00\\rangle$, $|01\\rangle$, $|10\\rangle$, $|11\\rangle$ were measured almost 25% each.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d28f149c-b02a-4c4f-b0c5-2252b5dd01fc",
      "metadata": {},
      "source": [
        "### 4.2 Multi-qubit quantum gates\n",
        "\n",
        "#### CNOT gate\n",
        "\n",
        "A CNOT(\"controlled NOT\" or CX) gate is a two-qubit gate, meaning its action involves two qubits at once: the control qubit and the target qubit. A CNOT flips the target qubit only when the control qubit is $|1\\rangle$.\n",
        "\n",
        "| Input (target,control) | Output (target,control) |\n",
        "| :--------------------: | :---------------------: |\n",
        "|           00           |            00           |\n",
        "|           01           |            11           |\n",
        "|           10           |            10           |\n",
        "|           11           |            01           |\n",
        "\n",
        "Let us first simulate the action of this two-qubit gate when q0 and q1 are both $|0\\rangle$, and obtain the output statevector. The Qiskit syntax used is `qc.cx(control qubit, target qubit)`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "id": "a5621efd-dd9f-4ea4-bf3a-be3cacb45287",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/a5621efd-dd9f-4ea4-bf3a-be3cacb45287-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 24,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Create a circuit with two quantum registers and two classical registers\n",
        "qc = QuantumCircuit(2, 2)\n",
        "\n",
        "# Apply the CNOT (cx) gate to a |00> state.\n",
        "qc.cx(0, 1)  # Here the control is set to q0 and the target is set to q1.\n",
        "\n",
        "# Draw the circuit\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "id": "6dcea9ac-c9c3-4211-8d62-6ae9beb9e723",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Statevector([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],\n",
            "            dims=(2, 2))\n"
          ]
        }
      ],
      "source": [
        "# See the statevector\n",
        "out_vector = Statevector(qc)\n",
        "print(out_vector)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "62d9fb42-6498-4e5a-b625-f5e3be15c36c",
      "metadata": {},
      "source": [
        "As expected, applying a CNOT gate on $|00\\rangle$ did not change the state, since the control qubit was in the $|0\\rangle$ state.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "af0c98e9-d440-4899-bee5-22591d395f33",
      "metadata": {},
      "source": [
        "Let's get back to our CNOT operation. This time we will apply a CNOT gate to $|01\\rangle$ and see what happens.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "id": "5a02de82-44ff-40eb-b64c-2389d6eae3ee",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/5a02de82-44ff-40eb-b64c-2389d6eae3ee-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 26,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(2, 2)\n",
        "\n",
        "# q0=1, q1=0\n",
        "qc.x(0)  # Apply a X gate to initialize q0 to 1\n",
        "qc.cx(0, 1)  # Set the control bit to q0 and the target bit to q1.\n",
        "\n",
        "# Draw the circuit\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "id": "f878f9fb-4142-4a6e-a4dd-ef2e2e2d5118",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Statevector([0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],\n",
            "            dims=(2, 2))\n"
          ]
        }
      ],
      "source": [
        "# See the statevector\n",
        "out_vector = Statevector(qc)\n",
        "print(out_vector)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0ed70dbf-4161-4edc-8035-681034acb4e0",
      "metadata": {},
      "source": [
        "By applying a CNOT gate, the $|01\\rangle$ state has now become $|11\\rangle$.\n",
        "\n",
        "Let us verify these results by running the circuit on a simulator.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 28,
      "id": "abcafb77-20bf-4bb7-bf8d-57f33af280c1",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/abcafb77-20bf-4bb7-bf8d-57f33af280c1-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 28,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Add measurements\n",
        "qc.measure(0, 0)\n",
        "qc.measure(1, 1)\n",
        "\n",
        "# Draw the circuit\n",
        "qc.draw(output=\"mpl\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 29,
      "id": "88b76f1d-083b-4f28-b415-380738d22599",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "{'11': 1024}\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/88b76f1d-083b-4f28-b415-380738d22599-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 29,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Run the circuit on a simulator to get the results\n",
        "# Define backend\n",
        "backend = AerSimulator()\n",
        "\n",
        "# Transpile to backend\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "isa_qc = pm.run(qc)\n",
        "\n",
        "# Run the job\n",
        "sampler = Sampler(backend)\n",
        "job = sampler.run([isa_qc])\n",
        "result = job.result()\n",
        "\n",
        "# Print the results\n",
        "counts = result[0].data.c.get_counts()\n",
        "print(counts)\n",
        "\n",
        "# Plot the counts in a histogram\n",
        "plot_histogram(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "86b95716-0817-4466-9f8f-3a212e0c08e3",
      "metadata": {},
      "source": [
        "The results should show you that $|11\\rangle$ has been measured with 100% probability.\n",
        "\n",
        "### 4.3 Quantum entanglement and execution on a real quantum device\n",
        "\n",
        "Let's start by introducing a specific entangled state which is particularly important in quantum computation, then we'll define the term \"entangled\":\n",
        "\n",
        "$$\n",
        "\\frac{1}{\\sqrt{2}}|00\\rangle + \\frac{1}{\\sqrt{2}}|11\\rangle\n",
        "$$\n",
        "\n",
        "and this state is called a **Bell state**.\n",
        "\n",
        "An entangled state is a state $|\\psi_{AB}\\rangle$ consisting of quantum states $|\\psi_A\\rangle$ and $|\\psi_B\\rangle$ that cannot be represented by a tensor product of individual quantum states.\n",
        "\n",
        "If $|\\psi_{AB}\\rangle$ below has two states $|\\psi\\rangle_A$ and $|\\psi\\rangle_B$;\n",
        "\n",
        "$$\n",
        "|\\psi_{AB}\\rangle = \\frac{1}{\\sqrt{2}}(|00\\rangle +|11\\rangle) = \\frac{1}{\\sqrt{2}}(|0\\rangle_A|0\\rangle_B +|1\\rangle_A|1\\rangle_B)\n",
        "$$\n",
        "\n",
        "$$\n",
        "|\\psi\\rangle_A = a_0|0\\rangle+a_1|1\\rangle\n",
        "$$\n",
        "\n",
        "$$\n",
        "|\\psi\\rangle_B = b_0|0\\rangle+b_1|1\\rangle\n",
        "$$\n",
        "\n",
        "the tensor product of these two states is the following\n",
        "\n",
        "$$\n",
        "|\\psi\\rangle _A\\otimes |\\psi\\rangle _B = a_0 b_0|00\\rangle+a_0 b_1|01\\rangle+a_1 b_0|10\\rangle+a_1 b_1|11\\rangle\n",
        "$$\n",
        "\n",
        "but there are no coefficients $a_0, a_1, b_0, $ and $b_1$ to satisfy these two equations. Therefore, $|\\psi_{AB}\\rangle$ is not represented by a tensor product of individual quantum state, $|\\psi\\rangle_A$ and $|\\psi\\rangle_B$, and this means that $|\\psi_{AB}\\rangle =  \\frac{1}{\\sqrt{2}}(|00\\rangle +|11\\rangle)$ is entangled state.\n",
        "\n",
        "Let us create the Bell state and run it on a real quantum computer. Now we will follow the four steps to writing a quantum program, called **Qiskit patterns**:\n",
        "\n",
        "1. Map problem to quantum circuits and operators\n",
        "2. Optimize for target hardware\n",
        "3. Execute on target hardware\n",
        "4. Post-process the results\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "126a32f5-9a11-4428-aa50-6cb3193cd1d6",
      "metadata": {},
      "source": [
        "#### Step 1. Map problem to quantum circuits and operators\n",
        "\n",
        "In a quantum program, quantum circuits are the native format in which to represent quantum instructions. When creating a circuit, you'll usually create a new QuantumCircuit object, then add instructions to it in sequence.\n",
        "\n",
        "The following code cell creates a circuit that produces a Bell state, the specific two-qubit entangled state from above.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 30,
      "id": "5fdd9317-8fab-46ee-ac6d-25ef031dd52b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/5fdd9317-8fab-46ee-ac6d-25ef031dd52b-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 30,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(2, 2)\n",
        "\n",
        "qc.h(0)\n",
        "qc.cx(0, 1)\n",
        "\n",
        "qc.measure(0, 0)\n",
        "qc.measure(1, 1)\n",
        "\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b3c9d5c2-7f53-4283-84bf-fbaa68e620c6",
      "metadata": {},
      "source": [
        "#### Step 2. Optimize for target hardware\n",
        "\n",
        "Qiskit converts abstract circuits to QISA (Quantum Instruction Set Architecture) circuits that respect the constraints of the target hardware and optimizes circuit performance. So before the optimization, we will specify the target hardware.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a426fb27-ac0b-4d1e-840c-21729ca630ce",
      "metadata": {},
      "source": [
        "If you do not have `qiskit-ibm-runtime`, you will need to install this first. For more information about Qiskit Runtime, [check out the API reference.](/docs/api/qiskit-ibm-runtime/runtime-service)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 31,
      "id": "1ef65ed1-926d-4f00-850d-4fb8750123a3",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Install\n",
        "# !pip install qiskit-ibm-runtime"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7170222f-2cd5-4482-8044-e126d8d53797",
      "metadata": {},
      "source": [
        "We will specify the target hardware.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a152031e-d4b6-468c-8ea4-441fe1c3c948",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "service.backends()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "2f07a360-adf5-467b-ac97-d466c0907dc6",
      "metadata": {},
      "outputs": [],
      "source": [
        "# You can specify the device\n",
        "# backend = service.backend('ibm_kingston')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "7c3072b3-69fb-4f56-9a92-6d49c5598c5e",
      "metadata": {},
      "outputs": [],
      "source": [
        "# You can also identify the least busy device\n",
        "backend = service.least_busy(operational=True)\n",
        "print(\"The least busy device is \", backend)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f7a015bb-1813-4acf-97e5-8489711b53fb",
      "metadata": {},
      "source": [
        "Transpiling the circuit is yet another complex process. Very briefly, this rewrites the circuit into a logically equivalent one using \"native gates\" (gates that a particular quantum computer can implement) and maps the qubits in your circuit to optimal real qubits on the target quantum computer. For more on transpilation, see this [documentation](/docs/api/qiskit/transpiler#overview).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "0fd980c2-386b-4583-b032-fa8375cb286c",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Transpile the circuit into basis gates executable on the hardware\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "target_circuit = pm.run(qc)\n",
        "\n",
        "target_circuit.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1f689582-b474-46aa-aa9f-208428db538a",
      "metadata": {},
      "source": [
        "You can see that in the transpilation the circuit was rewritten using new gates. For more information, refer to the [ECRGate](/docs/api/qiskit/qiskit.circuit.library.ECRGate#ecrgate) documentation.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fdd46180-c519-4c03-a09b-382be5140306",
      "metadata": {},
      "source": [
        "#### Step 3. Execute the target circuit\n",
        "\n",
        "Now, we will run the target circuit on the real device.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "9b4c27e3-8696-4246-b09d-0a4174eefeb9",
      "metadata": {},
      "outputs": [],
      "source": [
        "sampler = Sampler(backend)\n",
        "job_real = sampler.run([target_circuit])\n",
        "\n",
        "job_id = job_real.job_id()\n",
        "print(\"job id:\", job_id)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "aa8c88f1-d1ec-43c8-aafe-c9ab7cbb6dc2",
      "metadata": {},
      "source": [
        "Execution on the real device might require waiting in a queue, since quantum computers are valuable resources, and very much in demand. The job\\_id is used to check the execution status and results of the job later.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "666985b8-90bb-4724-bb13-9965930a84cc",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Check the job status (replace the job id below with your own)\n",
        "job_real.status(job_id)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d568cee6-69f4-4e3a-89a2-4826720d2d60",
      "metadata": {},
      "source": [
        "You can also check the job status from your IBM Quantum dashboard：[https://quantum.cloud.ibm.com/workloads](/workloads)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "664ce0ec-0ddb-4438-8e68-d36e8b67204f",
      "metadata": {},
      "outputs": [],
      "source": [
        "# If the Notebook session got disconnected you can also check your job status by running the following code\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "job_real = service.job(job_id)  # Input your job-id between the quotations\n",
        "job_real.status()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "b69e3456-6047-436a-8276-13ca6a69188c",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Execute after job has successfully run\n",
        "result_real = job_real.result()\n",
        "print(result_real[0].data.c.get_counts())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "554b7575-413e-4957-83db-9131a0b4bdaf",
      "metadata": {},
      "source": [
        "#### Step 4. Post-process the results\n",
        "\n",
        "Finally, we must post-process our results to create outputs in the expected format, like values or graphs.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "e22b1077-8311-4887-a7b3-c81006ba4eff",
      "metadata": {},
      "outputs": [],
      "source": [
        "plot_histogram(result_real[0].data.c.get_counts())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "240c2033-9f06-4f58-9075-5da1aa0f2dc5",
      "metadata": {},
      "source": [
        "As you can see, $|00\\rangle$ and $|11\\rangle$ are the most frequently observed. There are a few results other than the expected data, and they are due to noise and qubit decoherence. We will learn more about errors and noise in quantum computers in the later lessons of this course.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8dfaf680-c957-4250-bd40-b39d60afd38e",
      "metadata": {},
      "source": [
        "### 4.4 GHZ state\n",
        "\n",
        "The concept of entanglement can be extended to systems of more than two qubits. The GHZ state (Greenberger-Horne-Zeilinger state) is a maximally entangled state of three or more qubits. The GHZ state for three qubits is defined as\n",
        "\n",
        "$$\n",
        "\\frac{1}{\\sqrt 2}(|000\\rangle + |111\\rangle)\n",
        "$$\n",
        "\n",
        "It can be created with the following quantum circuit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 40,
      "id": "459b6162-3a54-41fe-9b67-9c1f8e731ebc",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/459b6162-3a54-41fe-9b67-9c1f8e731ebc-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 40,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(3, 3)\n",
        "\n",
        "qc.h(0)\n",
        "qc.cx(0, 1)\n",
        "qc.cx(1, 2)\n",
        "\n",
        "qc.measure(0, 0)\n",
        "qc.measure(1, 1)\n",
        "qc.measure(2, 2)\n",
        "\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6fa6efe6-d4bb-42ef-a7cc-3faf4ddf7115",
      "metadata": {},
      "source": [
        "The \"depth\" of a quantum circuit is a useful and common metric to describe quantum circuits. Trace a path through the quantum circuit, moving left to right, only changing qubits when they are connected by a multi-qubit gate. Count the number of gates along that path. The maximum number of gates for any such path through a circuit is the depth. In modern noisy quantum computers, low-depth circuits have fewer errors and are likely to return good results. Very deep circuits are not.\n",
        "\n",
        "Using `QuantumCircuit.depth()`, we can check the depth of our quantum circuit. The depth of the above circuit is 4. The top qubit has only three gates including the measurement. But there is a path from the top qubit down to either qubit 1 or qubit 2 which involves another CNOT gate.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 41,
      "id": "612505ab-1e11-467b-b5bf-6e18bd81256d",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "4"
            ]
          },
          "execution_count": 41,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc.depth()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "91c157ed-0fc5-40a8-8092-341bca361da3",
      "metadata": {},
      "source": [
        "### Exercise 2\n",
        "\n",
        "The GHZ state of an 8-qubit system is\n",
        "\n",
        "$$\n",
        "\\frac{1}{\\sqrt 2}(|00000000\\rangle + |11111111\\rangle)\n",
        "$$\n",
        "\n",
        "Write code to prepare this state with the shallowest possible circuit. The depth of the shallowest quantum circuit is 5, including the measurement gates.\n",
        "\n",
        "**Solution**:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 42,
      "id": "153eefc8-f021-41ee-97c4-a9555370f197",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/153eefc8-f021-41ee-97c4-a9555370f197-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 42,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Step 1\n",
        "qc = QuantumCircuit(8, 8)\n",
        "\n",
        "##your code goes here##\n",
        "qc.h(0)\n",
        "qc.cx(0, 4)\n",
        "qc.cx(4, 6)\n",
        "qc.cx(6, 7)\n",
        "\n",
        "qc.cx(4, 5)\n",
        "\n",
        "qc.cx(0, 2)\n",
        "qc.cx(2, 3)\n",
        "\n",
        "qc.cx(0, 1)\n",
        "qc.barrier()  # for visual separation\n",
        "\n",
        "# measure\n",
        "for i in range(8):\n",
        "    qc.measure(i, i)\n",
        "\n",
        "qc.draw(\"mpl\")\n",
        "# print(qc.depth())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 43,
      "id": "0d44521b-e08b-4445-a6ed-6ec2ac550142",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "5\n"
          ]
        }
      ],
      "source": [
        "print(qc.depth())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 46,
      "id": "0daedbeb-c75c-4bcf-b6e0-1f9fa0403b0d",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "{'11111111': 535, '00000000': 489}\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/bits-gates-and-circuits/extracted-outputs/0daedbeb-c75c-4bcf-b6e0-1f9fa0403b0d-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 46,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import plot_histogram\n",
        "# Step 2\n",
        "# For this exercise, the circuit and operators are simple, so no optimizations are needed.\n",
        "\n",
        "# Step 3\n",
        "# Run the circuit on a simulator to get the results\n",
        "backend = AerSimulator()\n",
        "\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "isa_qc = pm.run(qc)\n",
        "\n",
        "sampler = Sampler(mode=backend)\n",
        "job = sampler.run([isa_qc], shots=1024)\n",
        "result = job.result()\n",
        "\n",
        "counts = result[0].data.c.get_counts()\n",
        "print(counts)\n",
        "\n",
        "# Step 4\n",
        "# Plot the counts in a histogram\n",
        "\n",
        "plot_histogram(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d4057c5b-2dab-4590-afda-89d8cd7d26d5",
      "metadata": {},
      "source": [
        "## 5. Summary\n",
        "\n",
        "You have learned quantum computation with the circuit model using quantum bits and gates, and you have reviewed superposition, measurement, and entanglement. You also have learned the method to execute the quantum circuit on the real quantum device.\n",
        "\n",
        "In the final exercise to create a GHZ circuit, you have tried to reduce the circuit depth, which is an important factor for obtaining a utility scale solution in a noisy quantum computer.  In the later lessons of this course, you will learn about noise and about error mitigation methods in detail. In this lesson, as an introduction, we considered reducing the circuit depth in an ideal device, but in reality, we must consider the constraints of real device, such as qubit connectivity.  You will learn more about this in subsequent lessons in this course.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 45,
      "id": "eb838405-b298-4a81-ab23-9d0744090b9c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'2.0.2'"
            ]
          },
          "execution_count": 45,
          "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": 5
}