{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "e6e50bd6-8ac4-40b1-ac0f-6e22b6af1377",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Simuler un modèle d'Ising avec la fonction TEM\"\n",
        "description: \"Introduction à TEM, une fonction Qiskit développée par Algorithmiq, permettant de calculer des estimations avec atténuation des erreurs de post-traitement logiciel à l'aide de réseaux de tenseurs.\"\n",
        "---\n",
        "\n",
        "<span id=\"simulate-a-kicked-ising-model-with-the-tem-function\" />\n",
        "\n",
        "# Simuler un modèle d'Ising avec la fonction TEM\n",
        "\n",
        "{/* cspell:ignore Floquet, linestyles */}\n",
        "\n",
        "La méthode TEM (Tensor-network Error Mitigation) d'Algorithmiq est un algorithme hybride quantique-classique conçu pour atténuer le bruit entièrement au cours de la phase de post-traitement classique. Avec TEM, l'utilisateur peut calculer les valeurs attendues des observables, atténuant ainsi les erreurs inévitables induites par le bruit qui se produisent sur le matériel quantique avec une précision et une rentabilité accrues, ce qui en fait une option très intéressante pour les chercheurs quantiques et les professionnels du secteur.\n",
        "\n",
        "Ce tutoriel montre comment la TEM peut obtenir des résultats significatifs pour la dynamique d'un système quantique, qui seraient inaccessibles sans atténuation des erreurs et qui nécessiteraient beaucoup plus de ressources quantiques si d'autres méthodes d'atténuation des erreurs telles que la PEC et la ZNE étaient utilisées.\n",
        "\n",
        "*Estimation d'utilisation : ce notebook utilise environ 10 minutes QPU sur les appareils Heron r3. La durée d'exécution peut dépendre considérablement de l'appareil choisi. Les estimations d'utilisation par section sont disponibles ci-dessous.*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1f5e328d-fe93-4ee2-995b-2e70b36ea0de",
      "metadata": {},
      "source": [
        "<span id=\"run-error-mitigated-many-body-physics-experiments-with-the-tem-function\" />\n",
        "\n",
        "## Réalisez des expériences de physique à plusieurs corps avec atténuation des erreurs grâce à la fonction TEM\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b63a662c-a4e9-4b5f-92fd-46352a2bd0bd",
      "metadata": {},
      "source": [
        "Ce tutoriel est basé sur la référence suivante : [L. E. Fischer et al., Nat. Phys. (2026)](https://www.nature.com/articles/s41567-025-03144-9). Cette référence traite d'une simulation réelle sur du matériel quantique pouvant atteindre 91 qubits. Dans ce tutoriel, nous recréons une simulation similaire sur un circuit de taille réduite.\n",
        "\n",
        "Le modèle d'Ising modifié correspond au modèle d'Ising habituel :\n",
        "\n",
        "$\\hat{H}_{\\text{I}} = J \\sum_{n=0}^{N-2} \\hat{Z}_n \\hat{Z}_{n+1} + h \\sum_{n=0}^{N-1} \\hat{Z}_n$\n",
        "\n",
        "auquel est appliqué un coup de pied transversal :\n",
        "\n",
        "$\\hat{H}_{K} = b \\sum_{n=0}^{N-1} \\hat{X}_n$\n",
        "\n",
        "L'objectif est de simuler la dynamique d'un état sous l'hamiltonien d'Ising à coup transversal, dont l'évolution temporelle peut être mise en œuvre par une $\\hat{U}_{\\text{KI}} = e^{-i \\hat{H}_K} e^{-i \\hat{H}_I} $ unitaire de Floquet. L'état initial à faire évoluer est celui dans lequel le premier qubit est dans l'état $|+\\rangle$, tandis que les autres sont appariés et placés dans l'état de Bell $(|00\\rangle + |11\\rangle)/\\sqrt{2}$.\n",
        "\n",
        "La quantité que nous voulons observer est la fonction de corrélation. [Le document de référence](https://www.nature.com/articles/s41567-025-03144-9) explique comment cette quantité peut être réécrite sous la forme d'un opérateur de Pauli d' $\\hat{X}$ e sur le qubit d' $n^{th}$.\n",
        "Après un certain nombre d'étapes physiques $t$, nous calculons la valeur de l'opérateur de Pauli $\\hat{X}_{n=t}$.\n",
        "En fonction des paramètres du système, la valeur de cette observable est égale à une valeur qui peut être calculée avec exactitude ou seulement simulée à l'aide de méthodes approximatives. Plus précisément, pour $|J|=|b|=\\pi/4$, il est égal à $[\\cos(2h)]^t$, qui est la valeur que nous utiliserons pour comparer les résultats de ce tutoriel. De plus, à un instant donné $t$, $\\langle\\hat{X}_{n\\neq t}\\rangle$ est égal à zéro. Pour plus de détails sur l'obtention de ces valeurs et pour une comparaison avec les résultats approximatifs de la simulation classique en dehors de ces paramètres, voir [L. E. Fischer et al., Nat. Phys. (2026)](https://www.nature.com/articles/s41567-025-03144-9).\n",
        "\n",
        "La TEM fonctionne en caractérisant d'abord le bruit pour chaque couche unique de portes à deux qubits dans le circuit, ainsi qu'en caractérisant l'erreur de lecture. Ensuite, le circuit est exécuté sur la machine quantique. Enfin, l'atténuation des erreurs du réseau tensoriel est effectuée sur les ressources classiques dans IBM Cloud® et la valeur atténuée est renvoyée. Dans cet exemple, le circuit comporte deux couches distinctes à caractériser.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4b30f191-9759-49de-ba8f-7cc616b61ec6",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## Configuration\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9cf6d15e-324b-474a-886c-c3dca5a24141",
      "metadata": {},
      "source": [
        "Comme condition préalable, assurez-vous que les dépendances nécessaires sont installées.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "1eeec332-29ca-4882-8129-d1c93ed82b2b",
      "metadata": {},
      "outputs": [],
      "source": [
        "%pip install numpy matplotlib qiskit qiskit-ibm-catalog qiskit-ibm-runtime pylatexenc qiskit_qasm3_import"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "ad0002b7-dbff-4699-af52-ba0df72ed200",
      "metadata": {},
      "outputs": [],
      "source": [
        "import os\n",
        "from matplotlib import pyplot as plt\n",
        "import numpy as np\n",
        "\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.qasm3 import load\n",
        "\n",
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b95b9e75-37fe-4f86-a923-0a833c7960f8",
      "metadata": {},
      "source": [
        "<span id=\"error-mitigation-with-tem\" />\n",
        "\n",
        "## Atténuation des erreurs avec TEM\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "651a3f04-c8ba-4a39-8415-52d7e313ba2a",
      "metadata": {},
      "source": [
        "Nous fournissons ici un circuit qui met en œuvre le modèle d'Ising avec coup de pied décrit ci-dessus. Le circuit est préparé comme suit. Tout d'abord, il y a une phase de préparation de l'état, dans laquelle le premier qubit est dans l'état $|+\\rangle$, tandis que les autres sont dans des paires de Bell $(|00\\rangle + |11\\rangle)/\\sqrt{2}$. Vient ensuite la structure en briques qui met en œuvre l'évolution unitaire $\\hat{U}_{\\text{KI}}$. Le nombre d'étapes physiques correspond aux couches du circuit $t/2$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "11e42656-76ba-452c-af22-8f4cd22ff174",
      "metadata": {},
      "source": [
        "Le code suivant télécharge les deux fichiers QASM nécessaires à ce tutoriel.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "39bf7188-3771-4994-a6c6-e9cfcae3484f",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Download required QASM files\n",
        "import urllib\n",
        "\n",
        "urllib.request.urlretrieve(\n",
        "    \"https://ibm.box.com/shared/static/swy5jtq309b0xpzluzlmsmj908yphes8.qasm\",\n",
        "    \"ki_30q.qasm\",\n",
        ")\n",
        "urllib.request.urlretrieve(\n",
        "    \"https://ibm.box.com/shared/static/et3gkodonw6gsp2trs43lzaozrdtiu7s.qasm\",\n",
        "    \"ki_12q.qasm\",\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1f6f9970-63fb-40f4-9586-261cba23cb88",
      "metadata": {},
      "source": [
        "Nous pouvons visualiser une version réduite du circuit, avec 12 qubits et six étapes temporelles :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "381a4e25-bc9c-47d0-b9f1-172eb5516484",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/simulate-kicked-ising-tem/extracted-outputs/381a4e25-bc9c-47d0-b9f1-172eb5516484-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Parameters of the kicked Ising model\n",
        "h = 0.0\n",
        "num_qubits = 12\n",
        "t_steps = 6\n",
        "\n",
        "# Load the circuit for the kicked Ising model\n",
        "small_circuit = load(\"ki_12q.qasm\")\n",
        "\n",
        "# Draw the circuit\n",
        "small_circuit.draw(\"mpl\", scale=0.25, fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a674e407-504d-4812-82bf-98e91ec9a4b4",
      "metadata": {},
      "source": [
        "Ensuite, construisez l'observable, $\\hat{X}_{n=t}$. Il est construit comme une simple chaîne de Pauli dont l'ordre correspond à celui utilisé par Qiskit :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "a9a87f6c-176d-4c85-85e5-6751aea0c90b",
      "metadata": {},
      "outputs": [],
      "source": [
        "def xt_observable(n_qubits, t_steps):\n",
        "    pauli_str = \"\".join([\"I\" * t_steps, \"X\", \"I\" * (n_qubits - t_steps - 1)])\n",
        "    pauli_str = pauli_str[::-1]  # Reverse the string to match qiskit order\n",
        "    return SparsePauliOp(data=pauli_str, coeffs=1.0)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ba5f7042-4abd-4ae7-a091-591678377e8f",
      "metadata": {},
      "source": [
        "Dans notre petit exemple à 12 qubits, l'observable se présente comme suit :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "b2608df1-b4e4-4143-bea5-a65ab8045fd4",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "SparsePauliOp(['IIIIIXIIIIII'],\n",
            "              coeffs=[1.+0.j])\n"
          ]
        }
      ],
      "source": [
        "# Build the observable for the kicked Ising model\n",
        "small_observable = xt_observable(n_qubits=12, t_steps=6)\n",
        "print(small_observable)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e588fafe-8db8-4445-8893-a78190b27b64",
      "metadata": {},
      "source": [
        "Qiskit Functions utiliser les PUB comme moyen de collecter les contributions. Dans notre cas, considérons un circuit unique et observable comme notre PUB :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "fc48eb54-148b-4b0d-8424-a135cb92039e",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Collect the input PUBs, in this case composed of a\n",
        "# single circuit and observable\n",
        "pubs = [(small_circuit, [small_observable])]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9a4bcd8d-ae21-40ab-b0e2-510236ba92de",
      "metadata": {},
      "source": [
        "Ensuite, nous avons accès à la fonction TEM. Nous configurons d'abord l'authentification requise pour IBM Cloud et sélectionnons un backend parmi les appareils disponibles. Le jeton, les backends disponibles et les noms de ressources cloud (CRN) correspondants peuvent être obtenus en vous connectant à votre compte sur le [tableau de bord](/) IBM Quantum Platform.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "6c9f80a8-4a65-4daa-94bb-a98edd6a1989",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Set IBM Quantum credentials and backend configuration\n",
        "personal_token = os.environ.get(\n",
        "    \"QISKIT_IBM_TOKEN\", \"<API-KEY>\"\n",
        ")  # Replace with your personal token or set the environment variable\n",
        "channel = \"ibm_quantum_platform\"\n",
        "crn = \"your_crn\"  # Replace with the Cloud Resource Name (CRN)\n",
        "\n",
        "# Select the QPU backend\n",
        "backend_name = \"ibm_qpu_name\"  # Replace with your desired backend's name"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "10df1803-5245-42b2-8eea-c0773cd655b6",
      "metadata": {},
      "source": [
        "Chargez la fonction TEM à partir de l' [Qiskit Functions Catalog](/functions) :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "2473b284-108f-45fe-a8d8-3aed584137f6",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Load the TEM function from the Qiskit Functions Catalog\n",
        "catalog = QiskitFunctionsCatalog(\n",
        "    channel=channel,\n",
        "    token=personal_token,\n",
        "    instance=crn,\n",
        ")\n",
        "tem = catalog.load(\"algorithmiq/tem\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3c732819-4dca-421c-bc2b-45ff5a5912db",
      "metadata": {},
      "source": [
        "Nous pouvons désormais mener une expérience sur le circuit d'Ising activé avec l'atténuation des erreurs fournie par TEM. Avec les paramètres par défaut, TEM peut être exécuté de manière simple avec un temps d'exécution QPU prévu d'environ 2.5 minutes, en fonction du QPU :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "b826e025-f36b-4fb5-90bd-e1ef36f5c1b2",
      "metadata": {},
      "outputs": [],
      "source": [
        "tem_job = tem.run(pubs=pubs, backend_name=backend_name)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4b692a80-5a10-4131-9d7f-785fedbe4221",
      "metadata": {},
      "source": [
        "Avec les options par défaut, la fonction TEM exécute trois tâches sur l'ordinateur quantique : apprentissage du bruit, atténuation de la lecture et échantillonnage des circuits. Le nombre de clichés utilisés par chacun d'entre eux peut être modifié dans les options transmises à la fonction. Par défaut, ces paramètres sont définis pour obtenir une précision de l'ordre de l' 0.05 e dans les valeurs d'espérance atténuées.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "25b6f313-a928-493e-837f-45e6e7836aef",
      "metadata": {},
      "source": [
        "Vous pouvez vérifier l'état d'avancement de votre tâche sur le [tableau de bord](/) IBM Quantum Platform ou à l'aide de :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "05e202ff-5b86-4a93-a693-86fbb1cf3e02",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QUEUED\n"
          ]
        }
      ],
      "source": [
        "print(tem_job.status())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8e427c75-72fb-4a97-b723-97d695a692d3",
      "metadata": {},
      "source": [
        "Lorsque le statut est `DONE`, nous pouvons vérifier les résultats bruts et atténués. Les `tem_evs` définis ci-dessous sont les valeurs attendues des observables demandés, dans ce cas un seul observable, $\\langle \\hat X_{n=t}\\rangle$, et `tem_std` sont les écarts types correspondants.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "3ca34069-1363-4e37-9718-91639d817a82",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "TEM Result: 1.031 ± 0.046\n"
          ]
        }
      ],
      "source": [
        "# Get the results of the TEM job\n",
        "tem_results = tem_job.result()[\n",
        "    0\n",
        "]  # Get the first and only result from the job\n",
        "tem_evs = tem_results.data.evs[0]\n",
        "tem_std = tem_results.data.stds[0]\n",
        "\n",
        "print(f\"TEM Result: {tem_evs:.3f} ± {tem_std:.3f}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f90f503e-ab80-4550-a7cf-dfeea12babb0",
      "metadata": {},
      "source": [
        "Nous pouvons également vérifier combien de temps d'exécution quantique a été utilisé pour chaque appel sur [IBM Quantum Platform](), ou en inspectant les métadonnées de résultat du code Python.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "b05818d6-b680-483e-9084-f3fd2de067ab",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "TEM Runtime: 155.0 seconds\n"
          ]
        }
      ],
      "source": [
        "# Get the TEM job runtime\n",
        "tem_runtime = tem_job.result().metadata[\"resource_usage\"][\n",
        "    \"RUNNING: EXECUTING_QPU\"\n",
        "][\"QPU_TIME\"]\n",
        "\n",
        "print(f\"TEM Runtime: {tem_runtime} seconds\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6be333a8-41c9-4ba9-b07d-a0ac50149add",
      "metadata": {},
      "source": [
        "<span id=\"customize-tem-parameters-and-advanced-options\" />\n",
        "\n",
        "## Personnalisez les paramètres TEM et les options avancées\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "abee6fc2-90d6-4608-ad21-c606c936dd94",
      "metadata": {},
      "source": [
        "La fonction TEM offre plusieurs options avancées pour personnaliser votre flux de travail d'atténuation des erreurs. Ces options vous permettent de contrôler la précision, le nombre de tirs, les stratégies d'apprentissage du bruit et d'autres paramètres afin de mieux répondre aux exigences de votre expérience et aux ressources quantiques disponibles.\n",
        "\n",
        "Les options avancées courantes sont les suivantes :\n",
        "\n",
        "* **`precision`**: Spécifiez la précision cible pour les valeurs d'espérance atténuées.\n",
        "* **`default_shots`**: Au lieu de `precision`, vous pouvez spécifier le nombre de prises utilisées par la tâche de mesure.\n",
        "* **`tem_max_bond_dimension`**: Dimension maximale de liaison utilisée dans le réseau tensoriel.\n",
        "* **`tem_compression_cutoff`**: Valeur seuil à utiliser pour le réseau de tenseurs.\n",
        "* **Options d'apprentissage du bruit** : configurez la manière dont le bruit est caractérisé, par exemple le nombre de répétitions ou les circuits d'étalonnage spécifiques.\n",
        "* **`private`**: Assurez-vous que les circuits et les résultats des expériences restent privés et désactivez les téléchargements multiples des résultats des tâches.\n",
        "\n",
        "Reportez-vous à la [documentation TEM](/docs/guides/algorithmiq-tem) ou à l' [Qiskit Functions Catalog](/functions) pour obtenir la liste complète des options prises en charge et leurs descriptions. Vous pouvez ajuster ces paramètres pour trouver le bon équilibre entre la durée d'exécution, l'utilisation des ressources et la précision des résultats.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "24db681c-b306-41e0-8507-626ef279b076",
      "metadata": {},
      "source": [
        "Vous pouvez passer ces options sous forme de dictionnaire à `options` l'argument lors de l'exécution de la fonction TEM :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a2e9a032-91cb-4a18-9a00-00a149e60459",
      "metadata": {},
      "outputs": [],
      "source": [
        "options = {\n",
        "    \"default_shots\": 10_000,\n",
        "    \"tem_max_bond_dimension\": 512,\n",
        "    \"tem_compression_cutoff\": 1e-16,\n",
        "    # This option helps optimizing the measurement\n",
        "    # stage since the observable is strongly biased\n",
        "    # toward the X operator for all the qubits.\n",
        "    \"compute_shadows_bias_from_observable\": True,\n",
        "    # set to True to keep experiment results private,\n",
        "    # recommended for confidential circuits\n",
        "    \"private\": False,\n",
        "}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "db700868-4dae-48c8-be1a-668ef2e63177",
      "metadata": {},
      "source": [
        "Il est également possible de passer des options personnalisées pour l'algorithme d'apprentissage du bruit. Elles reprennent les définitions utilisées dans le : `qiskit-ibm-runtime`[`NoiseLearnerOptions`](/docs/api/qiskit-ibm-runtime/options-noise-learner-options)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 29,
      "id": "30591014-3bc6-4548-ba0d-dc5cc22e9dcc",
      "metadata": {},
      "outputs": [],
      "source": [
        "nl_options = {\n",
        "    \"num_randomizations\": 32,\n",
        "    \"max_layers_to_learn\": 2,\n",
        "    \"shots_per_randomization\": 128,\n",
        "    \"layer_pair_depths\": [0, 1, 2, 4, 16, 32],\n",
        "}\n",
        "\n",
        "# add noise learning options to the overall options\n",
        "options |= nl_options"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "216ad12c-8c70-4073-8515-b07fd57f74d4",
      "metadata": {},
      "source": [
        "Répétez l'expérience avec ces options personnalisées adaptées à notre circuit. La durée d'exécution prévue est d'environ quatre minutes QPU.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 30,
      "id": "ebce8e14-433f-4858-96c6-9d90ff0353af",
      "metadata": {},
      "outputs": [],
      "source": [
        "tem_job_custom = tem.run(\n",
        "    pubs=pubs, backend_name=backend_name, options=options\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bd8d2c12-c9da-4ac3-97c0-d53be1455091",
      "metadata": {},
      "source": [
        "Si la tâche n'est pas définie comme privée, nous pouvons récupérer le résultat ultérieurement. Pour ce faire, enregistrez l'ID de tâche imprimé ici et utilisez `tem_job_custom = catalog.get_job_by_id(\"your-job-id\")`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 31,
      "id": "0f99101b-9e72-45c8-8b00-9f3a257b8b3b",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Job ID: 1ba10094-a541-457a-9287-dbd49306d12d\n"
          ]
        }
      ],
      "source": [
        "job_id = tem_job_custom.job_id\n",
        "print(f\"Job ID: {job_id}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 33,
      "id": "0c751dac-e856-4371-aaed-f67aca31061f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "TEM Result: 0.956 ± 0.018\n"
          ]
        }
      ],
      "source": [
        "results_custom = tem_job_custom.result()\n",
        "tem_evs = results_custom[0].data.evs[0]\n",
        "tem_std = results_custom[0].data.stds[0]\n",
        "\n",
        "print(f\"TEM Result: {tem_evs:.3f} ± {tem_std:.3f}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "edfef6f9-6bac-42bb-8bd2-95f977f7b31b",
      "metadata": {},
      "source": [
        "Nous pouvons désormais examiner les résultats et les métadonnées pour mieux comprendre l'expérience :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 34,
      "id": "dd189b2d-860b-4b9a-88c2-7e5c62b1f160",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Unmitigated Result: 0.894 ± 0.015\n",
            "Exact Result: 1.0\n"
          ]
        }
      ],
      "source": [
        "metadata_custom = results_custom[0].metadata\n",
        "\n",
        "unmitigated_evs = metadata_custom[\"evs_non_mitigated\"][0]\n",
        "unmitigated_stds = metadata_custom[\"stds_non_mitigated\"][0]\n",
        "print(f\"Unmitigated Result: {unmitigated_evs:.3f} ± {unmitigated_stds:.3f}\")\n",
        "\n",
        "# Exact result for the kicked Ising model from the reference paper\n",
        "exact_evs = np.cos(2 * h) ** t_steps\n",
        "print(\"Exact Result:\", exact_evs)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 35,
      "id": "c3a2168d-98df-491e-a1f8-05de5684ab96",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/simulate-kicked-ising-tem/extracted-outputs/c3a2168d-98df-491e-a1f8-05de5684ab96-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Plot comparing the different expectation values\n",
        "plt.bar(\n",
        "    [\"Unmitigated\", \"TEM\"],\n",
        "    [unmitigated_evs, tem_evs],\n",
        "    yerr=[unmitigated_stds, tem_std],\n",
        "    color=[\"grey\", \"c\"],\n",
        ")\n",
        "plt.hlines(y=exact_evs, xmin=-0.5, xmax=1.5, colors=\"r\", linestyles=\"dashed\")\n",
        "plt.ylabel(\"Expectation Value\")\n",
        "plt.ylim(0, 1.1)\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d643bdb4-22e0-4f55-b3a8-d5ef39f6e696",
      "metadata": {},
      "source": [
        "Enfin, nous pouvons vérifier l'impact des options personnalisées sur le QPU et le temps d'exécution classique :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "id": "09cf2226-c48c-483b-aa49-80186229ae95",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QPU Runtime: 342.0 seconds\n",
            "Classical Runtime: 107.632604 seconds\n"
          ]
        }
      ],
      "source": [
        "# Get the metadata of the TEM job\n",
        "job_metadata = results_custom.metadata\n",
        "\n",
        "# Get the runtime of the TEM job\n",
        "qpu_runtime = job_metadata[\"resource_usage\"][\"RUNNING: EXECUTING_QPU\"][\n",
        "    \"QPU_TIME\"\n",
        "]\n",
        "classical_runtime = (\n",
        "    job_metadata[\"resource_usage\"][\"RUNNING: OPTIMIZING_FOR_HARDWARE\"][\n",
        "        \"CPU_TIME\"\n",
        "    ]\n",
        "    + job_metadata[\"resource_usage\"][\"RUNNING: POST_PROCESSING\"][\"CPU_TIME\"]\n",
        ")\n",
        "\n",
        "print(f\"QPU Runtime: {qpu_runtime} seconds\")\n",
        "print(f\"Classical Runtime: {classical_runtime} seconds\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7cea6cf1-5530-4bf6-83da-ad2e9ff96806",
      "metadata": {},
      "source": [
        "<span id=\"scale-tem-to-large-circuits\" />\n",
        "\n",
        "## Adapter le TEM aux grands circuits\n",
        "\n",
        "Les grands circuits peuvent, en principe, être exécutés avec la fonction TEM. Cependant, il est important d'être conscient des limites des ressources classiques, car TEM est exécuté sur des runners d' IBM Cloud s dont les temps d'exécution peuvent être très longs. Pour les circuits extrêmement volumineux, contactez l'équipe d'assistance TEM à l'adresse [qiskit\\ \\_ibm@algorithmiq.fi](mailto:qiskit_ibm@algorithmiq.fi).\n",
        "\n",
        "Nous présentons ici un exemple avec un circuit plus grand, de taille industrielle, à 30 qubits, en optimisant les paramètres TEM pour la vitesse plutôt que pour la précision.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f7ea1d3c-d745-48cc-8922-b070b2b5fd44",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Kicked Ising model parameters\n",
        "n_qubits = 30\n",
        "t_steps = 15\n",
        "h = 0.0\n",
        "\n",
        "# Load the circuit for the kicked Ising model\n",
        "circuit = load(\"ki_30q.qasm\")\n",
        "\n",
        "\n",
        "# Build the observable for the kicked Ising model\n",
        "observable = xt_observable(n_qubits=n_qubits, t_steps=t_steps)\n",
        "\n",
        "# Collect the input PUBs, in this case composed of a\n",
        "# single circuit and observable\n",
        "pubs = [(circuit, [observable])]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "854c3208-8c0f-4f7d-b260-0abba2bc71a0",
      "metadata": {},
      "source": [
        "Définissons quelques options axées sur les performances :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 49,
      "id": "64882a71-3027-4e25-b714-9e9d6b13cd49",
      "metadata": {},
      "outputs": [],
      "source": [
        "options = {\n",
        "    \"num_randomizations\": 32,\n",
        "    \"max_layers_to_learn\": 2,\n",
        "    \"shots_per_randomization\": 128,\n",
        "    \"layer_pair_depths\": [0, 1, 2, 4, 16, 32, 64],\n",
        "    \"default_shots\": 5_000,\n",
        "    \"tem_max_bond_dimension\": 128,\n",
        "    \"tem_compression_cutoff\": 1e-10,\n",
        "    \"compute_shadows_bias_from_observable\": True,\n",
        "    \"private\": False,\n",
        "}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4ba36257-1974-4274-b04c-6daf3afe9d72",
      "metadata": {},
      "source": [
        "Enfin, lancez l'expérience, obtenez le résultat et visualisez-le. Cela prendra environ 3.5 minutes QPU.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 50,
      "id": "6faf7f80-dec9-49d2-80e7-d4e6fdea5100",
      "metadata": {},
      "outputs": [],
      "source": [
        "tem_job_large = tem.run(pubs=pubs, backend_name=backend_name, options=options)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 51,
      "id": "333b2335-b480-4bf9-854c-5155eedee900",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Job ID: 9f3f190f-f4b0-4dcb-bb83-5f71f37d0d77\n"
          ]
        }
      ],
      "source": [
        "job_id = tem_job_large.job_id\n",
        "print(f\"Job ID: {job_id}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 53,
      "id": "a04dd421-a212-473c-a8a9-4c8edcfc3667",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "TEM Result: 0.794 ± 0.026\n",
            "QPU Runtime: 203.0 seconds\n",
            "Classical Runtime: 251.71805499999996 seconds\n"
          ]
        }
      ],
      "source": [
        "results_large = tem_job_large.result()\n",
        "tem_evs = results_large[0].data.evs[0]\n",
        "tem_std = results_large[0].data.stds[0]\n",
        "\n",
        "print(f\"TEM Result: {tem_evs:.3f} ± {tem_std:.3f}\")\n",
        "\n",
        "\n",
        "# Get the metadata of the TEM job\n",
        "job_metadata = tem_job_large.result().metadata\n",
        "\n",
        "# Get the runtime of the TEM job\n",
        "qpu_runtime = job_metadata[\"resource_usage\"][\"RUNNING: EXECUTING_QPU\"][\n",
        "    \"QPU_TIME\"\n",
        "]\n",
        "classical_runtime = (\n",
        "    job_metadata[\"resource_usage\"][\"RUNNING: OPTIMIZING_FOR_HARDWARE\"][\n",
        "        \"CPU_TIME\"\n",
        "    ]\n",
        "    + job_metadata[\"resource_usage\"][\"RUNNING: POST_PROCESSING\"][\"CPU_TIME\"]\n",
        ")\n",
        "\n",
        "print(f\"QPU Runtime: {qpu_runtime} seconds\")\n",
        "print(f\"Classical Runtime: {classical_runtime} seconds\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 54,
      "id": "24894c44-e399-4b9d-a3ff-38a28ff32ece",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/simulate-kicked-ising-tem/extracted-outputs/24894c44-e399-4b9d-a3ff-38a28ff32ece-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Plot comparing the different expectation values\n",
        "metadata_large = results_large[0].metadata\n",
        "unmitigated_evs = metadata_large[\"evs_non_mitigated\"][0]\n",
        "unmitigated_stds = metadata_large[\"stds_non_mitigated\"][0]\n",
        "\n",
        "exact_evs = np.cos(2 * h) ** t_steps\n",
        "\n",
        "plt.bar(\n",
        "    [\"Unmitigated\", \"TEM\"],\n",
        "    [unmitigated_evs, tem_evs],\n",
        "    yerr=[unmitigated_stds, tem_std],\n",
        "    color=[\"grey\", \"c\"],\n",
        ")\n",
        "plt.hlines(y=exact_evs, xmin=-0.5, xmax=1.5, colors=\"r\", linestyles=\"dashed\")\n",
        "plt.ylabel(\"Expectation Value\")\n",
        "plt.ylim(0, 1.1)\n",
        "plt.show()"
      ]
    },
    {
      "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"
    },
    "hours": 1.5,
    "qpuSeconds": 600
  },
  "nbformat": 4,
  "nbformat_minor": 4
}