{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "c52e7bba-1230-4974-8e86-2dbe8f6f219b",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Déboguer des tâches avec NEAT\"\n",
        "description: \"Utilisez la classe `Neat` du module d'outils de débogage `qiskit-ibm-runtime` pour déboguer et analyser les tâches.\"\n",
        "---\n",
        "\n",
        "<span id=\"debug-jobs-with-neat\" />\n",
        "\n",
        "# Déboguer des tâches avec NEAT\n",
        "\n",
        "{/* cspell:ignore ZIIIII, IZIIII,IIZIII, IIIZII, IIIIZI, IIIIIZ, rdiff */}\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d0599f3e",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "{/*\n",
        "  DO NOT EDIT THIS CELL!!!\n",
        "  This cell's content is generated automatically by a script. Anything you add\n",
        "  here will be removed next time the notebook is run. To add new content, create\n",
        "  a new cell before or after this one.\n",
        "  */}\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Versions de package\">\n",
        "    Le code de cette page a été développé en tenant compte des exigences suivantes.\n",
        "    Nous recommandons d'utiliser ces versions ou des versions plus récentes.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.1\n",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    qiskit-aer~=0.17\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "80d0a1da-8d98-49e1-9cb0-0006093bf44c",
      "metadata": {},
      "source": [
        "Vous pouvez utiliser la `Neat` classe pour analyser l'impact du bruit sur une charge de travail Estimator. Pour vérifier la syntaxe, utilisez [le mode de test local](/docs/guides/local-testing-mode).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b08f0589",
      "metadata": {},
      "source": [
        "<span id=\"neat-class-usage\" />\n",
        "\n",
        "## `Neat` utilisation de la classe\n",
        "\n",
        "Avant de soumettre une charge de travail gourmande en ressources pour exécution sur du matériel, vous pouvez utiliser la classe [NEAT (Noisy Estimator Analyzer Tool)](/docs/api/qiskit-ibm-runtime/debug-tools-neat#neat) de l' IBM Quantum, dans le module Compute, pour vérifier que votre charge de travail d'estimation est correctement configurée, qu'elle est susceptible de fournir des résultats précis, qu'elle utilise les options les plus adaptées au problème spécifié, et bien plus encore.\n",
        "\n",
        "`Neat` Cliffordiise les circuits d'entrée pour une simulation efficace, tout en conservant sa structure et sa profondeur. Les circuits de Clifford souffrent de niveaux de bruit similaires et constituent un bon moyen d'étudier le circuit original qui nous intéresse.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0dc5bf2a-e536-4141-a77c-0ee407cbd9b2",
      "metadata": {},
      "source": [
        "Commencez par importer les paquets nécessaires et [authentifiez-vous auprès du service de calcul d' IBM Quantum](/docs/guides/cloud-setup).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d653e186-7ec3-4f1b-b0e9-b322055dd6c8",
      "metadata": {},
      "source": [
        "<span id=\"prepare-the-environment\" />\n",
        "\n",
        "### Préparation de l'environnement\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "2f28c824-3158-43e6-ab3c-fd96c31859f0",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "import random\n",
        "\n",
        "from qiskit.circuit import QuantumCircuit\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator\n",
        "from qiskit_ibm_runtime.debug_tools import Neat\n",
        "\n",
        "from qiskit_aer.noise import NoiseModel, depolarizing_error"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "a45a6d9e-de39-4586-8395-a7f580f0e0dc",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Choose the least busy backend\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "# Generate a preset pass manager\n",
        "# This will be used to convert the abstract circuit to an equivalent\n",
        "# Instruction Set Architecture (ISA) circuit.\n",
        "\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=0)\n",
        "\n",
        "# Set the random seed\n",
        "random.seed(10)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "67572a70-da01-40fe-b299-b5599561164a",
      "metadata": {},
      "source": [
        "<span id=\"initialize-a-target-circuit\" />\n",
        "\n",
        "### Initialiser un circuit cible\n",
        "\n",
        "Considérons un circuit à six qubits qui possède les propriétés suivantes :\n",
        "\n",
        "* Alternance de rotations aléatoires `RZ` et de couches de portes `CNOT`.\n",
        "* A une structure en miroir, c'est-à-dire qu'il applique une `U` unitaire suivie de son inverse.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "df19af55-897d-4b1f-baf8-fac2641ae87d",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/debug-qiskit-runtime-jobs/extracted-outputs/df19af55-897d-4b1f-baf8-fac2641ae87d-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "def generate_circuit(n_qubits, n_layers):\n",
        "    r\"\"\"\n",
        "    A function to generate a pseudo-random a circuit with ``n_qubits`` qubits\n",
        "    and ``2*n_layers`` entangling layers of the type used in this notebook.\n",
        "    \"\"\"\n",
        "    # An array of random angles\n",
        "    angles = [\n",
        "        [random.random() for q in range(n_qubits)] for s in range(n_layers)\n",
        "    ]\n",
        "\n",
        "    qc = QuantumCircuit(n_qubits)\n",
        "    qubits = list(range(n_qubits))\n",
        "\n",
        "    # do random circuit\n",
        "    for layer in range(n_layers):\n",
        "        # rotations\n",
        "        for q_idx, qubit in enumerate(qubits):\n",
        "            qc.rz(angles[layer][q_idx], qubit)\n",
        "\n",
        "        # cx gates\n",
        "        control_qubits = (\n",
        "            qubits[::2] if layer % 2 == 0 else qubits[1 : n_qubits - 1 : 2]\n",
        "        )\n",
        "        for qubit in control_qubits:\n",
        "            qc.cx(qubit, qubit + 1)\n",
        "\n",
        "    # undo random circuit\n",
        "    for layer in range(n_layers)[::-1]:\n",
        "        # cx gates\n",
        "        control_qubits = (\n",
        "            qubits[::2] if layer % 2 == 0 else qubits[1 : n_qubits - 1 : 2]\n",
        "        )\n",
        "        for qubit in control_qubits:\n",
        "            qc.cx(qubit, qubit + 1)\n",
        "\n",
        "        # rotations\n",
        "        for q_idx, qubit in enumerate(qubits):\n",
        "            qc.rz(-angles[layer][q_idx], qubit)\n",
        "\n",
        "    return qc\n",
        "\n",
        "\n",
        "# Generate a random circuit\n",
        "qc = generate_circuit(6, 3)\n",
        "# Convert the abstract circuit to an equivalent ISA circuit.\n",
        "isa_qc = pm.run(qc)\n",
        "\n",
        "qc.draw(\"mpl\", idle_wires=0)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0167329b-c6a6-4b2c-98fc-bf9aba9b7ee6",
      "metadata": {},
      "source": [
        "Choisissez les opérateurs de Pauli `Z` comme observables et utilisez-les pour initialiser les blocs primitifs unifiés (PUB).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "830b1dcc-2669-46cc-bff8-01a96a05c6ab",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Observables: ['ZIIIII', 'IZIIII', 'IIZIII', 'IIIZII', 'IIIIZI', 'IIIIIZ']\n"
          ]
        }
      ],
      "source": [
        "# Initialize the observables\n",
        "obs = [\"ZIIIII\", \"IZIIII\", \"IIZIII\", \"IIIZII\", \"IIIIZI\", \"IIIIIZ\"]\n",
        "print(f\"Observables: {obs}\")\n",
        "\n",
        "# Map the observables to the backend's layout\n",
        "isa_obs = [SparsePauliOp(o).apply_layout(isa_qc.layout) for o in obs]\n",
        "\n",
        "# Initialize the PUBs, which consist of six-qubit circuits\n",
        "# with `n_layers` 1, ..., 6\n",
        "all_n_layers = [1, 2, 3, 4, 5, 6]\n",
        "\n",
        "pubs = [(pm.run(generate_circuit(6, n)), isa_obs) for n in all_n_layers]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2a49fc84-0c82-4cbb-a557-6e676e57c9fa",
      "metadata": {},
      "source": [
        "<span id=\"cliffordize-the-circuits\" />\n",
        "\n",
        "### Cliffordiser les circuits\n",
        "\n",
        "Les circuits PUB définis précédemment ne sont pas de type Clifford, ce qui les rend difficiles à simuler classiquement. Cependant, vous pouvez utiliser la méthode `Neat` [`to_clifford`](/docs/api/qiskit-ibm-runtime/debug-tools-neat#to_clifford) pour les convertir en circuits de Clifford afin d'obtenir une simulation plus efficace.  La méthode [`to_clifford`](/docs/api/qiskit-ibm-runtime/debug-tools-neat#to_clifford) est une enveloppe autour de la passe [`ConvertISAToClifford`](/docs/api/qiskit-ibm-runtime/transpiler-passes-convert-isa-to-clifford) qui peut également être utilisée indépendamment. En particulier, il remplace les portes à un qubit non Clifford du circuit original par des portes à un qubit Clifford, mais il ne modifie pas les portes à deux qubits, le nombre de qubits ou la profondeur du circuit.\n",
        "\n",
        "Voir [Simulation efficace de circuits stabilisateurs avec les primitives Qiskit Aer](/docs/guides/simulate-stabilizer-circuits) pour plus d'informations sur la simulation de circuits de Clifford.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7a86d99e-4431-4d62-8227-c49d17856369",
      "metadata": {},
      "source": [
        "Tout d'abord, initialiser `Neat`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "4b5bbd4c-bd7f-4679-9348-d41da74d26eb",
      "metadata": {},
      "outputs": [],
      "source": [
        "# You could specify a custom `NoiseModel` here. If `None`, `Neat`\n",
        "# pulls the noise model from the given backend\n",
        "noise_model = None\n",
        "\n",
        "# Initialize `Neat`\n",
        "analyzer = Neat(backend, noise_model)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b740dcdf-660e-41e2-b5e6-e8cc288af38b",
      "metadata": {},
      "source": [
        "Ensuite, il faut clifforiser les PUB.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "3ad78f41-a2f8-4381-826a-ae728e081ad6",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/debug-qiskit-runtime-jobs/extracted-outputs/3ad78f41-a2f8-4381-826a-ae728e081ad6-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "clifford_pubs = analyzer.to_clifford(pubs)\n",
        "\n",
        "clifford_pubs[0].circuit.draw(\"mpl\", idle_wires=0)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "83c3ff81-9f18-43eb-ba6e-57c5ef3d118f",
      "metadata": {},
      "source": [
        "<span id=\"application-1-analyze-the-impact-of-noise-on-the-circuit-outputs\" />\n",
        "\n",
        "## Application 1 : Analyser l'impact du bruit sur les sorties du circuit\n",
        "\n",
        "Cet exemple montre comment utiliser `Neat` pour étudier l'impact de différents modèles de bruit sur les PUB en fonction de la profondeur du circuit en effectuant des simulations dans des conditions idéales ([`ideal_sim`](/docs/api/qiskit-ibm-runtime/debug-tools-neat#ideal_sim)) et bruitées ([`noisy_sim`](/docs/api/qiskit-ibm-runtime/debug-tools-neat#noisy_sim)). Cela peut être utile pour définir des attentes quant à la qualité des résultats expérimentaux avant d'exécuter une tâche sur un QPU. Pour en savoir plus sur les modèles de bruit, consultez [Simulation exacte et bruyante avec les primitives Aer de Qiskit](/docs/guides/simulate-with-qiskit-aer#exact-and-noisy-simulation-with-qiskit-aer-primitives).\n",
        "\n",
        "Les résultats simulés permettent d'effectuer des opérations mathématiques et peuvent donc être comparés entre eux (ou avec des résultats expérimentaux) pour calculer des chiffres de mérite.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Une QPU peut être affectée par différents types de bruit. Le modèle de bruit Qiskit Aer utilisé ici ne simule que certains d'entre eux et est donc susceptible d'être moins grave que le bruit d'une QPU réelle.\n",
        "\n",
        "  Pour plus de détails sur les erreurs incluses lors de l'initialisation d'un modèle de bruit à partir d'une QPU, voir la référence de l'API Aer [`NoiseModel`](https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.noise.NoiseModel.html#qiskit_aer.noise.NoiseModel.from_backend) API reference.\n",
        "</Admonition>\n",
        "\n",
        "Commencez par effectuer des simulations classiques idéales et bruyantes.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "23859a99-2455-460e-98ea-17b36ea59c36",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Ideal results:\n",
            " NeatResult([NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.]))])\n",
            "\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Noisy results:\n",
            " NeatResult([NeatPubResult(vals=array([0.9921875 , 0.99023438, 0.99023438, 0.99023438, 0.97265625,\n",
            "       0.97070312])), NeatPubResult(vals=array([0.98046875, 0.98632812, 0.98828125, 0.9921875 , 0.96289062,\n",
            "       0.9765625 ])), NeatPubResult(vals=array([0.96289062, 0.96875   , 0.953125  , 0.953125  , 0.95507812,\n",
            "       0.9609375 ])), NeatPubResult(vals=array([0.94726562, 0.95507812, 0.93945312, 0.94921875, 0.94921875,\n",
            "       0.95898438])), NeatPubResult(vals=array([0.91992188, 0.92382812, 0.91015625, 0.921875  , 0.92382812,\n",
            "       0.9375    ])), NeatPubResult(vals=array([0.90039062, 0.9140625 , 0.90234375, 0.92578125, 0.91601562,\n",
            "       0.94335938]))])\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# Perform a noiseless simulation\n",
        "ideal_results = analyzer.ideal_sim(clifford_pubs)\n",
        "print(f\"Ideal results:\\n {ideal_results}\\n\")\n",
        "\n",
        "# Perform a noisy simulation with the backend's noise model\n",
        "noisy_results = analyzer.noisy_sim(clifford_pubs)\n",
        "print(f\"Noisy results:\\n {noisy_results}\\n\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a000a77a-0285-4b72-a69f-8f144f2c2a80",
      "metadata": {},
      "source": [
        "Ensuite, appliquez des opérations mathématiques pour calculer la différence absolue. Dans la suite du guide, la différence absolue est utilisée comme chiffre de mérite pour comparer des résultats idéaux à des résultats bruyants ou expérimentaux, mais des chiffres de mérite similaires peuvent être établis.\n",
        "\n",
        "La différence absolue montre que l'impact du bruit augmente avec la taille des circuits.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "cd61e437-bd2f-4349-a667-7edab51c4a6e",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Mean absolute difference between ideal and noisy results for circuits with 1 layers:\n",
            "  1.56%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 2 layers:\n",
            "  1.89%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 3 layers:\n",
            "  4.1%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 4 layers:\n",
            "  5.01%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 5 layers:\n",
            "  7.72%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 6 layers:\n",
            "  8.3%\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# Figure of merit: Absolute difference\n",
        "def rdiff(res1, re2):\n",
        "    r\"\"\"The absolute difference between `res1` and re2`.\n",
        "\n",
        "    --> The closer to `0`, the better.\n",
        "    \"\"\"\n",
        "    d = abs(res1 - re2)\n",
        "    return np.round(d.vals * 100, 2)\n",
        "\n",
        "\n",
        "for idx, (ideal_res, noisy_res) in enumerate(\n",
        "    zip(ideal_results, noisy_results)\n",
        "):\n",
        "    vals = rdiff(ideal_res, noisy_res)\n",
        "\n",
        "    # Print the mean absolute difference for the observables\n",
        "    mean_vals = np.round(np.mean(vals), 2)\n",
        "    print(\n",
        "        f\"Mean absolute difference between ideal and noisy results \"\n",
        "        f\"for circuits with {all_n_layers[idx]} layers:\\n  {mean_vals}%\\n\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7abcd001-9eac-4015-97a3-d6250ea4b667",
      "metadata": {},
      "source": [
        "Vous pouvez suivre ces lignes directrices grossières et simplifiées pour améliorer les circuits de ce type :\n",
        "\n",
        "* Si la différence moyenne absolue est supérieure à 90 %, l'atténuation ne sera probablement d'aucune utilité.\n",
        "* Si la différence moyenne absolue est inférieure à 90 %, l' [amplification probabiliste des erreurs (APE)](/docs/guides/error-mitigation-and-suppression-techniques#probabilistic-error-amplification-pea) pourra probablement améliorer les résultats.\n",
        "* Si la différence moyenne absolue est inférieure à 80 %, les [ZNE avec repli des portes](/docs/guides/error-mitigation-and-suppression-techniques#zero-noise-extrapolation-zne) pourront probablement améliorer les résultats.\n",
        "\n",
        "Comme toutes les différences absolues ci-dessus sont inférieures à 90 %, l'application de la PEA au circuit original devrait améliorer la qualité de ses résultats.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c64c936b-5b8f-4fd2-861d-8b1ded2a0ad4",
      "metadata": {},
      "source": [
        "Vous pouvez spécifier différents modèles de bruit dans l'analyseur. L'exemple suivant effectue le même test mais ajoute un modèle de bruit personnalisé.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "0835c562-55c9-4dbe-879e-7271f8bed280",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Mean absolute difference between ideal and noisy results for circuits with 1 layers:\n",
            "  0.0%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 2 layers:\n",
            "  0.0%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 3 layers:\n",
            "  0.0%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 4 layers:\n",
            "  0.0%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 5 layers:\n",
            "  0.0%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 6 layers:\n",
            "  0.0%\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# Set up a noise model with strength 0.02 on every two-qubit gate\n",
        "noise_model = NoiseModel()\n",
        "for qubits in backend.coupling_map:\n",
        "    noise_model.add_quantum_error(\n",
        "        depolarizing_error(0.02, 2), [\"ecr\", \"cx\"], qubits\n",
        "    )\n",
        "\n",
        "# Update the analyzer's noise model\n",
        "analyzer.noise_model = noise_model\n",
        "\n",
        "# Perform a noiseless simulation\n",
        "ideal_results = analyzer.ideal_sim(clifford_pubs)\n",
        "\n",
        "# Perform a noisy simulation with the backend's noise model\n",
        "noisy_results = analyzer.noisy_sim(clifford_pubs)\n",
        "\n",
        "# Compare the results\n",
        "for idx, (ideal_res, noisy_res) in enumerate(\n",
        "    zip(ideal_results, noisy_results)\n",
        "):\n",
        "    values = rdiff(ideal_res, noisy_res)\n",
        "\n",
        "    # Print the mean absolute difference for the observables\n",
        "    mean_values = np.round(np.mean(values), 2)\n",
        "    print(\n",
        "        f\"Mean absolute difference between ideal and noisy results \"\n",
        "        f\"for circuits with {all_n_layers[idx]} layers:\\n  {mean_values}%\\n\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f2408ca9-3e3c-4a2f-a99a-ce413d5d470f",
      "metadata": {},
      "source": [
        "Comme indiqué, étant donné un modèle de bruit, vous pouvez essayer de quantifier l'impact du bruit sur les PUB (version Cliffordiisée des PUB) qui vous intéressent avant de les exécuter sur une QPU.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ddd6da5f-4e84-4bf4-aaeb-0403f21275db",
      "metadata": {},
      "source": [
        "<span id=\"application-2-benchmark-different-strategies\" />\n",
        "\n",
        "## Application 2 : Comparer différentes stratégies\n",
        "\n",
        "Cet exemple utilise `Neat` pour aider à identifier les meilleures options pour vos PUBs. Pour ce faire, considérons l'exécution d'un problème d'estimation avec PEA, qui ne peut pas être simulé avec `qiskit_aer`. Vous pouvez utiliser `Neat` pour déterminer les facteurs d'amplification du bruit les plus efficaces, puis utiliser ces facteurs lorsque vous réalisez l'expérience originale sur une QPU.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "358bb82a-4bc9-46c2-98a0-e745ffc6788f",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Generate a circuit with six qubits and six layers\n",
        "isa_qc = pm.run(generate_circuit(6, 3))\n",
        "\n",
        "# Use the same observables as previously\n",
        "pubs = [(isa_qc, isa_obs)]\n",
        "clifford_pubs = analyzer.to_clifford(pubs)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "5774cb3f-c999-4242-a83a-7dcc0c57510b",
      "metadata": {},
      "outputs": [],
      "source": [
        "noise_factors = [\n",
        "    [1, 1.1],\n",
        "    [1, 1.1, 1.2],\n",
        "    [1, 1.5, 2],\n",
        "    [1, 1.5, 2, 2.5, 3],\n",
        "    [1, 4],\n",
        "]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "0b9900e6-84fe-4776-9bb5-08c6c729be29",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Run the PUBs on a QPU\n",
        "estimator = Estimator(backend)\n",
        "estimator.options.default_shots = 100000\n",
        "estimator.options.twirling.enable_gates = True\n",
        "estimator.options.twirling.enable_measure = True\n",
        "estimator.options.twirling.shots_per_randomization = 100\n",
        "estimator.options.resilience.measure_mitigation = True\n",
        "estimator.options.resilience.zne_mitigation = True\n",
        "estimator.options.resilience.zne.amplifier = \"pea\"\n",
        "\n",
        "jobs = []\n",
        "for factors in noise_factors:\n",
        "    estimator.options.resilience.zne.noise_factors = factors\n",
        "    jobs.append(estimator.run(clifford_pubs))\n",
        "\n",
        "results = [job.result() for job in jobs]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "16c18377-059a-4751-9ab1-afee0ed5b089",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Perform a noiseless simulation\n",
        "ideal_results = analyzer.ideal_sim(clifford_pubs)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "7db531a1-c417-4d5b-bdc3-7a4ad3385fd4",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Mean absolute difference for factors [1, 1.1]:\n",
            "  12.04%\n",
            "\n",
            "Mean absolute difference for factors [1, 1.1, 1.2]:\n",
            "  3.79%\n",
            "\n",
            "Mean absolute difference for factors [1, 1.5, 2]:\n",
            "  4.73%\n",
            "\n",
            "Mean absolute difference for factors [1, 1.5, 2, 2.5, 3]:\n",
            "  3.65%\n",
            "\n",
            "Mean absolute difference for factors [1, 4]:\n",
            "  2.72%\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# Look at the mean absolute difference to quickly determine\n",
        "# the best choice for your options\n",
        "for factors, res in zip(noise_factors, results):\n",
        "    d = rdiff(ideal_results[0], res[0])\n",
        "    print(\n",
        "        f\"Mean absolute difference for factors \"\n",
        "        f\"{factors}:\\n  {np.round(np.mean(d), 2)}%\\n\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0c37ef7b-df56-4f5f-9e11-10f209f105f9",
      "metadata": {},
      "source": [
        "Le résultat présentant la plus petite différence suggère les options à choisir.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2530a3e9-21a6-4841-9449-fe181c54aca4",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Etapes suivantes\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recommandations\">\n",
        "  * Découvrez un aperçu des [outils de débogage de Qiskit](/docs/guides/debugging-tools).\n",
        "  * Découvrez [la simulation exacte et bruyante avec les primitives Aer de Qiskit](/docs/guides/simulate-with-qiskit-aer).\n",
        "  * Découvrez [les options de calcul disponibles sur IBM Quantum](/docs/guides/runtime-options-overview).\n",
        "  * Découvrez [les techniques d'atténuation et de suppression des erreurs](/docs/guides/error-mitigation-and-suppression-techniques).\n",
        "  * Visitez la rubrique [Transpile avec les gestionnaires de pass](transpile-with-pass-managers).\n",
        "  * Découvrez [comment transpilier des circuits](/docs/guides/circuit-transpilation-settings#compare-transpiler-settings) dans le cadre des workflows de Qiskit Patterns.\n",
        "  * Consultez [la documentation relative à l'API des outils de débogage](/docs/api/qiskit-ibm-runtime/debug-tools).\n",
        "</Admonition>\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
}