{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "1379da5d-023f-42e7-8a3f-ea8c1e3a1d46",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Diagonalizzazione quantistica di Krylov basata su campioni\"\n",
        "description: \"Gli argomenti delle lezioni precedenti vengono combinati per sfruttare le garanzie di convergenza del QKD e la velocità dell'SQD nell'SKQD.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore arxiv Neel probs eigenvals Hatano */}\n",
        "\n",
        "<span id=\"sample-based-krylov-quantum-diagonalization-skqd\" />\n",
        "\n",
        "# Diagonalizzazione quantistica di Krylov basata su campioni (SKQD)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "97cfd899-4196-4d24-bf16-60bdd3899600",
      "metadata": {},
      "source": [
        "Questa lezione sulla diagonalizzazione quantistica di Krylov basata su campioni (SKQD) combina i metodi spiegati nei metodi precedenti. Si tratta di un singolo esempio che sfrutta il framework di modelli Qiskit:\n",
        "\n",
        "* Fase 1: mappare il problema in circuiti e operatori quantistici\n",
        "* Fase 2: Ottimizzazione per l'hardware di destinazione\n",
        "* Fase 3: Esecuzione tramite le primitive \" IBM Quantum \"\n",
        "* Fase 4: Post-processing\n",
        "\n",
        "Un passo importante nel metodo di diagonalizzazione quantistica basato sui campioni è la generazione di vettori di qualità per il sottospazio. Nella lezione precedente, abbiamo utilizzato l'ansatz LUCJ per generare vettori di sottospazi per un'hamiltoniana chimica. In questa lezione utilizzeremo gli stati di Krylov quantistici [\\[1\\]](#references), come già discusso nella lezione 2. In primo luogo, esamineremo come creare lo spazio di Krylov su un computer quantistico utilizzando operazioni di evoluzione temporale. Poi ne faremo un campione. Proietteremo l'hamiltoniana del sistema sul sottospazio campionato e la diagonalizzeremo per stimare l'energia dello stato fondamentale. L'algoritmo converge in modo dimostrabile ed efficiente allo stato fondamentale, sotto le ipotesi descritte nella lezione 2.\n",
        "\n",
        "<span id=\"0-the-krylov-space\" />\n",
        "\n",
        "## 0. Lo spazio di Krylov\n",
        "\n",
        "Ricordiamo che uno spazio di Krylov $\\mathcal{K}^r$ di ordine $r$ è lo spazio spaziato dai vettori ottenuti moltiplicando le potenze superiori di una matrice $A$, fino a $r-1$, con un vettore di riferimento $\\vert v \\rangle$.\n",
        "\n",
        "$$\n",
        "\\mathcal{K}^r = \\left\\{ \\vert v \\rangle, A \\vert v \\rangle, A^2 \\vert v \\rangle, ..., A^{r-1} \\vert v \\rangle \\right\\}\n",
        "$$\n",
        "\n",
        "Se la matrice $A$ è l'hamiltoniana $H$, lo spazio corrispondente è chiamato *spazio di Krylov di potenza* $\\mathcal{K}_P$. Nel caso in cui $A$ sia l'operatore di evoluzione temporale generato dall'hamiltoniana $U=e^{-iH(dt)}$, lo spazio è chiamato spazio di Krylov unitario $\\mathcal{K}_U$. Il sottospazio di Krylov di potenza non può essere generato direttamente su un computer quantistico poiché $H$ non è un operatore unitario. Si può invece utilizzare l'operatore di evoluzione temporale $U = e^{-iH(dt)}$, che si può dimostrare dia [garanzie di convergenza](https://arxiv.org/abs/2110.07492) simili a quelle dello spazio di Krylov di potenza. Le potenze di $U$ diventano quindi passi temporali diversi $U^k = e^{-iH(k dt)}$ dove $k = 0, 1, 2, ..., (r-1)$.\n",
        "\n",
        "$$\n",
        "\\mathcal{K}_U^r = \\left\\{ \\vert \\psi \\rangle, U \\vert \\psi \\rangle, U^2 \\vert \\psi \\rangle, ..., U^{r-1} \\vert \\psi \\rangle \\right\\}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "864a0ce7-d094-48ea-9cf0-2a7e38791815",
      "metadata": {},
      "source": [
        "<span id=\"1-map-problem-to-quantum-circuits-and-operators\" />\n",
        "\n",
        "## 1. Mappare il problema su circuiti quantistici e operatori\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5888e3e8-51a1-426a-9023-c137aa9c6c83",
      "metadata": {},
      "source": [
        "In questa lezione consideriamo l'hamiltoniana per la catena antiferromagnetica XX-Z spin-1/2 con $L = 22$ siti con condizione al contorno periodica:\n",
        "\n",
        "$$\n",
        "    H = \\sum_{i, j}^{N} J_{xy} (X_{i} X_{j} + Y_{i} Y_{j}) + Z_{i} Z_{j}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "f0d3e153-17da-4457-b1d2-2a35d31aea3a",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler import CouplingMap\n",
        "from qiskit_addon_utils.problem_generators import generate_xyz_hamiltonian\n",
        "\n",
        "num_spins = 22\n",
        "coupling_map = CouplingMap.from_ring(num_spins)\n",
        "H_op = generate_xyz_hamiltonian(coupling_map, coupling_constants=(0.3, 0.3, 1.0))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b0660e0d-5521-4095-a810-949729421b57",
      "metadata": {},
      "source": [
        "Per costruire lo spazio di Krylov, abbiamo bisogno di tre ingredienti principali:\n",
        "\n",
        "1. Una scelta della dimensione di Krylov ( $r$ ) e del passo temporale ( $dt$ ).\n",
        "2. Uno stato iniziale (di riferimento) (vettore $\\vert v \\rangle$ sopra) con sovrapposizione polinomiale con lo stato target (di terra), dove lo stato target è rado. Questo requisito di sovrapposizione polinomiale è lo stesso dell'algoritmo di stima quantistica della fase.\n",
        "3. Operatori di evoluzione temporale $U^{k}=e^{-iH(k * dt)}$ ( $k = 0, 1, 2, ..., r-1$ ).\n",
        "\n",
        "Per un valore scelto di $r$ (e, $dt$ ), creeremo $r$ circuiti quantistici separati e li campioneremo. Ogni circuito quantistico viene creato unendo la rappresentazione del circuito quantistico dello stato di riferimento e l'operatore di evoluzione temporale per un valore $k$.\n",
        "\n",
        "Una dimensione di Krylov maggiore migliora la convergenza dell'energia stimata. In questa lezione impostiamo la dimensione su $5$ per illustrare la tendenza alla convergenza.\n",
        "\n",
        "Ref [\\[2\\]](#references) ha dimostrato che un passo temporale sufficientemente piccolo per KQD è $\\pi / \\vert \\vert H \\vert \\vert$, e che è preferibile sottostimare questo valore piuttosto che sovrastimarlo. D'altra parte, la scelta di $dt$ troppo piccola porta a un condizionamento peggiore del sottospazio di Krylov, poiché i vettori base di Krylov differiscono meno da un passo all'altro. Inoltre, mentre questa scelta di $dt$ è provatamente adeguata per la convergenza di SKQD, in questo contesto basato sul campionamento la scelta ottimale di $dt$ nella pratica è un argomento di studio in corso. In questa lezione, impostiamo $dt = 0.15$.\n",
        "\n",
        "Oltre alla dimensione di Krylov e al passo temporale, è necessario impostare il numero di passi di Trotter per l'evoluzione temporale. L'utilizzo di un numero insufficiente di passaggi porta a errori di trotterizzazione maggiori, mentre un numero eccessivo di passaggi porta a circuiti più profondi. In questa lezione, impostiamo il numero di passi di Trotter su $6$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "52eb15e3-e06c-4820-bad1-80fb7c05feee",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Set parameters for quantum Krylov algorithm\n",
        "krylov_dim = 5  # size of krylov subspace\n",
        "dt = 0.15\n",
        "num_trotter_steps = 6"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a716ea3e-b3d6-42de-8ed5-331e6416e586",
      "metadata": {},
      "source": [
        "Successivamente, dobbiamo scegliere uno stato di riferimento $\\vert \\psi \\rangle$ che abbia una certa sovrapposizione con lo stato fondamentale. Per questa hamiltoniana, utilizziamo lo stato di *Neel* con 1s e 0s $\\vert ...101...010...101 \\rangle$ alternati come stato di riferimento.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "53347df7-b43c-4859-a9ea-a3dea2a44184",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Prep `Neel` state as the reference state for evolution\n",
        "from qiskit import QuantumCircuit\n",
        "\n",
        "qc_state_prep = QuantumCircuit(num_spins)\n",
        "for i in range(num_spins):\n",
        "    if i % 2 == 0:\n",
        "        qc_state_prep.x(i)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6952aaf2-c598-4ce9-8dc5-e63f0725de10",
      "metadata": {},
      "source": [
        "Infine, dobbiamo mappare l'operatore di evoluzione temporale in un circuito quantistico. Questo è stato fatto nella lezione 2, ma qui sfrutteremo i metodi di Qiskit, in particolare un metodo chiamato *sintesi*. Esistono diversi metodi per sintetizzare gli operatori matematici in circuiti quantistici con porte quantistiche. Molte di queste tecniche sono disponibili nel [modulo di sintesi Qiskit](/docs/api/qiskit/synthesis). Utilizzeremo l'approccio [`LieTrotter`](/docs/api/qiskit/qiskit.synthesis.LieTrotter) approccio per la sintesi [\\[3\\]](#references) [\\[4\\]](#references).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "c82afe58-a90a-49a9-9dfe-c24b2b5d0a8c",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.circuit import QuantumRegister\n",
        "from qiskit.circuit.library import PauliEvolutionGate\n",
        "from qiskit.synthesis import LieTrotter\n",
        "\n",
        "evol_gate = PauliEvolutionGate(\n",
        "    H_op, time=(dt / num_trotter_steps), synthesis=LieTrotter(reps=num_trotter_steps)\n",
        ")  # `U` operator\n",
        "\n",
        "qr = QuantumRegister(num_spins)\n",
        "qc_evol = QuantumCircuit(qr)\n",
        "qc_evol.append(evol_gate, qargs=qr)\n",
        "\n",
        "circuits = []\n",
        "for rep in range(krylov_dim):\n",
        "    circ = qc_state_prep.copy()\n",
        "\n",
        "    # Repeating the `U` operator to implement U^0, U^1, U^2, and so on, for power Krylov space\n",
        "    for _ in range(rep):\n",
        "        circ.compose(other=qc_evol, inplace=True)\n",
        "\n",
        "    circ.measure_all()\n",
        "    circuits.append(circ)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "7ffc3eaa-9563-4c89-9d7b-808a3a37b275",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/quantum-diagonalization-algorithms/qda-5-skqd/extracted-outputs/7ffc3eaa-9563-4c89-9d7b-808a3a37b275-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "circuits[1].decompose().draw(\"mpl\", fold=-1)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "bdbc0881-06b0-49f2-8919-a376aa7f08e3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/quantum-diagonalization-algorithms/qda-5-skqd/extracted-outputs/bdbc0881-06b0-49f2-8919-a376aa7f08e3-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "circuits[2].decompose().draw(\"mpl\", fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9b43f693-b6d0-43cb-b982-3f8a3b6e185d",
      "metadata": {},
      "source": [
        "<span id=\"2-optimize-for-target-hardware\" />\n",
        "\n",
        "## 2. Ottimizzazione per l'hardware di destinazione\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6ed5a22f-4bdc-4a8d-ad39-5307308d0cc4",
      "metadata": {},
      "source": [
        "Ora che abbiamo creato i circuiti, possiamo ottimizzarli per l'hardware di destinazione. Scegliamo una QPU su scala utility.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "8944305a-0f29-4f97-a04f-43249cdc02ea",
      "metadata": {},
      "outputs": [],
      "source": [
        "import warnings\n",
        "\n",
        "from qiskit import generate_preset_pass_manager\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "warnings.filterwarnings(\"ignore\")\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "# Use the least-busy backend or specify a quantum computer using the syntax commented out below.\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "# backend = service.backend(\"ibm_brisbane\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3ed422ad-04f5-4f1f-a142-f08a0ac0a34b",
      "metadata": {},
      "source": [
        "A questo punto, transpiliamo i circuiti nel backend di destinazione utilizzando un gestore di pass preimpostati.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "8a72b655-ccee-4927-8bf2-b99d0b92723a",
      "metadata": {},
      "outputs": [],
      "source": [
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
        "isa_circuits = pm.run(circuits=circuits)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6405ab01-5cec-4a02-8846-f9ba626d9cdc",
      "metadata": {},
      "source": [
        "<span id=\"3-execute-on-target-hardware\" />\n",
        "\n",
        "## 3. Eseguire sull'hardware di destinazione\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6aa67e8c-30db-4e11-9bf2-150c157ec49c",
      "metadata": {},
      "source": [
        "Dopo aver ottimizzato i circuiti per l'esecuzione hardware, siamo pronti a eseguirli sull'hardware di destinazione e a raccogliere campioni per la stima dell'energia dello stato di massa.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "0613c95b-e696-4ddb-8f51-dc1714d21a0e",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import SamplerV2 as Sampler\n",
        "\n",
        "sampler = Sampler(mode=backend)\n",
        "job = sampler.run(isa_circuits, shots=100_000)  # Takes approximately 2m 58s of QPU time"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "1c60e828-9359-46c6-84ef-88aecdb85b81",
      "metadata": {},
      "outputs": [],
      "source": [
        "counts_all = [job.result()[k].data.meas.get_counts() for k in range(krylov_dim)]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fa2fcfe0-66ab-4230-9262-9a46ecda034b",
      "metadata": {},
      "source": [
        "<span id=\"4-post-process-results\" />\n",
        "\n",
        "## 4. Risultati post-elaborazione\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "75321a43-0740-4d13-bdc4-350b44727b62",
      "metadata": {},
      "source": [
        "Successivamente, aggreghiamo i conteggi per dimensioni di Krylov crescenti in modo cumulativo. Utilizzando i conteggi cumulativi, si analizzano i sottospazi a dimensione Krylov crescente e si analizza il comportamento di convergenza.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "9954125c-5ad8-40e8-affa-4a644354c51f",
      "metadata": {},
      "outputs": [],
      "source": [
        "from collections import Counter\n",
        "\n",
        "counts_cumulative = []\n",
        "for i in range(krylov_dim):\n",
        "    counter = Counter()\n",
        "    for d in counts_all[: i + 1]:\n",
        "        counter.update(d)\n",
        "\n",
        "    counts = dict(counter)\n",
        "    counts_cumulative.append(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "14fcdfc2-b37e-4a9c-9794-7c1fa9a6ab1b",
      "metadata": {},
      "source": [
        "Per proiettare e diagonalizzare l'hamiltoniana, utilizziamo le capacità di [`qiskit-addon-sqd`](https://qiskit.github.io/qiskit-addon-sqd/). L'addon offre funzionalità per proiettare gli hamiltoniani basati sulle stringhe di Pauli su un sottospazio e risolve gli autovalori utilizzando `SciPy`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "5ace841d-59c6-4ea1-9ceb-6f6436546093",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_addon_sqd.counts import counts_to_arrays\n",
        "from qiskit_addon_sqd.qubit import solve_qubit"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "104cc0fd-4fa0-469b-bfb8-4089cea5145f",
      "metadata": {},
      "source": [
        "In linea di principio, è possibile filtrare le stringhe di bit con un modello errato prima di eseguire lo spanning del sottospazio. Ad esempio, lo stato fondamentale per l'hamiltoniana antiferromagnetica di questa lezione ha un numero uguale di spin \"up\" e \"down\", cioè il numero di \"1\" nella stringa di bit dovrebbe essere esattamente la metà del numero totale di bit (spin) nel sistema. La funzione seguente filtra le stringhe di bit con un numero errato di \"1\" dai conteggi.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 37,
      "id": "81d728a1-6ab4-4664-a7ca-2017dae10e1a",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Filters out bitstrings that do not have specified number (`num_ones`) of `1` bits.\n",
        "def postselect_counts(counts, num_ones):\n",
        "    filtered_counts = {}\n",
        "    for bitstring, freq in counts.items():\n",
        "        if bitstring.count(\"1\") == num_ones:\n",
        "            filtered_counts[bitstring] = freq\n",
        "\n",
        "    return filtered_counts"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d77772f5-fe1c-4a6c-abcb-c2c3c7d7293a",
      "metadata": {},
      "source": [
        "Utilizzando bitstring con il numero corretto di elettroni up/down, si estendono i sottospazi e si calcolano gli autovalori per una dimensione di Krylov crescente. A seconda delle dimensioni del problema e delle risorse classiche disponibili, potrebbe essere necessario adottare il sottocampionamento (simile alla [lezione sull'SQD](/learning/courses/quantum-diagonalization-algorithms/sqd-implementation) ) per tenere sotto controllo la dimensione del sottospazio. Inoltre, è possibile applicare la nozione di recupero della configurazione, come nella Lezione 4. Possiamo calcolare l'occupazione degli elettroni per sito dagli autostati ricostruiti e utilizzare le informazioni per correggere le bitstring con un numero errato di elettroni up/down. Lo lasciamo come esercizio per i lettori interessati.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 38,
      "id": "f0e0f56f-ec56-40b6-b8be-059be35d2ce5",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "\n",
        "num_batches = 10\n",
        "rand_seed = 0\n",
        "scipy_kwargs = {\"k\": 2, \"which\": \"SA\"}\n",
        "\n",
        "ground_state_energies = []\n",
        "for idx, counts in enumerate(counts_cumulative):\n",
        "    counts = postselect_counts(counts, num_ones=num_spins // 2)\n",
        "    bitstring_matrix, probs = counts_to_arrays(counts=counts)\n",
        "\n",
        "    eigenvals, eigenstates = solve_qubit(\n",
        "        bitstring_matrix, H_op, verbose=False, **scipy_kwargs\n",
        "    )\n",
        "    gs_en = np.min(eigenvals)\n",
        "    ground_state_energies.append(gs_en)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "67b2a04b-4e70-45dc-bd21-2c4340c18377",
      "metadata": {},
      "source": [
        "Quindi, tracciamo l'energia calcolata in funzione della dimensione di Krylov e la confrontiamo con l'energia esatta. L'energia esatta viene calcolata separatamente con un metodo classico di forza bruta. Si può notare che l'energia di stato fondamentale stimata converge con l'aumentare della dimensione dello spazio di Krylov. Sebbene la dimensione di Krylov di $5$ sia limitante, i risultati mostrano comunque una convergenza impressionante, che dovrebbe migliorare con una dimensione di Krylov maggiore [\\[1\\]](#references).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 39,
      "id": "debca96a-e0e3-4342-a755-8204dba50d74",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/quantum-diagonalization-algorithms/qda-5-skqd/extracted-outputs/debca96a-e0e3-4342-a755-8204dba50d74-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "\n",
        "exact_gs_en = -23.934184\n",
        "plt.plot(\n",
        "    range(1, krylov_dim + 1),\n",
        "    ground_state_energies,\n",
        "    color=\"blue\",\n",
        "    linestyle=\"-.\",\n",
        "    label=\"estimate\",\n",
        ")\n",
        "plt.plot(\n",
        "    range(1, krylov_dim + 1),\n",
        "    [exact_gs_en] * krylov_dim,\n",
        "    color=\"red\",\n",
        "    linestyle=\"-\",\n",
        "    label=\"exact\",\n",
        ")\n",
        "plt.xticks(range(1, krylov_dim + 1), range(1, krylov_dim + 1))\n",
        "plt.legend()\n",
        "plt.xlabel(\"Krylov space dimension\")\n",
        "plt.ylabel(\"Energy\")\n",
        "plt.ylim([-24, -22.50])\n",
        "plt.title(\n",
        "    \"Estimating Ground state energy with Sample-based Krylov Quantum Diagonalization\"\n",
        ")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5865567b-cc32-48dd-b7f9-32ce64d7dd7c",
      "metadata": {},
      "source": [
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Verifica la tua comprensione\n",
        "\n",
        "Leggete le domande qui sotto, riflettete sulle vostre risposte, quindi fate clic sui triangoli per scoprire le soluzioni.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Cosa si potrebbe fare per migliorare la convergenza nel grafico sopra riportato?\">\n",
        "    **Risposta:**\n",
        "\n",
        "    Aumentare la dimensione di Krylov. In generale, si potrebbe anche aumentare il numero di colpi, ma questo è già abbastanza alto nel calcolo precedente.\n",
        "  </AccordionItem>\n",
        "\n",
        "  <AccordionItem title=\"Quali sono i principali vantaggi di SKQD rispetto a (a) SQD e (b) KQD?\">\n",
        "    **Risposta:**\n",
        "\n",
        "    Possono esserci altre risposte valide, ma le risposte complete devono includere quanto segue:\n",
        "\n",
        "    (a) SKQD offre garanzie di convergenza che SQD non ha. In SQD è necessario fare un'ottima ipotesi per il proprio ansatz che abbia un'eccellente sovrapposizione con il supporto dello stato fondamentale nella base computazionale, oppure introdurre una componente variazionale nel calcolo per campionare una famiglia di ansaetze.\n",
        "\n",
        "    (b) SKQD richiede molto meno tempo di QPU, perché evita il costoso calcolo degli elementi della matrice tramite il test di Hadamard.\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a4cf119d-65cf-456c-be0d-731bb7a6799a",
      "metadata": {},
      "source": [
        "<span id=\"5-summary\" />\n",
        "\n",
        "## 5. Riepilogo\n",
        "\n",
        "* La stima dell'energia di stato fondamentale attraverso il campionamento degli stati base di Krylov è molto adatta ai modelli reticolari, compresi i sistemi di spin, i problemi della materia condensata e le teorie di gauge reticolari. Questo approccio si adatta molto meglio del VQE, perché non richiede l'ottimizzazione di molti parametri in un'ipotesi variazionale come nel VQE o in un SQD euristico basato su ipotesi (per esempio, il problema della chimica nella lezione precedente).\n",
        "  * Per mantenere basse le profondità dei circuiti, è consigliabile affrontare i problemi di reticolo che si prestano a un hardware con tolleranza ai guasti.\n",
        "* L'SKQD non incorre in un problema di misurazione quantistica come nel VQE. Non ci sono gruppi di operatori di Pauli pendolari da stimare.\n",
        "* SKQD è resistente ai campioni rumorosi, poiché è possibile ricorrere a una routine di post-selezione specifica per il problema (ad esempio, filtrando le stringhe di bit che non rispettano i modelli specifici del problema) oppure sostenere il classico overhead della diagonalizzazione (ovvero, diagonalizzare in un sottospazio più ampio) per eliminare efficacemente l'effetto del rumore.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c52bada7-1912-41f2-a770-3145a947de63",
      "metadata": {},
      "source": [
        "<span id=\"references\" />\n",
        "\n",
        "## Riferimenti\n",
        "\n",
        "\\[1] Jeffery Yu e altri, \"Algoritmo quantistico per la diagonalizzazione di Krylov basata su campioni\" (2025). [arxiv:quant-ph/2501.09702](https://arxiv.org/abs/2501.09702).\n",
        "\n",
        "\\[2] Ethan N. Epperly, Lin Lin e Yuji Nakatsukasa. \"Una teoria della diagonalizzazione dei sottospazi quantistici\". SIAM Journal on Matrix Analysis and Applications 43, 1263-1290 (2022).\n",
        "\n",
        "\\[2] N. Hatano e M. Suzuki, \"Trovare formule di prodotti esponenziali di ordine superiore\" (2005). [arXiv:math-ph/0506007](https://arxiv.org/abs/math-ph/0506007).\n",
        "\n",
        "\\[4] D. Berry, G. Ahokas, R. Cleve e B. Sanders, \"Efficient quantum algorithms for simulating sparse Hamiltonians\" (2006). [arXiv:quant-ph/0508139](https://arxiv.org/abs/quant-ph/0508139).\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"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}