{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b97a7e0a-66a6-46b2-b33f-47feeefad60d",
      "metadata": {},
      "source": [
        "---\n",
        "title: Utility II\n",
        "description: This notebook follows the methods and techniques of lesson 7. Our goal is to numerically solve the time-dependent Schrödinger equation.\n",
        "---\n",
        "\n",
        "{/* cspell:ignore sharex */}\n",
        "\n",
        "# Utility-scale experiment II\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Yukio Kawashima (12 July 2024)\n",
        "\n",
        "  [Download the pdf](https://ibm.ent.box.com/s/bipgoms7gr6b6vhkoc1uw6oi4wsanfoq) 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 2 m 30 s.*\n",
        "\n",
        "  (Note that this notebook used texts, illustration, and codes from a now-deprecated [tutorial notebook](https://github.com/qiskit-community/qiskit-algorithms/blob/main/docs/tutorials/13_trotterQRTE.ipynb) for Qiskit Algorithms.)\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "76421ffc-f47f-46a4-8198-af3bc21e3c5d",
      "metadata": {},
      "source": [
        "## 1. Introduction and review of time-evolution\n",
        "\n",
        "This notebook follows the methods and techniques of lesson 7. Our goal is to numerically solve the time-dependent Schrödinger equation. As discussed in lesson 7, Trotterization consists in the successive application of a quantum gate or gates, chosen to approximate the time evolution of a system for a time slice. We repeat that discussion here for convenience. Feel free to skip to the code cells below if you have recently reviewed lesson 7.\n",
        "\n",
        "Following from the Schrödinger equation, the time evolution of a system initially in the state $\\vert\\psi(0)\\rangle$ takes the form:\n",
        "\n",
        "$$\n",
        "\\vert \\psi(t) \\rangle = e^{-i H t} \\vert \\psi(0) \\rangle \\text{,}\n",
        "$$\n",
        "\n",
        "where $H$ is the time-independent Hamiltonian governing the system. We consider a Hamiltonian that can be written as a weighted sum of Pauli terms $H=\\sum_j a_j P_j$, with $P_j$ representing a tensor product of Pauli terms acting on $n$ qubits. In particular, these Pauli terms might commute with one another, or they might not. Given a state at time $t=0$, how do we obtain the system's state at a later time $|\\psi(t)\\rangle$ using a quantum computer? The exponential of an operator can be most easily understood through its Taylor series:\n",
        "\n",
        "$$\n",
        "e^{-i H t} = 1-iHt-\\frac{1}{2}H^2t^2+...\n",
        "$$\n",
        "\n",
        "Some very basic exponentials, like $e^{iZ}$ can be implemented easily on quantum computers using a compact set of quantum gates. Most Hamiltonians of interest will not have just a single term, but will instead have many terms. Note what happens if $H = H_1+H_2$:\n",
        "\n",
        "$$\n",
        "e^{-i H t} = 1-i(H_1+H_2)t-\\frac{1}{2}(H_1+H_2)^2t^2+...\n",
        "$$\n",
        "\n",
        "When $H_1$ and $H_2$ commute, we have the familiar case (which is also true for numbers, and variables $a$ and $b$ below):\n",
        "\n",
        "$$\n",
        "e^{-i (a+b) t} = e^{-i a t}e^{-i b t}\n",
        "$$\n",
        "\n",
        "But when operators do not commute, terms cannot be rearranged in the Taylor series to simplify in this way. Thus, expressing complicated Hamiltonians in quantum gates is a challenge.\n",
        "\n",
        "One solution is to consider very small time $t$, such that the first-order term in the Taylor expansion dominates. Under that assumption:\n",
        "\n",
        "$$\n",
        "e^{-i (H_1+H_2) t} \\approx 1-i(H_1+H_2)t \\approx (1-i H_1 t)(1-i H_2 t) \\approx e^{-i H_1 t}e^{-i H_2 t}\n",
        "$$\n",
        "\n",
        "Of course, we might need to evolve our state for a longer time. That is accomplished by using many such small steps in time. This process is called Trotterization:\n",
        "\n",
        "$$\n",
        "\\vert \\psi(t) \\rangle \\approx \\left(\\prod_j e^{-i a_j P_j t/r} \\right)^r \\vert\\psi(0) \\rangle \\text{,}\n",
        "$$\n",
        "\n",
        "Here $t/r$ is the time slice (evolution step) that we are choosing. As a result, a gate to be applied $r$ times is created. A smaller timestep leads to a more accurate approximation. However, this also leads to deeper circuits which, in practice, leads to more error accumulation (a non-negligible concern on near-term quantum devices).\n",
        "\n",
        "Today, we will study the time evolution of the [Ising model](https://en.wikipedia.org/wiki/Ising_model) on linear lattices of $N=2$ and $N=6$ sites. These lattices consist of an array of spins $\\sigma_i$ that interact only with their nearest neighbors. These spins can have two orientations: $\\uparrow$ and $\\downarrow$, which correspond to a magnetization of $+1$ and $-1$ respectively.\n",
        "\n",
        "$$\n",
        "H = - J \\sum_{i=0}^{N-2} Z_i Z_{i+1} - h \\sum_{i=0}^{N-1} X_i  \\text{,}\n",
        "$$\n",
        "\n",
        "where $J$ describes the interaction energy, and $h$ the magnitude of an external field (in the x-direction above, but we will modify this). Let us write this expression using Pauli matrices, and considering that the external field has an angle $\\alpha$ with respect to the transversal direction,\n",
        "\n",
        "$$\n",
        "H = -J \\sum_{i=0}^{N-2} Z_i Z_{i+1} -h \\sum_{i=0}^{N-1} (\\sin\\alpha Z_i + \\cos\\alpha X_i) \\text{.}\n",
        "$$\n",
        "\n",
        "This Hamiltonian is useful in that it allows us to easily study the effects of an external field. In the computational basis, the system will be encoded as follows:\n",
        "\n",
        "|       Quantum state      |             Spin representation            |\n",
        "| :----------------------: | :----------------------------------------: |\n",
        "| $\\lvert 0 0 0 0 \\rangle$ |     $\\uparrow\\uparrow\\uparrow\\uparrow$     |\n",
        "| $\\lvert 1 0 0 0 \\rangle$ |    $\\downarrow\\uparrow\\uparrow\\uparrow$    |\n",
        "|         $\\ldots$         |                  $\\ldots$                  |\n",
        "| $\\lvert 1 1 1 1 \\rangle$ | $\\downarrow\\downarrow\\downarrow\\downarrow$ |\n",
        "\n",
        "We will start investigating the time evolution of such a quantum system. More specifically, we will visualize the time-evolution of certain properties of the system like magnetization.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "81aff7b3-67e5-453b-9f5b-68baf5209560",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'2.0.2'"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Check the version of Qiskit\n",
        "import qiskit\n",
        "\n",
        "qiskit.__version__"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "c88eda88-da8a-4e5e-9b8b-53ac0d0ed91b",
      "metadata": {
        "scrolled": true,
        "tags": []
      },
      "outputs": [],
      "source": [
        "# Import the qiskit library\n",
        "\n",
        "import numpy as np\n",
        "import warnings\n",
        "\n",
        "from qiskit import QuantumCircuit, QuantumRegister\n",
        "from qiskit.circuit.library import PauliEvolutionGate\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.synthesis import LieTrotter\n",
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "\n",
        "from qiskit_aer import AerSimulator\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService, Estimator\n",
        "\n",
        "warnings.filterwarnings(\"ignore\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ed6c1602-d994-46d6-9426-d38272a63d56",
      "metadata": {},
      "source": [
        "## 2. Defining the transverse-field Ising Hamiltonian\n",
        "\n",
        "We here consider the 1-D transverse-field Ising model.\n",
        "\n",
        "First, we will create a function that takes in the system parameters $N$, $J$, and $h$, and returns our Hamiltonian as a `SparsePauliOp`. A [SparsePauliOp](/docs/api/qiskit/qiskit.quantum_info.SparsePauliOp) is a sparse representation of an operator in terms of weighted [Pauli](/docs/api/qiskit/qiskit.quantum_info.Pauli) terms.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b3137f47-640a-4382-95b6-6bb9e760bc96",
      "metadata": {},
      "source": [
        "### 2.1 Activity 1\n",
        "\n",
        "Construct a function to build a transverse-field Ising Hamiltonian (see the equation above) with arguments of \"the number of qubits\", \"J parameter\", and \"h parameter\". Try this on your own using previous examples. Scroll down for the solution.\n",
        "\n",
        "**Solution:**\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "3de92af7-7504-4dca-b0b4-0d934f0c2069",
      "metadata": {},
      "outputs": [],
      "source": [
        "def get_hamiltonian(nqubits, J, h):\n",
        "    # List of Hamiltonian terms as 3-tuples containing\n",
        "    # (1) the Pauli string,\n",
        "    # (2) the qubit indices corresponding to the Pauli string,\n",
        "    # (3) the coefficient.\n",
        "    ZZ_tuples = [(\"ZZ\", [i, i + 1], -J) for i in range(0, nqubits - 1)]\n",
        "    X_tuples = [(\"X\", [i], -h) for i in range(0, nqubits)]\n",
        "\n",
        "    # We create the Hamiltonian as a SparsePauliOp, via the method\n",
        "    # `from_sparse_list`, and multiply by the interaction term.\n",
        "    hamiltonian = SparsePauliOp.from_sparse_list(\n",
        "        [*ZZ_tuples, *X_tuples], num_qubits=nqubits\n",
        "    )\n",
        "    return hamiltonian.simplify()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8b147fb0-6c3e-4eaf-8553-8850b53ff121",
      "metadata": {},
      "source": [
        "We will start investigating the time evolution of a quantum system, while keeping track of magnetization.\n",
        "We here compare the results of the Statevector and Matrix Product State simulators.\n",
        "\n",
        "#### Define the Hamiltonian\n",
        "\n",
        "The system that we now consider has a size of $N=20$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "56764f93-3851-4b1c-b9e2-ea34161ddd85",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "SparsePauliOp(['IIIIIIIIIIIIIIIIIIZZ', 'IIIIIIIIIIIIIIIIIZZI', 'IIIIIIIIIIIIIIIIZZII', 'IIIIIIIIIIIIIIIZZIII', 'IIIIIIIIIIIIIIZZIIII', 'IIIIIIIIIIIIIZZIIIII', 'IIIIIIIIIIIIZZIIIIII', 'IIIIIIIIIIIZZIIIIIII', 'IIIIIIIIIIZZIIIIIIII', 'IIIIIIIIIZZIIIIIIIII', 'IIIIIIIIZZIIIIIIIIII', 'IIIIIIIZZIIIIIIIIIII', 'IIIIIIZZIIIIIIIIIIII', 'IIIIIZZIIIIIIIIIIIII', 'IIIIZZIIIIIIIIIIIIII', 'IIIZZIIIIIIIIIIIIIII', 'IIZZIIIIIIIIIIIIIIII', 'IZZIIIIIIIIIIIIIIIII', 'ZZIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIX', 'IIIIIIIIIIIIIIIIIIXI', 'IIIIIIIIIIIIIIIIIXII', 'IIIIIIIIIIIIIIIIXIII', 'IIIIIIIIIIIIIIIXIIII', 'IIIIIIIIIIIIIIXIIIII', 'IIIIIIIIIIIIIXIIIIII', 'IIIIIIIIIIIIXIIIIIII', 'IIIIIIIIIIIXIIIIIIII', 'IIIIIIIIIIXIIIIIIIII', 'IIIIIIIIIXIIIIIIIIII', 'IIIIIIIIXIIIIIIIIIII', 'IIIIIIIXIIIIIIIIIIII', 'IIIIIIXIIIIIIIIIIIII', 'IIIIIXIIIIIIIIIIIIII', 'IIIIXIIIIIIIIIIIIIII', 'IIIXIIIIIIIIIIIIIIII', 'IIXIIIIIIIIIIIIIIIII', 'IXIIIIIIIIIIIIIIIIII', 'XIIIIIIIIIIIIIIIIIII'],\n",
              "              coeffs=[-1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j,\n",
              " -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j,\n",
              " -1.+0.j, -1.+0.j, -1.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,\n",
              "  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,\n",
              "  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j])"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "n_qubits = 20\n",
        "hamiltonian = get_hamiltonian(nqubits=n_qubits, J=1.0, h=-5.0)\n",
        "hamiltonian"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "eb075fee-fdb5-4016-bea2-643b444062b8",
      "metadata": {},
      "source": [
        "#### Set the parameters of the time-evolution simulation\n",
        "\n",
        "Here we will consider the Lie–Trotter (first order).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "3a5af3d3-015b-4a5c-86cd-52830067a1e2",
      "metadata": {},
      "outputs": [],
      "source": [
        "num_timesteps = 20\n",
        "evolution_time = 2.0\n",
        "dt = evolution_time / num_timesteps\n",
        "product_formula_lt = LieTrotter()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e5fc52a2-15af-464f-aac2-890417745c82",
      "metadata": {},
      "source": [
        "#### Prepare the quantum circuit (Initial state)\n",
        "\n",
        "Create an initial state. We will start from the ground state, which is a ferromagnetic state (all up or all down). Here, we use an example of all ups (which is all '0').\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "64f622f2-6e1c-4b42-b548-dd3e5aa32786",
      "metadata": {
        "scrolled": true,
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/utility-ii/extracted-outputs/f3f6c2f1-63b7-4bb8-83d3-af579900ea6f-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "initial_circuit = QuantumCircuit(n_qubits)\n",
        "initial_circuit.prepare_state(\"00000000000000000000\")\n",
        "# Change reps and see the difference when you decompose the circuit\n",
        "initial_circuit.decompose(reps=1).draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dab0957f-186f-475f-bdee-907469b54174",
      "metadata": {},
      "source": [
        "#### Prepare the quantum circuit 2 (Single circuit for time evolution)\n",
        "\n",
        "We here construct a circuit for a single time step using Lie–Trotter.\n",
        "The Lie product formula (first order) is implemented in the [LieTrotter](/docs/api/qiskit/qiskit.synthesis.LieTrotter) class. A first-order formula consists of the approximation stated in the introduction, where the matrix exponential of a sum is approximated by a product of matrix exponentials:\n",
        "\n",
        "$$\n",
        "e^{H_1+H_2} \\approx e^{H_1} e^{H_2}\n",
        "$$\n",
        "\n",
        "Let us count the operations for this circuit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "b812f4b6-fb83-4c89-a8bc-ac0d85784720",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "Trotter step with Lie-Trotter\n",
            "-----------------------------\n",
            "Depth: 58\n",
            "Gate count: 77\n",
            "Nonlocal gate count: 38\n",
            "Gate breakdown: CX: 38, U3: 20, U1: 19\n",
            "\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/utility-ii/extracted-outputs/dbc253b8-17a1-4cb7-aede-bddfa59fab8a-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "single_step_evolution_gates_lt = PauliEvolutionGate(\n",
        "    hamiltonian, dt, synthesis=product_formula_lt\n",
        ")\n",
        "single_step_evolution_lt = QuantumCircuit(n_qubits)\n",
        "single_step_evolution_lt.append(\n",
        "    single_step_evolution_gates_lt, single_step_evolution_lt.qubits\n",
        ")\n",
        "\n",
        "print(\n",
        "    f\"\"\"\n",
        "Trotter step with Lie-Trotter\n",
        "-----------------------------\n",
        "Depth: {single_step_evolution_lt.decompose(reps=3).depth()}\n",
        "Gate count: {len(single_step_evolution_lt.decompose(reps=3))}\n",
        "Nonlocal gate count: {single_step_evolution_lt.decompose(reps=3).num_nonlocal_gates()}\n",
        "Gate breakdown: {\", \".join([f\"{k.upper()}: {v}\" for k, v in single_step_evolution_lt.decompose(reps=3).count_ops().items()])}\n",
        "\"\"\"\n",
        ")\n",
        "single_step_evolution_lt.decompose(reps=3).draw(\"mpl\", fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "474e7a29-82bc-470e-8556-87e88195f213",
      "metadata": {},
      "source": [
        "#### Set the operators to be measured\n",
        "\n",
        "Let us define a *magnetization operator* $\\sum_i Z_i  / N$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "2488d18d-70f0-43a2-9675-4d34562e47ce",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "magnetization :  SparsePauliOp(['IIIIIIIIIIIIIIIIIIIZ', 'IIIIIIIIIIIIIIIIIIZI', 'IIIIIIIIIIIIIIIIIZII', 'IIIIIIIIIIIIIIIIZIII', 'IIIIIIIIIIIIIIIZIIII', 'IIIIIIIIIIIIIIZIIIII', 'IIIIIIIIIIIIIZIIIIII', 'IIIIIIIIIIIIZIIIIIII', 'IIIIIIIIIIIZIIIIIIII', 'IIIIIIIIIIZIIIIIIIII', 'IIIIIIIIIZIIIIIIIIII', 'IIIIIIIIZIIIIIIIIIII', 'IIIIIIIZIIIIIIIIIIII', 'IIIIIIZIIIIIIIIIIIII', 'IIIIIZIIIIIIIIIIIIII', 'IIIIZIIIIIIIIIIIIIII', 'IIIZIIIIIIIIIIIIIIII', 'IIZIIIIIIIIIIIIIIIII', 'IZIIIIIIIIIIIIIIIIII', 'ZIIIIIIIIIIIIIIIIIII'],\n",
            "              coeffs=[0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j,\n",
            " 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j,\n",
            " 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j, 0.05+0.j])\n"
          ]
        }
      ],
      "source": [
        "magnetization = (\n",
        "    SparsePauliOp.from_sparse_list(\n",
        "        [(\"Z\", [i], 1.0) for i in range(0, n_qubits)], num_qubits=n_qubits\n",
        "    )\n",
        "    / n_qubits\n",
        ")\n",
        "print(\"magnetization : \", magnetization)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "308ed03d-432d-4113-9c06-2ce10c02ecd5",
      "metadata": {},
      "source": [
        "#### Perform time-evolution simulation\n",
        "\n",
        "We will monitor the magnetization (expectation value of the magnetization operator). We will use Statevector and MPS simulators and compare the results.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "25bd2824-009e-4d76-be83-a906bf8b0d44",
      "metadata": {
        "scrolled": true
      },
      "outputs": [],
      "source": [
        "# Step 1. Map the problem\n",
        "# Initiate the circuit\n",
        "evolved_state = QuantumCircuit(initial_circuit.num_qubits)\n",
        "# Start from the initial spin configuration\n",
        "evolved_state.append(initial_circuit, evolved_state.qubits)\n",
        "\n",
        "# Define backend (simulator)\n",
        "# MPS\n",
        "backend_mps = AerSimulator(method=\"matrix_product_state\")\n",
        "# Statevector\n",
        "backend_sv = AerSimulator(method=\"statevector\")\n",
        "\n",
        "# Set Runtime Estimator\n",
        "# MPS\n",
        "estimator_mps = Estimator(mode=backend_mps)\n",
        "# Statevector\n",
        "estimator_sv = Estimator(mode=backend_sv)\n",
        "\n",
        "# Step 2. Optimize\n",
        "# Set pass manager\n",
        "# MPS\n",
        "pm_mps = generate_preset_pass_manager(optimization_level=3, backend=backend_mps)\n",
        "# Statevector\n",
        "pm_sv = generate_preset_pass_manager(optimization_level=3, backend=backend_sv)\n",
        "\n",
        "# Transpile initial circuit\n",
        "# MPS\n",
        "evolved_state_mps = pm_mps.run(evolved_state)\n",
        "# Statevector\n",
        "evolved_state_sv = pm_sv.run(evolved_state)\n",
        "\n",
        "# Apply layout to the operator\n",
        "# MPS\n",
        "magnetization_mps = magnetization.apply_layout(evolved_state_mps.layout)\n",
        "# Statevector\n",
        "magnetization_sv = magnetization.apply_layout(evolved_state_sv.layout)\n",
        "\n",
        "mag_mps_list = []\n",
        "mag_sv_list = []\n",
        "\n",
        "# Step 3. Run the circuit\n",
        "# Estimate expectation values for t=0.0: MPS\n",
        "job = estimator_mps.run([(evolved_state_mps, [magnetization_mps])])\n",
        "# Get estimated expectation values: MPS\n",
        "evs = job.result()[0].data.evs\n",
        "# Collect data: MPS\n",
        "mag_mps_list.append(evs[0])\n",
        "\n",
        "# Estimate expectation values for t=0.0: Statevector\n",
        "job = estimator_sv.run([(evolved_state_sv, [magnetization_sv])])\n",
        "# Get estimated expectation values: Statevector\n",
        "evs = job.result()[0].data.evs\n",
        "# Collect data: Statevector\n",
        "mag_sv_list.append(evs[0])\n",
        "\n",
        "# Start time evolution\n",
        "for n in range(num_timesteps):\n",
        "    # Step 1. Map the problem\n",
        "    # Expand the circuit to describe delta-t\n",
        "    evolved_state.append(single_step_evolution_lt, evolved_state.qubits)\n",
        "    # Step 2. Optimize\n",
        "    # Transpile the circuit: MPS\n",
        "    evolved_state_mps = pm_mps.run(evolved_state)\n",
        "    # Apply the physical layout of the qubits to the operator: MPS\n",
        "    magnetization_mps = magnetization.apply_layout(evolved_state_mps.layout)\n",
        "    # Step 3. Run the circuit\n",
        "    # Estimate expectation values at delta-t: MPS\n",
        "    job = estimator_mps.run([(evolved_state_mps, [magnetization_mps])])\n",
        "    # Get estimated expectation values: MPS\n",
        "    evs = job.result()[0].data.evs\n",
        "    # Collect data: MPS\n",
        "    mag_mps_list.append(evs[0])\n",
        "\n",
        "    # Step 2. Optimize\n",
        "    # Transpile the circuit: Statevector\n",
        "    evolved_state_sv = pm_sv.run(evolved_state)\n",
        "    # Apply the physical layout of the qubits to the operator: Statevector\n",
        "    magnetization_sv = magnetization.apply_layout(evolved_state_sv.layout)\n",
        "    # Step 3. Run the circuit\n",
        "    # Estimate expectation values at delta-t: Statevector\n",
        "    job = estimator_sv.run([(evolved_state_sv, [magnetization_sv])])\n",
        "    # Get estimated expectation values: Statevector\n",
        "    evs = job.result()[0].data.evs\n",
        "    # Collect data: Statevector\n",
        "    mag_sv_list.append(evs[0])\n",
        "\n",
        "# Transform the list of expectation values (at each time step) to arrays\n",
        "mag_mps_array = np.array(mag_mps_list)\n",
        "mag_sv_array = np.array(mag_sv_list)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "046df34e-4cc8-455a-a3e8-f6b345c9249a",
      "metadata": {},
      "source": [
        "#### Plot the time evolution of the observables\n",
        "\n",
        "We plot the expectation values we measured against time. Confirm that the results from statevector and matrix product space simulators agree.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "1762b191-c234-4acc-a6ea-8433a59ef3f8",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "Text(0.5, 0.98, 'Observable evolution')"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/utility-ii/extracted-outputs/7583b935-afce-40c8-807d-6d61d43af13c-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "\n",
        "# Step 4. Post-processing\n",
        "fig, axes = plt.subplots(2, sharex=True)\n",
        "times = np.linspace(0, evolution_time, num_timesteps + 1)  # includes initial state\n",
        "axes[0].plot(\n",
        "    times, mag_mps_array, label=\"MPS\", marker=\"x\", c=\"darkmagenta\", ls=\"-\", lw=0.8\n",
        ")\n",
        "axes[1].plot(\n",
        "    times, mag_sv_array, label=\"SV\", marker=\"x\", c=\"darkmagenta\", ls=\"-\", lw=0.8\n",
        ")\n",
        "\n",
        "axes[0].set_ylabel(\"MPS\")\n",
        "axes[1].set_ylabel(\"Statevector\")\n",
        "axes[1].set_xlabel(\"Time\")\n",
        "fig.suptitle(\"Observable evolution\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4a4a4efa-de95-470e-8030-1b842e63f904",
      "metadata": {},
      "source": [
        "We will start investigating the time evolution of a quantum system, while keeping track of properties.\n",
        "We here compare the results of the Matrix Product State simulator and the actual quantum device.\n",
        "\n",
        "### 2.2 Activity 2\n",
        "\n",
        "#### Define the Hamiltonian\n",
        "\n",
        "The system that we now consider has a size of $N=70$. Note that the other conditions are the same from the 20-qubit problem. Try this on your own; scroll down for the solution.\n",
        "\n",
        "**Solution:**\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "b8ee438b-69ac-438d-a8c9-a2055c347f0e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZI', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'ZZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIX', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXI', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IXIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'XIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],\n",
              "              coeffs=[-1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j,\n",
              " -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j,\n",
              " -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j,\n",
              " -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j,\n",
              " -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j,\n",
              " -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j,\n",
              " -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j,\n",
              " -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j,\n",
              " -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j, -1.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,\n",
              "  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,\n",
              "  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,\n",
              "  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,\n",
              "  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,\n",
              "  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,\n",
              "  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,\n",
              "  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,\n",
              "  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,  5.+0.j,\n",
              "  5.+0.j,  5.+0.j,  5.+0.j])"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Set the number of qubits\n",
        "n_qubits2 = 70\n",
        "# Construct the Hamiltonian by calling the function you made in Activity 1\n",
        "hamiltonian2 = get_hamiltonian(nqubits=n_qubits2, J=1.0, h=-5.0)\n",
        "hamiltonian2"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8bcad10c-1ad8-4d62-ba05-6c3d4792e4b9",
      "metadata": {},
      "source": [
        "### 2.3 Activity 3\n",
        "\n",
        "Create an initial state. We will start from the ground state, which is a ferromagnetic state (all up or all down). Here, we use an example of all ups (which is all '0'). Try this on your own; scroll down for the solution.\n",
        "\n",
        "**Solution:**\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "b7bfecd3-cc23-4005-89d5-61754b72ac7d",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/utility-ii/extracted-outputs/edacae4b-ab0e-4f1b-8c3d-001ade87e64e-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Initiate the (quantum)circuit\n",
        "initial_circuit2 = QuantumCircuit(n_qubits2)\n",
        "# Use QuantumCircuit.prepare_state() to define the initial state\n",
        "initial_circuit2.prepare_state(\n",
        "    \"0000000000000000000000000000000000000000000000000000000000000000000000\"\n",
        ")\n",
        "# Change reps and see the difference when you decompose the circuit\n",
        "initial_circuit2.decompose(reps=1).draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d3699dfb-5f77-4c2b-b4c7-13ca873b032b",
      "metadata": {},
      "source": [
        "### 2.4 Activity 4\n",
        "\n",
        "#### Prepare the quantum circuit 2 (Single circuit for time evolution) for the 70-qubit problem\n",
        "\n",
        "We here construct a circuit for a single time step using Lie–Trotter.\n",
        "Exactly as in the 20-qubit case, the Lie product formula (first order) is implemented in the [LieTrotter](/docs/api/qiskit/qiskit.synthesis.LieTrotter) class. Again, the first-order formula consists of the approximation stated above:\n",
        "\n",
        "$$\n",
        "e^{H_1+H_2} \\approx e^{H_1} e^{H_2}\n",
        "$$\n",
        "\n",
        "Try this yourself, building from the example of the 20-qubit case. As before, count the operations for this circuit.\n",
        "\n",
        "**Solution:**\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "adb8395b-478a-4db0-b85e-456be61c9e69",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "Trotter step with Lie-Trotter\n",
            "-----------------------------\n",
            "Depth: 208\n",
            "Gate count: 277\n",
            "Nonlocal gate count: 138\n",
            "Gate breakdown: CX: 138, U3: 70, U1: 69\n",
            "\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/utility-ii/extracted-outputs/4f3385fc-d214-4405-8e37-eefe45cee98c-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Construct the gates using PauliEvolutionGate()\n",
        "single_step_evolution_gates_lt2 = PauliEvolutionGate(\n",
        "    hamiltonian2, dt, synthesis=LieTrotter()\n",
        ")\n",
        "# Initiate the quantum circuit\n",
        "single_step_evolution_lt2 = QuantumCircuit(n_qubits2)\n",
        "# Append the gates defined above\n",
        "single_step_evolution_lt2.append(\n",
        "    single_step_evolution_gates_lt2, single_step_evolution_lt2.qubits\n",
        ")\n",
        "\n",
        "print(\n",
        "    f\"\"\"\n",
        "Trotter step with Lie-Trotter\n",
        "-----------------------------\n",
        "Depth: {single_step_evolution_lt2.decompose(reps=3).depth()}\n",
        "Gate count: {len(single_step_evolution_lt2.decompose(reps=3))}\n",
        "Nonlocal gate count: {single_step_evolution_lt2.decompose(reps=3).num_nonlocal_gates()}\n",
        "Gate breakdown: {\", \".join([f\"{k.upper()}: {v}\" for k, v in single_step_evolution_lt2.decompose(reps=3).count_ops().items()])}\n",
        "\"\"\"\n",
        ")\n",
        "single_step_evolution_lt2.decompose(reps=3).draw(\"mpl\", fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "acede2cd-d3d8-45b8-8bc5-b307fc1f32fe",
      "metadata": {},
      "source": [
        "### 2.5 Activity 5\n",
        "\n",
        "#### Set the operators to be measured\n",
        "\n",
        "We define a *magnetization operator* exactly analogous to the one from the 20-qubit case: $\\sum_i Z_i  / N$. Try this yourself by modifying the 20-qubit solution.\n",
        "\n",
        "**Solution:**\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "9cac351a-b15c-4aff-87f1-c877946664d3",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "magnetization :  SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZI', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'ZIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII'],\n",
            "              coeffs=[0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j, 0.01428571+0.j,\n",
            " 0.01428571+0.j, 0.01428571+0.j])\n"
          ]
        }
      ],
      "source": [
        "# Define the magnetization operator in SparsePauliOp\n",
        "magnetization2 = (\n",
        "    SparsePauliOp.from_sparse_list(\n",
        "        [(\"Z\", [i], 1.0) for i in range(0, n_qubits2)], num_qubits=n_qubits2\n",
        "    )\n",
        "    / n_qubits2\n",
        ")\n",
        "print(\"magnetization : \", magnetization2)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "91f92286-acb7-4946-9f5f-150587e7f4d0",
      "metadata": {},
      "source": [
        "### 2.6 Activity 6\n",
        "\n",
        "#### Perform time-evolution simulation\n",
        "\n",
        "We will monitor the magnetization (expectation value of the magnetization operator). We will use the MPS simulator to get the reference value to compare the results computed from the hardware. You have used the MPS simulator before in this tutorial. Modify that example where necessary to fit this new calculation.\n",
        "\n",
        "**Solution:**\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "7e7b754c-deff-40fd-9250-8b4deafa18d6",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Step 1. Map the problem\n",
        "# Initiate the circuit\n",
        "evolved_state2 = QuantumCircuit(initial_circuit2.num_qubits)\n",
        "# Start from the initial spin configuration\n",
        "evolved_state2.append(initial_circuit2, evolved_state2.qubits)\n",
        "# Define backend (MPs simulator)\n",
        "backend_mps2 = AerSimulator(method=\"matrix_product_state\")\n",
        "# Initiate Runtime Estimator\n",
        "estimator_mps2 = Estimator(mode=backend_mps2)\n",
        "# Step 2. Optimize\n",
        "# Initiate pass manager\n",
        "pm_mps2 = generate_preset_pass_manager(optimization_level=3, backend=backend_mps2)\n",
        "# Transpile\n",
        "evolved_state_mps2 = pm_mps2.run(evolved_state2)\n",
        "# Apply qubit layout to the observable to measure\n",
        "magnetization_mps2 = magnetization2.apply_layout(evolved_state_mps2.layout)\n",
        "# Initiate list\n",
        "mag_mps_list2 = []\n",
        "# Step 3. Run the circuit\n",
        "# Estimate expectation values for t=0.0\n",
        "job = estimator_mps2.run([(evolved_state_mps2, [magnetization_mps2])])\n",
        "# Get estimated expectation values\n",
        "evs = job.result()[0].data.evs\n",
        "# Append to list\n",
        "mag_mps_list2.append(evs[0])\n",
        "\n",
        "# Start time evolution\n",
        "for n in range(num_timesteps):\n",
        "    # Step 1. Map the problem\n",
        "    # Expand the circuit to describe delta-t\n",
        "    evolved_state2.append(single_step_evolution_lt2, evolved_state2.qubits)\n",
        "    # Step 2. Optimize\n",
        "    # Transpile the circuit\n",
        "    evolved_state_mps2 = pm_mps2.run(evolved_state2)\n",
        "    # Apply the physical layout of the qubits to the operator\n",
        "    magnetization_mps2 = magnetization2.apply_layout(evolved_state_mps2.layout)\n",
        "    # Step 3. Run the circuit\n",
        "    # Estimate expectation values at delta-t\n",
        "    job = estimator_mps2.run([(evolved_state_mps2, [magnetization_mps2])])\n",
        "    # Get estimated expectation values\n",
        "    evs = job.result()[0].data.evs\n",
        "    # Append to list\n",
        "    mag_mps_list2.append(evs[0])\n",
        "# Transform the list of expectation values (at each time step) to arrays\n",
        "mag_mps_array2 = np.array(mag_mps_list2)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c8612280-d29b-4952-826f-16a686a051dd",
      "metadata": {},
      "source": [
        "As in all previous lessons, we will implement the Qiskit patterns framework. The lesson up to this point has been focused on creating the correct quantum circuits to describe our problem. This is effectively Step 1.\n",
        "\n",
        "#### Step 2: Optimize for target hardware\n",
        "\n",
        "We start by defining the target backend.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "610ecd2c-9a47-43c1-872b-a4038fb83817",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'ibm_kingston'"
            ]
          },
          "execution_count": 19,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "backend.name"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ba36b8f4-9fae-4151-b3fa-8f848eb77a0d",
      "metadata": {},
      "source": [
        "We transpile the circuits and gather them in a list. This might take a few minutes.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "id": "116e914e-8fa4-4e60-9980-af71d9bcc2f9",
      "metadata": {},
      "outputs": [],
      "source": [
        "pm_hw = generate_preset_pass_manager(optimization_level=3, backend=backend)\n",
        "circuit_isa = []\n",
        "# Step 1. Map the problem\n",
        "evolved_state_hw = QuantumCircuit(initial_circuit2.num_qubits)\n",
        "evolved_state_hw.append(initial_circuit2, evolved_state_hw.qubits)\n",
        "# Step 2. Optimize\n",
        "circuit_isa.append(pm_hw.run(evolved_state_hw))\n",
        "\n",
        "for n in range(num_timesteps):\n",
        "    # Step 1. Map the problem\n",
        "    evolved_state_hw.append(single_step_evolution_lt2, evolved_state_hw.qubits)\n",
        "    # Step 2. Optimize\n",
        "    circuit_isa.append(pm_hw.run(evolved_state_hw))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "60c95c4c-9eab-4c14-b17d-c710beecb2ce",
      "metadata": {},
      "source": [
        "#### Step 3: Execute on target hardware\n",
        "\n",
        "We will define the Runtime Estimator and construct the list of PUBs. We must also apply the layout to the operators to be measured.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "id": "3da4db25-5e78-4a86-b740-75fdacbdb831",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Step 2. Optimize\n",
        "estimator_hw = Estimator(mode=backend)\n",
        "pub_list = []\n",
        "for circuit in circuit_isa:\n",
        "    temp = (circuit, magnetization2.apply_layout(circuit.layout))\n",
        "    pub_list.append(temp)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2433f80e-5ed8-4e73-8adb-c4c688a79775",
      "metadata": {},
      "source": [
        "We are now ready to run the job.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "ba037ca8-dd6f-4962-a7f4-65f0bde66f8b",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "d147hfdqf56g0081sxs0\n"
          ]
        }
      ],
      "source": [
        "job = estimator_hw.run(pub_list)\n",
        "job_id = job.job_id()\n",
        "print(job_id)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 28,
      "id": "efcb2851-3529-4e76-8a0f-1b65be8f4818",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'DONE'"
            ]
          },
          "execution_count": 28,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# check job status\n",
        "job.status()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f5dd6d18-08e9-49eb-90b4-8b6037fd6d34",
      "metadata": {},
      "source": [
        "#### Step 4: Post-process results\n",
        "\n",
        "We will first get the results.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "id": "eb661ec3-b8fd-4e2b-a525-547685cc6864",
      "metadata": {},
      "outputs": [],
      "source": [
        "job = service.job(job_id)\n",
        "pub_result = job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1840130b-3c40-4a10-ac83-1bc4350a1f58",
      "metadata": {},
      "source": [
        "Now we must extract the expectation values from these results.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "id": "be186c8e-0408-4d2d-b843-5d27c82ba99c",
      "metadata": {},
      "outputs": [],
      "source": [
        "mag_hw_list = []\n",
        "for res in pub_result:\n",
        "    evs = res.data.evs\n",
        "    mag_hw_list.append(evs)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0a03e25f-d447-4c52-9595-c776c9b7a23c",
      "metadata": {},
      "source": [
        "We will use this for comparison below. First, let us see if we can optimize our circuits even further.\n",
        "\n",
        "## 3. Solution using a real quantum computer II\n",
        "\n",
        "Let us return to Qiskit patterns step 1, and see if we can reduce the depth of our circuit.\n",
        "\n",
        "### 3.1 Step 1. Map the problem to quantum circuits and operators\n",
        "\n",
        "#### Activity 7\n",
        "\n",
        "Construct a time-evolution circuit. Use your knowledge from previous lessons to try to reduce the depth of the circuit.\n",
        "\n",
        "**Solution:**\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "52a28d34-0852-4099-bcb8-ea9487701d43",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "Trotter step with Lie-Trotter\n",
            "-----------------------------\n",
            "Depth: 7\n",
            "Gate count: 277\n",
            "Nonlocal gate count: 138\n",
            "Gate breakdown: CX: 138, U3: 70, U1: 69\n",
            "\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/utility-ii/extracted-outputs/769902d2-acce-4252-8c44-cba3cc0f9be5-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 22,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Define J\n",
        "J = 1.0\n",
        "# Define h\n",
        "h = -5.0\n",
        "# Create instruction for rotation around ZZ:\n",
        "# Initiate the circuit (use 2 qubits)\n",
        "Rzz_circ = QuantumCircuit(2)\n",
        "# Add Rzz gate (do not forget to multiply the angle by 2.0)\n",
        "Rzz_circ.rzz(-J * dt * 2.0, 0, 1)\n",
        "# Transform the QuantumCircuit to instruction (QuantumCircuit.to_instruction())\n",
        "Rzz_instr = Rzz_circ.to_instruction(label=\"RZZ\")\n",
        "\n",
        "# Create instruction for rotation around X:\n",
        "# Initiate the circuit (use 1 qubit)\n",
        "Rx_circ = QuantumCircuit(1)\n",
        "# Add Rx gate (do not forget to multiply the angle by 2.0)\n",
        "Rx_circ.rx(-h * dt * 2.0, 0)\n",
        "# Transform the QuantumCircuit to instruction (QuantumCircuit.to_instruction())\n",
        "Rx_instr = Rx_circ.to_instruction(label=\"RX\")\n",
        "\n",
        "# Define the interaction list\n",
        "interaction_list = [\n",
        "    [[i, i + 1] for i in range(0, n_qubits2 - 1, 2)],\n",
        "    [[i, i + 1] for i in range(1, n_qubits2 - 1, 2)],\n",
        "]  # linear chain\n",
        "\n",
        "# Define the registers\n",
        "qr = QuantumRegister(n_qubits2)\n",
        "# Initiate the circuit\n",
        "single_step_evolution_sh = QuantumCircuit(qr)\n",
        "# Construct the Rzz gates\n",
        "for i, color in enumerate(interaction_list):\n",
        "    for interaction in color:\n",
        "        single_step_evolution_sh.append(Rzz_instr, interaction)\n",
        "\n",
        "# Construct the Rx gates\n",
        "for i in range(0, n_qubits2):\n",
        "    single_step_evolution_sh.append(Rx_instr, [i])\n",
        "\n",
        "print(\n",
        "    f\"\"\"\n",
        "Trotter step with Lie-Trotter\n",
        "-----------------------------\n",
        "Depth: {single_step_evolution_sh.decompose(reps=3).depth()}\n",
        "Gate count: {len(single_step_evolution_sh.decompose(reps=3))}\n",
        "Nonlocal gate count: {single_step_evolution_sh.decompose(reps=3).num_nonlocal_gates()}\n",
        "Gate breakdown: {\", \".join([f\"{k.upper()}: {v}\" for k, v in single_step_evolution_sh.decompose(reps=3).count_ops().items()])}\n",
        "\"\"\"\n",
        ")\n",
        "\n",
        "single_step_evolution_sh.decompose(reps=2).draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5cde0bf4-37e8-469a-a88f-bb9c37168cea",
      "metadata": {},
      "source": [
        "This was very successful. We can now proceed with the remaining Qiskit patterns steps.\n",
        "\n",
        "### 3.2 Step 2. Optimize for target hardware\n",
        "\n",
        "Transpile the circuits and gather them in a list. Once again, this might take a few minutes.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 32,
      "id": "958e2251-2a1e-4caf-b501-946f32b4fe9e",
      "metadata": {},
      "outputs": [],
      "source": [
        "pm_hw2 = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
        "circuit_isa2 = []\n",
        "# Step 1. Map the problem\n",
        "evolved_state_hw2 = QuantumCircuit(initial_circuit2.num_qubits)\n",
        "evolved_state_hw2.append(initial_circuit2, evolved_state_hw2.qubits)\n",
        "# Step 2. Optimize\n",
        "circuit_isa2.append(pm_hw2.run(evolved_state_hw2))\n",
        "for n in range(num_timesteps):\n",
        "    # Step 1. Map the problem\n",
        "    evolved_state_hw2.append(single_step_evolution_sh, evolved_state_hw2.qubits)\n",
        "    # Step 2. Optimize\n",
        "    circuit_isa2.append(pm_hw2.run(evolved_state_hw2))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8c74b53d-abac-48ac-883c-029adcd4894c",
      "metadata": {},
      "source": [
        "Define the Runtime Estimator and construct the list of PUBs.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 33,
      "id": "754e4c6d-04cc-4cc1-af81-c6fc13c353e0",
      "metadata": {},
      "outputs": [],
      "source": [
        "estimator_hw2 = Estimator(mode=backend)\n",
        "pub_list2 = []\n",
        "for circuit in circuit_isa2:\n",
        "    temp = (circuit, magnetization2.apply_layout(circuit.layout))\n",
        "    pub_list2.append(temp)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e2fa2986-701d-4f68-ab38-d6bf24a599c6",
      "metadata": {},
      "source": [
        "### 3.3 Step 3. Execute on target hardware\n",
        "\n",
        "Run the job.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 34,
      "id": "5288e0f3-e12c-4e8c-80f8-6e2535ffb0d1",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "d147qqeqf56g0081sye0\n"
          ]
        }
      ],
      "source": [
        "job2 = estimator_hw2.run(pub_list2)\n",
        "job2_id = job2.job_id()\n",
        "print(job2_id)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 36,
      "id": "37dfc4b9-4757-4a87-a1a4-972a372b931a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'DONE'"
            ]
          },
          "execution_count": 36,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# check job status\n",
        "job2.status()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4d08139b-71af-4578-b3b5-45f9a3741c0b",
      "metadata": {},
      "source": [
        "Get the results.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "id": "83d2d003-2f97-4294-a745-2e0a1c7ae80c",
      "metadata": {},
      "outputs": [],
      "source": [
        "job2 = service.job(job2_id)\n",
        "pub_result2 = job2.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7f32a06a-2974-4f22-9dbe-d2ec6143f3cf",
      "metadata": {},
      "source": [
        "### 3.4 Step 4. Post-processing\n",
        "\n",
        "Extract the expectation values from the results.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "id": "402c9208-9a1d-4424-8ef2-636407c398d7",
      "metadata": {},
      "outputs": [],
      "source": [
        "mag_hw_list2 = []\n",
        "for res in pub_result2:\n",
        "    evs = res.data.evs\n",
        "    mag_hw_list2.append(evs)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0c255702-0ef3-46ff-bb6e-4675af2676a3",
      "metadata": {},
      "source": [
        "Transform the list into numpy arrays for plotting.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "id": "0d28a88f-990c-4330-9506-4cf23ae57415",
      "metadata": {},
      "outputs": [],
      "source": [
        "mag_hw_array = np.array(mag_hw_list)\n",
        "mag_hw_array2 = np.array(mag_hw_list2)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "128662bd-44dc-4730-bdaa-fd686d1dbf04",
      "metadata": {},
      "source": [
        "Now let us plot the results and compare the hardware (default and shallow circuit) results with the MPS simulator. How does the error in the real hardware influence the results?\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "id": "3aa52fc2-1685-482c-8673-c25096ddb44f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "Text(0.5, 0.98, 'Observable evolution')"
            ]
          },
          "execution_count": 27,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/utility-ii/extracted-outputs/83c809cb-299c-4071-a662-d10ba7e24996-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "fig, axes = plt.subplots(3, sharex=True)\n",
        "times = np.linspace(0, evolution_time, num_timesteps + 1)  # includes initial state\n",
        "axes[0].plot(\n",
        "    times, mag_mps_array2, label=\"MPS\", marker=\"x\", c=\"darkmagenta\", ls=\"-\", lw=0.8\n",
        ")\n",
        "axes[1].plot(\n",
        "    times, mag_hw_array, label=\"HW\", marker=\"x\", c=\"darkmagenta\", ls=\"-\", lw=0.8\n",
        ")\n",
        "axes[2].plot(\n",
        "    times, mag_hw_array2, label=\"HW2\", marker=\"x\", c=\"darkmagenta\", ls=\"-\", lw=0.8\n",
        ")\n",
        "axes[0].set_ylabel(\"MPS\")\n",
        "axes[1].set_ylabel(\"HW\")\n",
        "axes[2].set_ylabel(\"HW2\")\n",
        "axes[2].set_xlabel(\"Time\")\n",
        "fig.suptitle(\"Observable evolution\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ec7c30e2-eea0-4fb7-80c8-e0dfb826c95e",
      "metadata": {},
      "source": [
        "Congratulations! You have moved one step further in your utility-scale quantum journey. There is only one lesson left!\n",
        "\n"
      ]
    },
    {
      "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
}