{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b97a7e0a-66a6-46b2-b33f-47feeefad60d",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Utilità II\"\n",
        "description: \"Questo quaderno segue i metodi e le tecniche della lezione 7. Il nostro obiettivo è risolvere numericamente l'equazione di Schrödinger dipendente dal tempo.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore sharex */}\n",
        "\n",
        "<span id=\"utility-scale-experiment-ii\" />\n",
        "\n",
        "# Esperimento su scala industriale II\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Yukio Kawashima (12 luglio 2024)\n",
        "\n",
        "  [Scarica il pdf](https://ibm.ent.box.com/s/bipgoms7gr6b6vhkoc1uw6oi4wsanfoq) della lezione originale. Si noti che alcuni frammenti di codice potrebbero diventare deprecati, poiché si tratta di immagini statiche.\n",
        "\n",
        "  *Il tempo approssimativo della QPU per eseguire questo esperimento è di 2 m 30 s.*\n",
        "\n",
        "  (Si noti che questo quaderno ha utilizzato testi, illustrazioni e codici di un [quaderno di esercitazioni per](https://github.com/qiskit-community/qiskit-algorithms/blob/main/docs/tutorials/13_trotterQRTE.ipynb) gli algoritmi di Qiskit, ormai deprecato)\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "76421ffc-f47f-46a4-8198-af3bc21e3c5d",
      "metadata": {},
      "source": [
        "<span id=\"1-introduction-and-review-of-time-evolution\" />\n",
        "\n",
        "## 1. Introduzione e revisione dell'evoluzione temporale\n",
        "\n",
        "Questo quaderno segue i metodi e le tecniche della lezione 7. Il nostro obiettivo è risolvere numericamente l'equazione di Schrödinger dipendente dal tempo. Come discusso nella lezione 7, la trotterizzazione consiste nell'applicazione successiva di una o più porte quantistiche, scelte per approssimare l'evoluzione temporale di un sistema per una fetta di tempo. Riprendiamo qui la discussione per comodità. Se avete già rivisto la lezione 7, potete passare alle celle di codice sottostanti.\n",
        "\n",
        "A partire dall'equazione di Schrödinger, l'evoluzione temporale di un sistema inizialmente nello stato $\\vert\\psi(0)\\rangle$ assume la forma:\n",
        "\n",
        "$$\n",
        "\\vert \\psi(t) \\rangle = e^{-i H t} \\vert \\psi(0) \\rangle \\text{,}\n",
        "$$\n",
        "\n",
        "dove $H$ è l'hamiltoniana indipendente dal tempo che governa il sistema. Consideriamo un'hamiltoniana che può essere scritta come una somma pesata di termini di Pauli $H=\\sum_j a_j P_j$, con $P_j$ che rappresenta un prodotto tensoriale di termini di Pauli che agiscono su $n$ qubit. In particolare, questi termini di Pauli possono commutare tra loro, oppure no. Dato uno stato al tempo $t=0$, come si può ottenere lo stato del sistema in un tempo successivo $|\\psi(t)\\rangle$ utilizzando un computer quantistico? L'esponenziale di un operatore può essere più facilmente compreso attraverso la sua serie di Taylor:\n",
        "\n",
        "$$\n",
        "e^{-i H t} = 1-iHt-\\frac{1}{2}H^2t^2+...\n",
        "$$\n",
        "\n",
        "Alcuni esponenziali molto semplici, come $e^{iZ}$, possono essere implementati facilmente sui computer quantistici utilizzando un insieme compatto di porte quantistiche. La maggior parte degli hamiltoniani di interesse non avrà un solo termine, ma molti termini. Si noti cosa succede se $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",
        "Quando $H_1$ e $H_2$ commutano, si ha il caso familiare (che vale anche per i numeri e le variabili $a$ e $b$ di seguito):\n",
        "\n",
        "$$\n",
        "e^{-i (a+b) t} = e^{-i a t}e^{-i b t}\n",
        "$$\n",
        "\n",
        "Tuttavia, quando gli operatori non si interscambiano, i termini non possono essere riorganizzati nella serie di Taylor per semplificare in questo modo. Pertanto, l'espressione di hamiltoniani complicati in porte quantistiche rappresenta una sfida.\n",
        "\n",
        "Una soluzione consiste nel considerare un tempo molto piccolo $t$, tale da rendere dominante il termine del primo ordine nell'espansione di Taylor. In base a questa ipotesi:\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",
        "Naturalmente, potremmo aver bisogno di evolvere il nostro stato per un periodo più lungo. Questo si ottiene utilizzando molti piccoli passi nel tempo. Questo processo è chiamato trotterizzazione:\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",
        "Qui $t/r$ è la fetta di tempo (passo evolutivo) che stiamo scegliendo. Di conseguenza, viene creato un cancello da applicare $r$ volte. Un passo temporale minore porta a un'approssimazione più accurata. Tuttavia, questo porta anche a circuiti più profondi che, in pratica, comportano un maggiore accumulo di errori (una preoccupazione non trascurabile per i dispositivi quantistici a breve termine).\n",
        "\n",
        "Oggi studieremo l'evoluzione temporale del [modello di Ising](https://en.wikipedia.org/wiki/Ising_model) su reticoli lineari di siti $N=2$ e $N=6$. Questi reticoli sono costituiti da una serie di spin $\\sigma_i$ che interagiscono solo con i loro vicini più prossimi. Questi spin possono avere due orientamenti: $\\uparrow$ e $\\downarrow$, che corrispondono a una magnetizzazione di $+1$ e $-1$ rispettivamente.\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",
        "dove $J$ descrive l'energia di interazione e $h$ la grandezza di un campo esterno (nella direzione x di cui sopra, ma che modificheremo). Scriviamo questa espressione utilizzando le matrici di Pauli e considerando che il campo esterno ha un angolo $\\alpha$ rispetto alla direzione trasversale,\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",
        "Questa hamiltoniana è utile perché ci permette di studiare facilmente gli effetti di un campo esterno. Nella base computazionale, il sistema sarà codificato come segue:\n",
        "\n",
        "|     Stato quantistico    |         Rappresentazione dello spin        |\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",
        "Inizieremo a studiare l'evoluzione temporale di un sistema quantistico di questo tipo. In particolare, visualizzeremo l'evoluzione temporale di alcune proprietà del sistema, come la magnetizzazione.\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": [
        "<span id=\"2-defining-the-transverse-field-ising-hamiltonian\" />\n",
        "\n",
        "## 2. Definizione dell'Hamiltoniano di Ising a campo trasversale\n",
        "\n",
        "Consideriamo qui il modello di Ising a campo trasverso 1-D.\n",
        "\n",
        "Per prima cosa, creeremo una funzione che accetta i parametri del sistema $N$, $J$, e $h$, e restituisce la nostra hamiltoniana come `SparsePauliOp`. A [SparsePauliOp](/docs/api/qiskit/qiskit.quantum_info.SparsePauliOp) è una rappresentazione rada di un operatore in termini di termini di [Pauli](/docs/api/qiskit/qiskit.quantum_info.Pauli) ponderati.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b3137f47-640a-4382-95b6-6bb9e760bc96",
      "metadata": {},
      "source": [
        "<span id=\"21-activity-1\" />\n",
        "\n",
        "### 2.1 Attività 1\n",
        "\n",
        "Costruire una funzione per costruire un'hamiltoniana di Ising a campo trasverso (vedi l'equazione precedente) con gli argomenti \"numero di qubit\", \"parametro J\" e \"parametro h\". Provate a farlo da soli utilizzando gli esempi precedenti. Scorrete in basso per la soluzione.\n",
        "\n",
        "**Soluzione:**\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": [
        "Inizieremo a studiare l'evoluzione temporale di un sistema quantistico, tenendo traccia della magnetizzazione.\n",
        "Confrontiamo qui i risultati dei simulatori di stato Statevector e Matrix Product State.\n",
        "\n",
        "<span id=\"define-the-hamiltonian\" />\n",
        "\n",
        "#### Definire l'Hamiltoniano\n",
        "\n",
        "Il sistema che ora consideriamo ha una dimensione di $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": [
        "<span id=\"set-the-parameters-of-the-time-evolution-simulation\" />\n",
        "\n",
        "#### Imposta i parametri della simulazione dell'evoluzione temporale\n",
        "\n",
        "Qui considereremo il Lie-Trotter (primo ordine).\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": [
        "<span id=\"prepare-the-quantum-circuit-initial-state\" />\n",
        "\n",
        "#### Preparare il circuito quantistico (stato iniziale)\n",
        "\n",
        "Creare uno stato iniziale. Partiremo dallo stato di massa, che è uno stato ferromagnetico (tutto su o tutto giù). Qui utilizziamo un esempio di tutti gli up (che sono tutti '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": [
        "<span id=\"prepare-the-quantum-circuit-2-single-circuit-for-time-evolution\" />\n",
        "\n",
        "#### Preparare il circuito quantistico 2 (circuito singolo per l'evoluzione temporale)\n",
        "\n",
        "Qui costruiamo un circuito per un singolo passo temporale utilizzando Lie-Trotter.\n",
        "La formula del prodotto di Lie (primo ordine) è implementata nella classe [LieTrotter](/docs/api/qiskit/qiskit.synthesis.LieTrotter) classe. Una formula del primo ordine consiste nell'approssimazione indicata nell'introduzione, in cui la matrice esponenziale di una somma è approssimata da un prodotto di matrici esponenziali:\n",
        "\n",
        "$$\n",
        "e^{H_1+H_2} \\approx e^{H_1} e^{H_2}\n",
        "$$\n",
        "\n",
        "Contiamo le operazioni di questo circuito.\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": [
        "<span id=\"set-the-operators-to-be-measured\" />\n",
        "\n",
        "#### Impostare gli operatori da misurare\n",
        "\n",
        "Definiamo un *operatore di magnetizzazione* $\\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": [
        "<span id=\"perform-time-evolution-simulation\" />\n",
        "\n",
        "#### Eseguire una simulazione dell'evoluzione nel tempo\n",
        "\n",
        "Monitoreremo la magnetizzazione (valore di aspettativa dell'operatore di magnetizzazione). Utilizzeremo i simulatori Statevector e MPS e confronteremo i risultati.\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": [
        "<span id=\"plot-the-time-evolution-of-the-observables\" />\n",
        "\n",
        "#### Tracciare l'evoluzione temporale delle grandezze osservabili\n",
        "\n",
        "Tracciamo i valori di aspettativa misurati rispetto al tempo. Confermare che i risultati dei simulatori dello spazio del vettore di stato e del prodotto matriciale concordano.\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": [
        "Inizieremo a studiare l'evoluzione temporale di un sistema quantistico, tenendo traccia delle proprietà.\n",
        "Confrontiamo qui i risultati del simulatore di stato del prodotto matrice e del dispositivo quantistico reale.\n",
        "\n",
        "<span id=\"22-activity-2\" />\n",
        "\n",
        "### 2.2 Attività 2\n",
        "\n",
        "<span id=\"define-the-hamiltonian\" />\n",
        "\n",
        "#### Definire l'Hamiltoniano\n",
        "\n",
        "Il sistema che consideriamo ora ha una dimensione di $N=70$. Si noti che le altre condizioni sono le stesse del problema dei 20-qubit. Provate a farlo da soli; scorrete in basso per trovare la soluzione.\n",
        "\n",
        "**Soluzione:**\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": [
        "<span id=\"23-activity-3\" />\n",
        "\n",
        "### 2.3 Attività 3\n",
        "\n",
        "Creare uno stato iniziale. Partiremo dallo stato di massa, che è uno stato ferromagnetico (tutto su o tutto giù). Qui utilizziamo un esempio di tutti gli up (che sono tutti '0'). Provate a farlo da soli; scorrete in basso per trovare la soluzione.\n",
        "\n",
        "**Soluzione:**\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": [
        "<span id=\"24-activity-4\" />\n",
        "\n",
        "### 2.4 Attività 4\n",
        "\n",
        "<span id=\"prepare-the-quantum-circuit-2-single-circuit-for-time-evolution-for-the-70-qubit-problem\" />\n",
        "\n",
        "#### Preparare il circuito quantistico 2 (circuito singolo per l'evoluzione temporale) per il problema a 70 qubit\n",
        "\n",
        "Qui costruiamo un circuito per un singolo passo temporale utilizzando Lie-Trotter.\n",
        "Esattamente come nel caso dei 20-qubit, la formula del prodotto di Lie (del primo ordine) è implementata nella classe [LieTrotter](/docs/api/qiskit/qiskit.synthesis.LieTrotter) classe. Anche in questo caso, la formula del primo ordine consiste nell'approssimazione di cui sopra:\n",
        "\n",
        "$$\n",
        "e^{H_1+H_2} \\approx e^{H_1} e^{H_2}\n",
        "$$\n",
        "\n",
        "Provate voi stessi, partendo dall'esempio del caso a 20 bit. Come in precedenza, contare le operazioni per questo circuito.\n",
        "\n",
        "**Soluzione:**\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": [
        "<span id=\"25-activity-5\" />\n",
        "\n",
        "### 2.5 Attività 5\n",
        "\n",
        "<span id=\"set-the-operators-to-be-measured\" />\n",
        "\n",
        "#### Impostare gli operatori da misurare\n",
        "\n",
        "Definiamo un *operatore di magnetizzazione* esattamente analogo a quello del caso a 20-qubit: $\\sum_i Z_i  / N$. Provate voi stessi modificando la soluzione a 20-qubit.\n",
        "\n",
        "**Soluzione:**\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": [
        "<span id=\"26-activity-6\" />\n",
        "\n",
        "### 2.6 Attività 6\n",
        "\n",
        "<span id=\"perform-time-evolution-simulation\" />\n",
        "\n",
        "#### Eseguire una simulazione dell'evoluzione nel tempo\n",
        "\n",
        "Monitoreremo la magnetizzazione (valore di aspettativa dell'operatore di magnetizzazione). Utilizzeremo il simulatore MPS per ottenere il valore di riferimento per confrontare i risultati calcolati dall'hardware. Il simulatore MPS è già stato utilizzato in questa esercitazione. Modificare l'esempio, se necessario, per adattarlo al nuovo calcolo.\n",
        "\n",
        "**Soluzione:**\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": [
        "Come in tutte le lezioni precedenti, implementeremo il framework Qiskit patterns. La lezione fino a questo punto si è concentrata sulla creazione dei circuiti quantistici corretti per descrivere il nostro problema. Questa è effettivamente la Fase 1.\n",
        "\n",
        "<span id=\"step-2-optimize-for-target-hardware\" />\n",
        "\n",
        "#### Passaggio 2: Ottimizzazione per l'hardware di destinazione\n",
        "\n",
        "Iniziamo definendo il backend di destinazione.\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": [
        "Trasponiamo i circuiti e li raccogliamo in un elenco. Potrebbe richiedere alcuni minuti.\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": [
        "<span id=\"step-3-execute-on-target-hardware\" />\n",
        "\n",
        "#### Fase 3: Esecuzione sull'hardware di destinazione\n",
        "\n",
        "Definiamo il Runtime Estimator e costruiamo l'elenco dei PUB. Dobbiamo anche applicare il layout agli operatori da misurare.\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": [
        "Ora siamo pronti a eseguire il lavoro.\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": [
        "<span id=\"step-4-post-process-results\" />\n",
        "\n",
        "#### Fase 4: Post-elaborazione dei risultati\n",
        "\n",
        "Per prima cosa otterremo i risultati.\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": [
        "Ora dobbiamo estrarre i valori di aspettativa da questi risultati.\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": [
        "Lo utilizzeremo di seguito per un confronto. Per prima cosa, vediamo se possiamo ottimizzare ulteriormente i nostri circuiti.\n",
        "\n",
        "<span id=\"3-solution-using-a-real-quantum-computer-ii\" />\n",
        "\n",
        "## 3. Soluzione utilizzando un vero computer quantistico II\n",
        "\n",
        "Torniamo agli schemi di Qiskit al punto 1 e vediamo se possiamo ridurre la profondità del nostro circuito.\n",
        "\n",
        "<span id=\"31-step-1-map-the-problem-to-quantum-circuits-and-operators\" />\n",
        "\n",
        "### 3.1 Passaggio 1. Mappare il problema su circuiti quantistici e operatori\n",
        "\n",
        "<span id=\"activity-7\" />\n",
        "\n",
        "#### Attività 7\n",
        "\n",
        "Costruire un circuito a evoluzione temporale. Utilizzate le conoscenze acquisite nelle lezioni precedenti per cercare di ridurre la profondità del circuito.\n",
        "\n",
        "**Soluzione:**\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": [
        "L'iniziativa ha avuto molto successo. Ora possiamo procedere con i restanti passaggi dei modelli Qiskit.\n",
        "\n",
        "<span id=\"32-step-2-optimize-for-target-hardware\" />\n",
        "\n",
        "### 3.2 Fase 2. Ottimizza per l'hardware di destinazione\n",
        "\n",
        "Transpilare i circuiti e riunirli in un elenco. Anche in questo caso, l'operazione potrebbe richiedere alcuni minuti.\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": [
        "Definire il Runtime Estimator e costruire l'elenco dei PUB.\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": [
        "<span id=\"33-step-3-execute-on-target-hardware\" />\n",
        "\n",
        "### 3.3 Passaggio 3. Esecuzione su hardware di destinazione\n",
        "\n",
        "Eseguire il lavoro.\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": [
        "Ottenere i risultati.\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": [
        "<span id=\"34-step-4-post-processing\" />\n",
        "\n",
        "### 3.4 Fase 4. Post-elaborazione\n",
        "\n",
        "Estrarre i valori di aspettativa dai risultati.\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": [
        "Trasforma l'elenco in array numpy per il plottaggio.\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": [
        "Ora tracciamo i risultati e confrontiamo i risultati dell'hardware (circuito predefinito e superficiale) con il simulatore MPS. In che modo l'errore nell'hardware reale influenza i risultati?\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": [
        "Congratulazioni. Avete fatto un ulteriore passo avanti nel vostro viaggio quantico su scala pubblica. Rimane solo una lezione!\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
}