{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "fd07a3db-1aa2-4884-98db-6f68765c3edc",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Construire des modèles de bruit\"\n",
        "description: \"Découvrez comment élaborer des modèles de bruit pour la gestion des erreurs.\"\n",
        "---\n",
        "\n",
        "<span id=\"build-noise-models\" />\n",
        "\n",
        "# Construire des modèles de bruit\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "35e9a88b-6872-42b0-ac4f-36bf8898f2fa",
      "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": "19c35f2c-437a-48b7-8c9f-9ac3526811a7",
      "metadata": {},
      "source": [
        "Cette page montre comment utiliser le module Qiskit Aer [`noise`](https://qiskit.org/ecosystem/aer/apidocs/aer_noise.html) pour construire des modèles de bruit pour simuler des circuits quantiques en présence d'erreurs. Ceci est utile pour émuler des processeurs quantiques bruyants et pour étudier les effets du bruit sur l'exécution des algorithmes quantiques.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "85a94e7b-6b43-4a4a-a3b6-a412e1d66c7d",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.403378Z",
          "start_time": "2019-08-19T17:00:41.139269Z"
        }
      },
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit.quantum_info import Kraus, SuperOp\n",
        "from qiskit.visualization import plot_histogram\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_aer import AerSimulator\n",
        "\n",
        "# Import from Qiskit Aer noise module\n",
        "from qiskit_aer.noise import (\n",
        "    NoiseModel,\n",
        "    QuantumError,\n",
        "    ReadoutError,\n",
        "    depolarizing_error,\n",
        "    pauli_error,\n",
        "    thermal_relaxation_error,\n",
        ")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "da49be49-d174-413c-b05d-20236817aac2",
      "metadata": {
        "slideshow": {
          "slide_type": "slide"
        }
      },
      "source": [
        "<span id=\"qiskit-aer-noise-module\" />\n",
        "\n",
        "## Module `noise` Qiskit Aer\n",
        "\n",
        "Le module Qiskit Aer `noise` contient des classes Python pour construire des modèles de bruit personnalisés pour la simulation. Il existe trois catégories principales :\n",
        "\n",
        "1. La classe `NoiseModel` qui stocke un modèle de bruit utilisé pour la simulation bruyante.\n",
        "\n",
        "2. La classe `QuantumError` qui décrit les erreurs de porte du CPTP. Ils peuvent être appliqués :\n",
        "   * Instructions après la *porte* ou la *réinitialisation*\n",
        "   * Instructions avant la *mesure*.\n",
        "\n",
        "3. La classe `ReadoutError` qui décrit les erreurs de lecture classiques.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ea2762d5-7260-4ce9-9e44-2950331ba3e7",
      "metadata": {},
      "source": [
        "<span id=\"initialize-a-noise-model-from-a-backend\" />\n",
        "\n",
        "## Initialiser un modèle de bruit à partir d'un backend\n",
        "\n",
        "Vous pouvez initialiser un modèle de bruit à l'aide de paramètres définis à partir des dernières données d'étalonnage d'un backend physique.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Le backend `FakeSherbrooke` fictif de `qiskit_ibm_runtime` est utilisé dans ces exemples, mais vous pouvez l'essayer sur n'importe quel backend réel ou fictif compatible avec Qiskit.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "b47efd06-6a64-455a-be12-07054e800a34",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.fake_provider import FakeSherbrooke\n",
        "\n",
        "backend = FakeSherbrooke()\n",
        "noise_model = NoiseModel.from_backend(backend)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "54f7cb42-dd95-4089-afbb-db9e83d41b50",
      "metadata": {},
      "source": [
        "Cela permet d'obtenir un modèle de bruit qui correspond approximativement aux erreurs rencontrées lors de l'utilisation de ce backend. Si vous souhaitez avoir un contrôle plus détaillé sur les paramètres du modèle de bruit, vous devrez créer votre propre modèle de bruit, comme décrit dans le reste de cette page.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "a4940a81-d6ab-4f15-8505-05282c67d823",
      "metadata": {},
      "source": [
        "<span id=\"quantum-errors\" />\n",
        "\n",
        "## Erreurs quantiques\n",
        "\n",
        "Plutôt que de traiter `QuantumError` l'objet directement, il existe de nombreuses fonctions d'aide permettant de générer automatiquement un type spécifique d'erreur quantique paramétrée. Ils sont contenus dans le `noise` module et comprennent des fonctions pour de nombreux types d'erreurs courantes utilisées dans la recherche en informatique quantique. Les noms des fonctions et le type d'erreur qu'elles renvoient sont les suivants :\n",
        "\n",
        "| Fonction d'erreur standard      | Détails                                                                                                                                                                                                                                               |\n",
        "| ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n",
        "| `kraus_error`                   | un canal d'erreur CPTP général à n qubits donné sous la forme d'une liste de matrices de Kraus $[K_0, ...]$.                                                                                                                                          |\n",
        "| `mixed_unitary_error`           | une erreur unitaire mixte à n qubits donnée sous la forme d'une liste de matrices unitaires et de probabilités $[(U_0, p_0),...]$.                                                                                                                    |\n",
        "| `coherent_unitary_error`        | une erreur unitaire cohérente à n qubits donnée sous la forme d'une matrice unitaire unique $U$.                                                                                                                                                      |\n",
        "| `pauli_error`                   | un canal d'erreur de Pauli à n qubits (mixte unitaire) donné sous la forme d'une liste de Pauli et de probabilités $[(P_0, p_0),...]$                                                                                                                 |\n",
        "| `depolarizing_error`            | un canal d'erreur dépolarisant à n-qubits paramétré par une probabilité de dépolarisation $p$.                                                                                                                                                        |\n",
        "| `reset_error`                   | erreur de réinitialisation d'un seul qubit paramétrée par les probabilités $p_0, p_1$ de réinitialisation à l'état $\\vert1\\rangle$ $\\vert0\\rangle$.                                                                                                   |\n",
        "| `thermal_relaxation_error`      | un canal de relaxation thermique à qubit unique paramétré par les constantes de temps de relaxation $T_1$, $T_2$, le temps de porte $t$, et la population thermique de l'état excité $p_1$.                                                           |\n",
        "| `phase_amplitude_damping_error` | Un canal d'erreur d'amortissement de phase et d'amplitude généralisé à qubit unique donné par un paramètre d'amortissement d'amplitude $\\lambda$, un paramètre d'amortissement de phase $\\gamma$, et une population thermique de l'état excité $p_1$. |\n",
        "| `amplitude_damping_error`       | Un canal d'erreur à amortissement d'amplitude généralisé à un qubit donné par un paramètre d'amortissement d'amplitude $\\lambda$, et une population thermique d'état excité $p_1$.                                                                    |\n",
        "| `phase_damping_error`           | Canal d'erreur d'amortissement de phase à un seul qubit donné par un paramètre d'amortissement $\\gamma$ de phase.                                                                                                                                     |\n",
        "\n",
        "<span id=\"combine-quantum-errors\" />\n",
        "\n",
        "### Combiner les erreurs quantiques\n",
        "\n",
        "`QuantumError` peuvent être combinées en utilisant la composition, le produit tensoriel et l'expansion tensorielle (produit tensoriel d'ordre inversé) pour produire de nouveaux `QuantumErrors` comme :\n",
        "\n",
        "* Composition : $\\cal{E}(\\rho)=\\cal{E_2}(\\cal{E_1}(\\rho))$ sous forme de `error = error1.compose(error2)`\n",
        "* Produit tensoriel : $\\cal{E}(\\rho) =(\\cal{E_1}\\otimes\\cal{E_2})(\\rho)$ comme `error = error1.tensor(error2)`\n",
        "* Développer le produit : $\\cal{E}(\\rho) =(\\cal{E_2}\\otimes\\cal{E_1})(\\rho)$ comme `error = error1.expand(error2)`\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "cd42ec1c-a971-4dd8-913c-2a4fd4f4a845",
      "metadata": {},
      "source": [
        "<span id=\"example\" />\n",
        "\n",
        "### Exemple\n",
        "\n",
        "Pour construire une erreur de basculement de bit de 5 % sur un seul qubit :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "437a8576-084c-499f-af7e-12b0a2fbfcd0",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.420358Z",
          "start_time": "2019-08-19T17:00:43.416062Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QuantumError on 1 qubits. Noise circuits:\n",
            "  P(0) = 0.05, Circuit = \n",
            "   ┌───┐\n",
            "q: ┤ X ├\n",
            "   └───┘\n",
            "  P(1) = 0.95, Circuit = \n",
            "   ┌───┐\n",
            "q: ┤ I ├\n",
            "   └───┘\n",
            "QuantumError on 1 qubits. Noise circuits:\n",
            "  P(0) = 0.05, Circuit = \n",
            "   ┌───┐\n",
            "q: ┤ Z ├\n",
            "   └───┘\n",
            "  P(1) = 0.95, Circuit = \n",
            "   ┌───┐\n",
            "q: ┤ I ├\n",
            "   └───┘\n"
          ]
        }
      ],
      "source": [
        "# Construct a 1-qubit bit-flip and phase-flip errors\n",
        "p_error = 0.05\n",
        "bit_flip = pauli_error([(\"X\", p_error), (\"I\", 1 - p_error)])\n",
        "phase_flip = pauli_error([(\"Z\", p_error), (\"I\", 1 - p_error)])\n",
        "print(bit_flip)\n",
        "print(phase_flip)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "d71ef2d9-e386-4649-9e1c-a7bfe7342687",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.435843Z",
          "start_time": "2019-08-19T17:00:43.432211Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QuantumError on 1 qubits. Noise circuits:\n",
            "  P(0) = 0.0025000000000000005, Circuit = \n",
            "   ┌───┐┌───┐\n",
            "q: ┤ X ├┤ Z ├\n",
            "   └───┘└───┘\n",
            "  P(1) = 0.0475, Circuit = \n",
            "   ┌───┐┌───┐\n",
            "q: ┤ X ├┤ I ├\n",
            "   └───┘└───┘\n",
            "  P(2) = 0.0475, Circuit = \n",
            "   ┌───┐┌───┐\n",
            "q: ┤ I ├┤ Z ├\n",
            "   └───┘└───┘\n",
            "  P(3) = 0.9025, Circuit = \n",
            "   ┌───┐┌───┐\n",
            "q: ┤ I ├┤ I ├\n",
            "   └───┘└───┘\n"
          ]
        }
      ],
      "source": [
        "# Compose two bit-flip and phase-flip errors\n",
        "bitphase_flip = bit_flip.compose(phase_flip)\n",
        "print(bitphase_flip)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "ffa9fd9c-3d98-4285-8daf-ee22ca2b0d55",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.460191Z",
          "start_time": "2019-08-19T17:00:43.456782Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QuantumError on 2 qubits. Noise circuits:\n",
            "  P(0) = 0.0025000000000000005, Circuit = \n",
            "     ┌───┐\n",
            "q_0: ┤ X ├\n",
            "     ├───┤\n",
            "q_1: ┤ Z ├\n",
            "     └───┘\n",
            "  P(1) = 0.0475, Circuit = \n",
            "     ┌───┐\n",
            "q_0: ┤ I ├\n",
            "     ├───┤\n",
            "q_1: ┤ Z ├\n",
            "     └───┘\n",
            "  P(2) = 0.0475, Circuit = \n",
            "     ┌───┐\n",
            "q_0: ┤ X ├\n",
            "     ├───┤\n",
            "q_1: ┤ I ├\n",
            "     └───┘\n",
            "  P(3) = 0.9025, Circuit = \n",
            "     ┌───┐\n",
            "q_0: ┤ I ├\n",
            "     ├───┤\n",
            "q_1: ┤ I ├\n",
            "     └───┘\n"
          ]
        }
      ],
      "source": [
        "# Tensor product two bit-flip and phase-flip errors with\n",
        "# bit-flip on qubit-0, phase-flip on qubit-1\n",
        "error2 = phase_flip.tensor(bit_flip)\n",
        "print(error2)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "80e275c7-b856-4301-9266-0eb7a783e0f8",
      "metadata": {},
      "source": [
        "<span id=\"convert-to-and-from-quantumchannel-operators\" />\n",
        "\n",
        "### Convertir vers et depuis les opérateurs d' QuantumChannel\n",
        "\n",
        "Nous pouvons également faire des allers-retours entre les objets `QuantumError` dans Qiskit Aer et les objets `QuantumChannel` dans Qiskit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "2006e158-bea6-4e18-a06c-31b567401b6c",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.482424Z",
          "start_time": "2019-08-19T17:00:43.473779Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Kraus([[[-9.74679434e-01+0.j,  0.00000000e+00+0.j],\n",
            "        [ 0.00000000e+00+0.j, -9.74679434e-01+0.j]],\n",
            "\n",
            "       [[ 0.00000000e+00+0.j,  2.23606798e-01+0.j],\n",
            "        [ 2.23606798e-01+0.j, -4.96506831e-17+0.j]]],\n",
            "      input_dims=(2,), output_dims=(2,))\n"
          ]
        }
      ],
      "source": [
        "# Convert to Kraus operator\n",
        "bit_flip_kraus = Kraus(bit_flip)\n",
        "print(bit_flip_kraus)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "425a9b6f-e078-4a48-ab1c-a5621a8b773a",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.509521Z",
          "start_time": "2019-08-19T17:00:43.503976Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "SuperOp([[1. +0.j, 0. +0.j, 0. +0.j, 0. +0.j],\n",
            "         [0. +0.j, 0.9+0.j, 0. +0.j, 0. +0.j],\n",
            "         [0. +0.j, 0. +0.j, 0.9+0.j, 0. +0.j],\n",
            "         [0. +0.j, 0. +0.j, 0. +0.j, 1. +0.j]],\n",
            "        input_dims=(2,), output_dims=(2,))\n"
          ]
        }
      ],
      "source": [
        "# Convert to Superoperator\n",
        "phase_flip_sop = SuperOp(phase_flip)\n",
        "print(phase_flip_sop)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "97624c98-f1c0-4a9b-be5b-2c664d368e9f",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:43.794037Z",
          "start_time": "2019-08-19T17:00:43.778223Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QuantumError on 1 qubits. Noise circuits:\n",
            "  P(0) = 1.0, Circuit = \n",
            "   ┌───────┐\n",
            "q: ┤ kraus ├\n",
            "   └───────┘\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "True"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Convert back to a quantum error\n",
        "print(QuantumError(bit_flip_kraus))\n",
        "\n",
        "# Check conversion is equivalent to original error\n",
        "QuantumError(bit_flip_kraus) == bit_flip"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "7f663dfe-e238-418c-bff4-c751468a6678",
      "metadata": {},
      "source": [
        "<span id=\"readout-error\" />\n",
        "\n",
        "### Erreur de lecture\n",
        "\n",
        "Les erreurs de lecture classiques sont spécifiées par une liste de vecteurs de probabilité $P(A|B)$ d'affectation :\n",
        "\n",
        "* $A$ est la valeur du bit classique *enregistré*\n",
        "* $B$ est la *vraie* valeur du bit renvoyée par la mesure\n",
        "\n",
        "Par exemple, pour un qubit : $ P(A|B) = [P(A|0), P(A|1)]$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "f70f39f8-dec5-46cb-a194-4768cffbd6db",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:44.659598Z",
          "start_time": "2019-08-19T17:00:44.654818Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "ReadoutError([[0.95 0.05]\n",
              " [0.1  0.9 ]])"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Measurement misassignment probabilities\n",
        "p0given1 = 0.1\n",
        "p1given0 = 0.05\n",
        "\n",
        "ReadoutError([[1 - p1given0, p1given0], [p0given1, 1 - p0given1]])"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "e77fcdcd-346c-4f78-83eb-0c32359ba62c",
      "metadata": {},
      "source": [
        "Les erreurs de lecture peuvent également être combinées en utilisant `compose`, `tensor` et `expand`, comme pour les erreurs quantiques.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "b2258427-2283-435c-b964-60423c3b0f39",
      "metadata": {},
      "source": [
        "<span id=\"add-errors-to-a-noise-model\" />\n",
        "\n",
        "## Ajouter des erreurs à un modèle de bruit\n",
        "\n",
        "Lorsqu'on ajoute une erreur quantique à un modèle de bruit, il faut spécifier le type d' *instruction* sur lequel elle agit et les qubits auxquels elle s'applique. Il existe deux cas d'erreurs quantiques :\n",
        "\n",
        "1. Erreur quantique globale\n",
        "2. Erreur quantique d'un qubit spécifique\n",
        "\n",
        "<span id=\"1-all-qubit-quantum-error\" />\n",
        "\n",
        "### 1. Erreur quantique sur tous les qubits\n",
        "\n",
        "La même erreur s'applique à toutes les occurrences d'une instruction, quels que soient les qubits sur lesquels elle agit.\n",
        "\n",
        "Il est ajouté à l'adresse `noise_model.add_all_qubit_quantum_error(error, instructions)`:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "0a5ae501-87e5-4930-96c1-b0af2d6993ce",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:45.882254Z",
          "start_time": "2019-08-19T17:00:45.877630Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "NoiseModel:\n",
            "  Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']\n",
            "  Instructions with noise: ['u2', 'u1', 'u3']\n",
            "  All-qubits errors: ['u1', 'u2', 'u3']\n"
          ]
        }
      ],
      "source": [
        "# Create an empty noise model\n",
        "noise_model = NoiseModel()\n",
        "\n",
        "# Add depolarizing error to all single qubit u1, u2, u3 gates\n",
        "error = depolarizing_error(0.05, 1)\n",
        "noise_model.add_all_qubit_quantum_error(error, [\"u1\", \"u2\", \"u3\"])\n",
        "\n",
        "# Print noise model info\n",
        "print(noise_model)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "f2f360be-5d7b-435d-980a-e20450a0267f",
      "metadata": {},
      "source": [
        "<span id=\"2-specific-qubit-quantum-error\" />\n",
        "\n",
        "### 2. Erreur quantique spécifique au qubit\n",
        "\n",
        "L'erreur s'applique à toute occurrence d'une instruction agissant sur une liste de qubits spécifiée. Notez que l'ordre des qubits est important : par exemple, une erreur appliquée aux qubits \\[0, 1] pour une porte à deux qubits est différente d'une erreur appliquée aux qubits \\[1, 0.]\n",
        "\n",
        "Il est ajouté à l'adresse `noise_model.add_quantum_error(error, instructions, qubits)`:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "05d7e61f-75dc-488b-bfab-c00ad87fe1ea",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:46.615959Z",
          "start_time": "2019-08-19T17:00:46.612055Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "NoiseModel:\n",
            "  Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']\n",
            "  Instructions with noise: ['u2', 'u1', 'u3']\n",
            "  Qubits with noise: [0]\n",
            "  Specific qubit errors: [('u1', (0,)), ('u2', (0,)), ('u3', (0,))]\n"
          ]
        }
      ],
      "source": [
        "# Create an empty noise model\n",
        "noise_model = NoiseModel()\n",
        "\n",
        "# Add depolarizing error to all single qubit u1, u2, u3 gates on qubit 0 only\n",
        "error = depolarizing_error(0.05, 1)\n",
        "noise_model.add_quantum_error(error, [\"u1\", \"u2\", \"u3\"], [0])\n",
        "\n",
        "# Print noise model info\n",
        "print(noise_model)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "c2dc1bb3-66a9-4d63-8341-0c4c45ed89d6",
      "metadata": {},
      "source": [
        "<span id=\"note-on-non-local-qubit-quantum-error\" />\n",
        "\n",
        "### Remarque sur les erreurs quantiques non locales des qubits\n",
        "\n",
        "`NoiseModel` ne prend pas en charge l'ajout d'erreurs quantiques sur des qubits non locaux. Ils devraient être traités en dehors de `NoiseModel`. Cela signifie que vous devriez [écrire votre propre passe de transcompilation](/docs/guides/custom-transpiler-pass) (`TransformationPass`) et l'exécuter juste avant de lancer le simulateur si vous souhaitez intégrer vos erreurs quantiques dans votre circuit selon vos propres paramètres.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "2617effb-ae2e-44a3-8a7b-28b68b756ac6",
      "metadata": {},
      "source": [
        "<span id=\"execute-a-noisy-simulation-with-a-noise-model\" />\n",
        "\n",
        "### Exécuter une simulation bruyante avec un modèle de bruit\n",
        "\n",
        "La commande `AerSimulator(noise_model=noise_model)` renvoie un simulateur configuré selon le modèle de bruit donné. En plus de définir le modèle de bruit du simulateur, il remplace également les portes de la base du simulateur, en fonction des portes du modèle de bruit.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "7df257fd-424b-486e-a607-7d4c392b4c98",
      "metadata": {
        "slideshow": {
          "slide_type": "subslide"
        }
      },
      "source": [
        "<span id=\"noise-model-examples\" />\n",
        "\n",
        "## Exemples de modèles de bruit\n",
        "\n",
        "Nous allons maintenant donner quelques exemples de modèles de bruit. Pour nos démonstrations, nous utilisons un circuit de test simple générant un état GHZ à n qubits :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "43df6b1f-b07a-4bf2-bba6-c7ec35eec620",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:48.817405Z",
          "start_time": "2019-08-19T17:00:48.806966Z"
        },
        "slideshow": {
          "slide_type": "fragment"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "        ┌───┐                ░ ┌─┐         \n",
            "   q_0: ┤ H ├──■─────────────░─┤M├─────────\n",
            "        └───┘┌─┴─┐           ░ └╥┘┌─┐      \n",
            "   q_1: ─────┤ X ├──■────────░──╫─┤M├──────\n",
            "             └───┘┌─┴─┐      ░  ║ └╥┘┌─┐   \n",
            "   q_2: ──────────┤ X ├──■───░──╫──╫─┤M├───\n",
            "                  └───┘┌─┴─┐ ░  ║  ║ └╥┘┌─┐\n",
            "   q_3: ───────────────┤ X ├─░──╫──╫──╫─┤M├\n",
            "                       └───┘ ░  ║  ║  ║ └╥┘\n",
            "meas: 4/════════════════════════╩══╩══╩══╩═\n",
            "                                0  1  2  3 \n"
          ]
        }
      ],
      "source": [
        "# System Specification\n",
        "n_qubits = 4\n",
        "circ = QuantumCircuit(n_qubits)\n",
        "\n",
        "# Test Circuit\n",
        "circ.h(0)\n",
        "for qubit in range(n_qubits - 1):\n",
        "    circ.cx(qubit, qubit + 1)\n",
        "circ.measure_all()\n",
        "print(circ)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "eea319ec-8764-4d77-8863-c5a2e9ae370a",
      "metadata": {},
      "source": [
        "<span id=\"ideal-simulation\" />\n",
        "\n",
        "### Simulation idéale\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "bc713d11-755e-41e4-94f0-1ed76e3c2469",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:50.560988Z",
          "start_time": "2019-08-19T17:00:50.415545Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/build-noise-models/extracted-outputs/bc713d11-755e-41e4-94f0-1ed76e3c2469-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Ideal simulator and execution\n",
        "sim_ideal = AerSimulator()\n",
        "result_ideal = sim_ideal.run(circ).result()\n",
        "plot_histogram(result_ideal.get_counts(0))"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "ac7111a6-04dc-4068-9044-54d93e745116",
      "metadata": {
        "slideshow": {
          "slide_type": "subslide"
        }
      },
      "source": [
        "<span id=\"noise-example-1-basic-bit-flip-error-noise-model\" />\n",
        "\n",
        "## Exemple de bruit 1 : Modèle de bruit de base avec erreur de basculement de bit\n",
        "\n",
        "Prenons un exemple simple de modèle de bruit jouet, courant dans la recherche sur la théorie de l'information quantique :\n",
        "\n",
        "* Lors de l'application d'une porte à qubit unique, l'état du qubit est inversé avec la probabilité `p_gate1`.\n",
        "* Lors de l'application d'une porte à deux qubits, appliquer des erreurs à un qubit à chaque qubit.\n",
        "* Lors de la réinitialisation d'un qubit, le qubit est réinitialisé à 1 au lieu de 0 avec la probabilité `p_reset`.\n",
        "* Lors de la mesure d'un qubit, inverser l'état du qubit avec la probabilité `p_meas`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "fee3c383-0499-4d1f-be9f-32b41a31f561",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:51.543615Z",
          "start_time": "2019-08-19T17:00:51.536564Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "NoiseModel:\n",
            "  Basis gates: ['cx', 'id', 'rz', 'sx', 'u1', 'u2', 'u3']\n",
            "  Instructions with noise: ['u3', 'u1', 'u2', 'reset', 'cx', 'measure']\n",
            "  All-qubits errors: ['reset', 'measure', 'u1', 'u2', 'u3', 'cx']\n"
          ]
        }
      ],
      "source": [
        "# Example error probabilities\n",
        "p_reset = 0.03\n",
        "p_meas = 0.1\n",
        "p_gate1 = 0.05\n",
        "\n",
        "# QuantumError objects\n",
        "error_reset = pauli_error([(\"X\", p_reset), (\"I\", 1 - p_reset)])\n",
        "error_meas = pauli_error([(\"X\", p_meas), (\"I\", 1 - p_meas)])\n",
        "error_gate1 = pauli_error([(\"X\", p_gate1), (\"I\", 1 - p_gate1)])\n",
        "error_gate2 = error_gate1.tensor(error_gate1)\n",
        "\n",
        "# Add errors to noise model\n",
        "noise_bit_flip = NoiseModel()\n",
        "noise_bit_flip.add_all_qubit_quantum_error(error_reset, \"reset\")\n",
        "noise_bit_flip.add_all_qubit_quantum_error(error_meas, \"measure\")\n",
        "noise_bit_flip.add_all_qubit_quantum_error(error_gate1, [\"u1\", \"u2\", \"u3\"])\n",
        "noise_bit_flip.add_all_qubit_quantum_error(error_gate2, [\"cx\"])\n",
        "\n",
        "print(noise_bit_flip)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "dbf3f5ee-0f66-4a37-b512-038a21ce2ed2",
      "metadata": {},
      "source": [
        "<span id=\"execute-the-noisy-simulation\" />\n",
        "\n",
        "### Exécuter la simulation bruyante\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "abeb9f09-d762-406d-983e-0357ade59636",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:52.951874Z",
          "start_time": "2019-08-19T17:00:52.687440Z"
        },
        "slideshow": {
          "slide_type": "-"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/build-noise-models/extracted-outputs/abeb9f09-d762-406d-983e-0357ade59636-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Create noisy simulator backend\n",
        "sim_noise = AerSimulator(noise_model=noise_bit_flip)\n",
        "\n",
        "# Transpile circuit for noisy basis gates\n",
        "passmanager = generate_preset_pass_manager(\n",
        "    optimization_level=3, backend=sim_noise\n",
        ")\n",
        "circ_tnoise = passmanager.run(circ)\n",
        "\n",
        "# Run and get counts\n",
        "result_bit_flip = sim_noise.run(circ_tnoise).result()\n",
        "counts_bit_flip = result_bit_flip.get_counts(0)\n",
        "\n",
        "# Plot noisy output\n",
        "plot_histogram(counts_bit_flip)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "ced838fa-105d-4bdf-b240-51b78ff18e29",
      "metadata": {},
      "source": [
        "<span id=\"example-2-t1/t2-thermal-relaxation\" />\n",
        "\n",
        "## Exemple 2 : Relaxation thermique d' T1/T2\n",
        "\n",
        "Considérons maintenant un modèle d'erreur plus réaliste basé sur la relaxation thermique avec l'environnement du qubit :\n",
        "\n",
        "* Chaque qubit est paramétré par une constante de temps de relaxation thermique $T_1$ et une constante de temps de déphasage $T_2$.\n",
        "* Notons que nous devons avoir $T_2 \\le 2 T_1$.\n",
        "* Les taux d'erreur sur les instructions sont déterminés par les temps de porte et les valeurs des qubits $T_1$, $T_2$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "b2ab3829-98fa-4b5d-b622-25c155abfdf0",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:54.577456Z",
          "start_time": "2019-08-19T17:00:54.491018Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "NoiseModel:\n",
            "  Basis gates: ['cx', 'id', 'rz', 'sx', 'u2', 'u3']\n",
            "  Instructions with noise: ['u3', 'u2', 'reset', 'cx', 'measure']\n",
            "  Qubits with noise: [0, 1, 2, 3]\n",
            "  Specific qubit errors: [('reset', (0,)), ('reset', (1,)), ('reset', (2,)), ('reset', (3,)), ('measure', (0,)), ('measure', (1,)), ('measure', (2,)), ('measure', (3,)), ('u2', (0,)), ('u2', (1,)), ('u2', (2,)), ('u2', (3,)), ('u3', (0,)), ('u3', (1,)), ('u3', (2,)), ('u3', (3,)), ('cx', (0, 0)), ('cx', (0, 1)), ('cx', (0, 2)), ('cx', (0, 3)), ('cx', (1, 0)), ('cx', (1, 1)), ('cx', (1, 2)), ('cx', (1, 3)), ('cx', (2, 0)), ('cx', (2, 1)), ('cx', (2, 2)), ('cx', (2, 3)), ('cx', (3, 0)), ('cx', (3, 1)), ('cx', (3, 2)), ('cx', (3, 3))]\n"
          ]
        }
      ],
      "source": [
        "# T1 and T2 values for qubits 0-3\n",
        "T1s = np.random.normal(\n",
        "    50e3, 10e3, 4\n",
        ")  # Sampled from normal distribution mean 50 microsec\n",
        "T2s = np.random.normal(\n",
        "    70e3, 10e3, 4\n",
        ")  # Sampled from normal distribution mean 50 microsec\n",
        "\n",
        "# Truncate random T2s <= T1s\n",
        "T2s = np.array([min(T2s[j], 2 * T1s[j]) for j in range(4)])\n",
        "\n",
        "# Instruction times (in nanoseconds)\n",
        "time_u1 = 0  # virtual gate\n",
        "time_u2 = 50  # (single X90 pulse)\n",
        "time_u3 = 100  # (two X90 pulses)\n",
        "time_cx = 300\n",
        "time_reset = 1000  # 1 microsecond\n",
        "time_measure = 1000  # 1 microsecond\n",
        "\n",
        "# QuantumError objects\n",
        "errors_reset = [\n",
        "    thermal_relaxation_error(t1, t2, time_reset) for t1, t2 in zip(T1s, T2s)\n",
        "]\n",
        "errors_measure = [\n",
        "    thermal_relaxation_error(t1, t2, time_measure) for t1, t2 in zip(T1s, T2s)\n",
        "]\n",
        "errors_u1 = [\n",
        "    thermal_relaxation_error(t1, t2, time_u1) for t1, t2 in zip(T1s, T2s)\n",
        "]\n",
        "errors_u2 = [\n",
        "    thermal_relaxation_error(t1, t2, time_u2) for t1, t2 in zip(T1s, T2s)\n",
        "]\n",
        "errors_u3 = [\n",
        "    thermal_relaxation_error(t1, t2, time_u3) for t1, t2 in zip(T1s, T2s)\n",
        "]\n",
        "errors_cx = [\n",
        "    [\n",
        "        thermal_relaxation_error(t1a, t2a, time_cx).expand(\n",
        "            thermal_relaxation_error(t1b, t2b, time_cx)\n",
        "        )\n",
        "        for t1a, t2a in zip(T1s, T2s)\n",
        "    ]\n",
        "    for t1b, t2b in zip(T1s, T2s)\n",
        "]\n",
        "\n",
        "# Add errors to noise model\n",
        "noise_thermal = NoiseModel()\n",
        "for j in range(4):\n",
        "    noise_thermal.add_quantum_error(errors_reset[j], \"reset\", [j])\n",
        "    noise_thermal.add_quantum_error(errors_measure[j], \"measure\", [j])\n",
        "    noise_thermal.add_quantum_error(errors_u1[j], \"u1\", [j])\n",
        "    noise_thermal.add_quantum_error(errors_u2[j], \"u2\", [j])\n",
        "    noise_thermal.add_quantum_error(errors_u3[j], \"u3\", [j])\n",
        "    for k in range(4):\n",
        "        noise_thermal.add_quantum_error(errors_cx[j][k], \"cx\", [j, k])\n",
        "\n",
        "print(noise_thermal)"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "a3dd27c5-c032-44b9-ada9-19280e8a0140",
      "metadata": {},
      "source": [
        "<span id=\"execute-the-noisy-simulation\" />\n",
        "\n",
        "### Exécuter la simulation bruyante\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "ff52bf52-1323-40fc-a631-2b1889b21b20",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2019-08-19T17:00:55.689241Z",
          "start_time": "2019-08-19T17:00:55.515394Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/build-noise-models/extracted-outputs/ff52bf52-1323-40fc-a631-2b1889b21b20-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Run the noisy simulation\n",
        "sim_thermal = AerSimulator(noise_model=noise_thermal)\n",
        "\n",
        "# Transpile circuit for noisy basis gates\n",
        "passmanager = generate_preset_pass_manager(\n",
        "    optimization_level=3, backend=sim_thermal\n",
        ")\n",
        "circ_tthermal = passmanager.run(circ)\n",
        "\n",
        "# Run and get counts\n",
        "result_thermal = sim_thermal.run(circ_tthermal).result()\n",
        "counts_thermal = result_thermal.get_counts(0)\n",
        "\n",
        "# Plot noisy output\n",
        "plot_histogram(counts_thermal)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0df436e1-b43c-41b1-9581-a4d530e51a7b",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Etapes suivantes\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recommandations\">\n",
        "  * Pour simuler des circuits soumis à du bruit, consultez [la section « Simulation exacte et avec bruit à l'aide des primitives de Qiskit Aer](/docs/guides/simulate-with-qiskit-sdk-primitives) ».\n",
        "  * Consultez la référence du [module de bruit Qiskit Aer.](https://qiskit.org/ecosystem/aer/apidocs/aer_noise.html)\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
}