{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "1379da5d-023f-42e7-8a3f-ea8c1e3a1d46",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Diagonalisation quantique de Krylov basée sur des échantillons\"\n",
        "description: \"Les thèmes abordés dans les leçons précédentes sont combinés afin de tirer parti des garanties de convergence du QKD et de la vitesse du SQD dans le SKQD.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore arxiv Neel probs eigenvals Hatano */}\n",
        "\n",
        "<span id=\"sample-based-krylov-quantum-diagonalization-skqd\" />\n",
        "\n",
        "# Diagonalisation quantique de Krylov basée sur des échantillons (SKQD)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "97cfd899-4196-4d24-bf16-60bdd3899600",
      "metadata": {},
      "source": [
        "Cette leçon sur la diagonalisation quantique de Krylov basée sur l'échantillonnage (SKQD) combine les méthodes expliquées dans les méthodes précédentes. Il s'agit d'un exemple unique qui s'appuie sur le cadre de modèles Qiskit :\n",
        "\n",
        "* Étape 1 : Tracer le problème à l'aide de circuits et d'opérateurs quantiques\n",
        "* Étape 2 : Optimisation pour le matériel cible\n",
        "* Étape 3 : Exécution à l'aide des primitives « IBM Quantum »\n",
        "* Étape 4 : Post-traitement\n",
        "\n",
        "Une étape importante de la méthode de diagonalisation quantique basée sur l'échantillon consiste à générer des vecteurs de qualité pour le sous-espace. Dans la leçon précédente, nous avons utilisé l'ansatz LUCJ pour générer des vecteurs de sous-espace pour un hamiltonien de chimie. Dans cette leçon, nous utiliserons les états de Krylov quantiques [\\[1\\]](#references), comme nous l'avons vu dans la leçon 2. Tout d'abord, nous verrons comment créer l'espace de Krylov sur un ordinateur quantique en utilisant des opérations d'évolution temporelle. Nous en tirerons ensuite un échantillon. Nous projetterons l'hamiltonien du système sur le sous-espace échantillonné et le diagonaliserons pour estimer l'énergie de l'état fondamental. L'algorithme converge de manière prouvée et efficace vers l'état fondamental, sous les hypothèses décrites dans la leçon 2.\n",
        "\n",
        "<span id=\"0-the-krylov-space\" />\n",
        "\n",
        "## 0. L'espace de Krylov\n",
        "\n",
        "Rappelons qu'un espace de Krylov $\\mathcal{K}^r$ d'ordre $r$ est l'espace couvert par les vecteurs obtenus en multipliant les puissances supérieures d'une matrice $A$, jusqu'à $r-1$, avec un vecteur de référence $\\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",
        "Si la matrice $A$ est l'hamiltonien $H$, l'espace correspondant est appelé *espace de Krylov des puissances* $\\mathcal{K}_P$. Dans le cas où $A$ est l'opérateur d'évolution temporelle généré par l'hamiltonien $U=e^{-iH(dt)}$, l'espace est appelé espace de Krylov unitaire $\\mathcal{K}_U$. Le sous-espace de Krylov puissance ne peut pas être généré directement sur un ordinateur quantique car $H$ n'est pas un opérateur unitaire. Au lieu de cela, nous pouvons utiliser l'opérateur d'évolution temporelle $U = e^{-iH(dt)}$, dont on peut montrer qu'il offre des [garanties de convergence](https://arxiv.org/abs/2110.07492) similaires à celles de l'espace de Krylov puissance. Les puissances de $U$ deviennent alors des pas de temps différents $U^k = e^{-iH(k dt)}$ où $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. Mapper le problème sur des circuits quantiques et des opérateurs\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5888e3e8-51a1-426a-9023-c137aa9c6c83",
      "metadata": {},
      "source": [
        "Dans cette leçon, nous considérons l'hamiltonien de la chaîne antiferromagnétique XX-Z spin-1/2 avec des sites $L = 22$ avec la condition de limite périodique :\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": [
        "Pour construire l'espace de Krylov, nous avons besoin de trois ingrédients principaux :\n",
        "\n",
        "1. Choix de la dimension de Krylov ( $r$ ) et du pas de temps ( $dt$ ).\n",
        "2. Un état initial (de référence) (vecteur $\\vert v \\rangle$ ci-dessus) avec un chevauchement polynomial avec l'état cible (au sol), lorsque l'état cible est peu dense. Cette exigence de chevauchement polynomial est la même que dans l'algorithme d'estimation de la phase quantique.\n",
        "3. Opérateurs d'évolution temporelle $U^{k}=e^{-iH(k * dt)}$ ( $k = 0, 1, 2, ..., r-1$ ).\n",
        "\n",
        "Pour une valeur choisie de $r$ (et, $dt$ ), nous créerons $r$ circuits quantiques distincts et les échantillonnerons. Chaque circuit quantique est créé en joignant la représentation du circuit quantique de l'état de référence et l'opérateur d'évolution temporelle pour une valeur $k$.\n",
        "\n",
        "Une dimension de Krylov plus importante améliore la convergence de l'énergie estimée. Dans cette leçon, nous avons fixé la dimension à $5$ pour illustrer la tendance à la convergence.\n",
        "\n",
        "Ref [\\[2\\]](#references) a montré qu'un pas de temps suffisamment petit pour la KQD est $\\pi / \\vert \\vert H \\vert \\vert$, et qu'il est préférable de sous-estimer cette valeur plutôt que de la surestimer. D'autre part, si l'on choisit $dt$ comme étant trop petit, le conditionnement du sous-espace de Krylov est moins bon, car les vecteurs de base de Krylov diffèrent moins d'un pas de temps à l'autre. En outre, bien que ce choix de $dt$ soit adéquat pour la convergence de SKQD, dans ce contexte basé sur l'échantillonnage, le choix optimal de $dt$ dans la pratique est un sujet d'étude en cours. Dans cette leçon, nous avons défini $dt = 0.15$.\n",
        "\n",
        "Outre la dimension de Krylov et le pas de temps, nous devons définir le nombre de pas de Trotter pour l'évolution temporelle. L'utilisation d'un nombre insuffisant d'étapes conduit à des erreurs de trotterisation plus importantes, tandis qu'un nombre trop élevé d'étapes conduit à des circuits plus profonds. Dans cette leçon, nous avons fixé le nombre de pas de Trotter à $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": [
        "Ensuite, nous devons choisir un état de référence $\\vert \\psi \\rangle$ qui présente un certain chevauchement avec l'état fondamental. Pour cet hamiltonien, nous utilisons l'état de *Neel* avec une alternance de 1s et 0s $\\vert ...101...010...101 \\rangle$ comme état de référence.\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": [
        "Enfin, nous devons faire correspondre l'opérateur d'évolution temporelle à un circuit quantique. Cela a été fait dans la leçon 2, mais ici nous allons utiliser des méthodes de Qiskit, en particulier une méthode appelée *synthèse*. Il existe différentes méthodes pour synthétiser les opérateurs mathématiques en circuits quantiques avec des portes quantiques. De nombreuses techniques de ce type sont disponibles dans le [module de synthèse Qiskit](/docs/api/qiskit/synthesis). Nous utiliserons l'approche [`LieTrotter`](/docs/api/qiskit/qiskit.synthesis.LieTrotter) de synthèse [\\[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. Optimisation pour le matériel cible\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6ed5a22f-4bdc-4a8d-ad39-5307308d0cc4",
      "metadata": {},
      "source": [
        "Maintenant que nous avons créé les circuits, nous pouvons les optimiser pour un matériel cible. Nous choisissons une QPU à l'échelle d'un service public.\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": [
        "Nous transposons ensuite les circuits vers le backend cible à l'aide d'un gestionnaire de passe prédéfini.\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. Exécuter sur le matériel cible\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6aa67e8c-30db-4e11-9bf2-150c157ec49c",
      "metadata": {},
      "source": [
        "Après avoir optimisé les circuits pour l'exécution matérielle, nous sommes prêts à les exécuter sur le matériel cible et à collecter des échantillons pour l'estimation de l'énergie de l'état fondamental.\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. Résultats post-traitement\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "75321a43-0740-4d13-bdc4-350b44727b62",
      "metadata": {},
      "source": [
        "Ensuite, nous agrégeons les chiffres pour les dimensions de Krylov croissantes de manière cumulative. En utilisant les comptes cumulés, nous couvrirons des sous-espaces pour une dimension de Krylov croissante et analyserons le comportement de convergence.\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": [
        "Pour projeter et diagonaliser l'hamiltonien, nous utilisons les capacités de [`qiskit-addon-sqd`](https://qiskit.github.io/qiskit-addon-sqd/). L'addon offre des fonctionnalités permettant de projeter les hamiltoniens basés sur la chaîne de Pauli sur un sous-espace et de résoudre les valeurs propres à l'aide de `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": [
        "En principe, nous pouvons filtrer les chaînes de bits présentant un motif incorrect avant de couvrir le sous-espace. Par exemple, l'état fondamental de l'hamiltonien antiferromagnétique de cette leçon présente généralement un nombre égal de spins \"up\" et \"down\", c'est-à-dire que le nombre de \"1\" dans la chaîne de bits doit être exactement égal à la moitié du nombre total de bits (spins) dans le système. La fonction suivante filtre les chaînes de bits dont le nombre de \"1\" est incorrect.\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": [
        "En utilisant des chaînes de bits avec le nombre correct d'électrons ascendants/descendants, nous couvrons des sous-espaces et calculons les valeurs propres pour une dimension de Krylov croissante. En fonction de la taille du problème et des ressources classiques disponibles, il peut s'avérer nécessaire d'adopter un sous-échantillonnage (similaire à la [leçon sur le SQD](/learning/courses/quantum-diagonalization-algorithms/sqd-implementation) ) pour contrôler la dimension du sous-espace. De plus, nous pouvons appliquer la notion de récupération de configuration similaire à la leçon 4. Nous pouvons calculer l'occupation électronique par site à partir des états propres reconstruits et utiliser ces informations pour corriger les chaînes de bits comportant un nombre incorrect d'électrons ascendants/descendants. Nous laissons cet exercice aux lecteurs intéressés.\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": [
        "Ensuite, nous traçons l'énergie calculée en fonction de la dimension de Krylov et la comparons à l'énergie exacte. L'énergie exacte est calculée séparément à l'aide d'une méthode classique de force brute. Nous pouvons constater que l'énergie estimée de l'état fondamental converge avec l'augmentation de la dimension de l'espace de Krylov. Bien que la dimension de Krylov de $5$ soit limitée, les résultats montrent toujours une convergence impressionnante, qui devrait s'améliorer avec une dimension de Krylov plus grande [\\[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",
        "#### Vérifiez votre compréhension\n",
        "\n",
        "Lisez les questions ci-dessous, réfléchissez à vos réponses, puis cliquez sur les triangles pour trouver les solutions.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Que pourrait-on faire pour améliorer la convergence dans le graphique ci-dessus?\">\n",
        "    **Réponse :**\n",
        "\n",
        "    Augmenter la dimension de Krylov. En général, on pourrait aussi augmenter le nombre de tirs, mais celui-ci est déjà assez élevé dans le calcul ci-dessus.\n",
        "  </AccordionItem>\n",
        "\n",
        "  <AccordionItem title=\"Quels sont les principaux avantages du SKQD par rapport (a) au SQD et (b) au KQD?\">\n",
        "    **Réponse :**\n",
        "\n",
        "    Il peut y avoir d'autres réponses valables, mais les réponses complètes doivent comprendre les éléments suivants :\n",
        "\n",
        "    (a) SKQD offre des garanties de convergence que SQD n'offre pas. En SQD, vous devez soit faire une très bonne supposition pour votre ansatz qui a un excellent chevauchement avec le support de l'état fondamental dans la base de calcul, soit introduire une composante variationnelle dans le calcul pour échantillonner une famille d'ansatz.\n",
        "\n",
        "    (b) SKQD nécessite beaucoup moins de temps QPU, car il évite le calcul coûteux des éléments de la matrice via le test de 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. Résumé\n",
        "\n",
        "* L'estimation de l'énergie de l'état fondamental par l'échantillonnage des états de base de Krylov est très bien adaptée aux modèles de treillis, y compris les systèmes de spin, les problèmes de matière condensée et les théories de jauge sur treillis. Cette approche s'adapte beaucoup mieux que l'EQV, car elle ne nécessite pas d'optimisation sur de nombreux paramètres dans un ansatz variationnel comme dans l'EQV, ou dans la SQD basée sur un ansatz heuristique (par exemple, le problème de chimie de la leçon précédente).\n",
        "  * Pour réduire la profondeur des circuits, il est judicieux d'aborder les problèmes de treillis qui se prêtent à l'utilisation de matériel tolérant aux pannes.\n",
        "* SKQD ne pose pas de problème de mesure quantique comme dans VQE. Il n'y a pas de groupes d'opérateurs de Pauli commutés à estimer.\n",
        "* La méthode SKQD est résistante aux échantillons bruités, car il est possible d'utiliser une routine de post-sélection spécifique au problème (par exemple, en filtrant les chaînes binaires qui ne respectent pas les motifs propres au problème) ou d'accepter la surcharge liée à la diagonalisation classique (c'est-à-dire de diagonaliser dans un sous-espace plus grand) afin d'éliminer efficacement l'effet du bruit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c52bada7-1912-41f2-a770-3145a947de63",
      "metadata": {},
      "source": [
        "<span id=\"references\" />\n",
        "\n",
        "## Références\n",
        "\n",
        "\\[1] Jeffery Yu et al, \"Algorithme centré sur le quantum pour la diagonalisation de Krylov basée sur l'échantillonnage\" (2025). [arxiv:quant-ph/2501.09702](https://arxiv.org/abs/2501.09702).\n",
        "\n",
        "\\[2] Ethan N. Epperly, Lin Lin et Yuji Nakatsukasa. \"Une théorie de la diagonalisation du sous-espace quantique\". SIAM Journal on Matrix Analysis and Applications 43, 1263-1290 (2022).\n",
        "\n",
        "\\[2] N. Hatano et M. Suzuki, \"Finding Exponential Product Formulas of Higher Orders\" (2005). [arXiv:math-ph/0506007](https://arxiv.org/abs/math-ph/0506007).\n",
        "\n",
        "\\[4] D. Berry, G. Ahokas, R. Cleve et 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
}