{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "e6d26387-f218-4f62-80c4-792103129b99",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Simulation efficace des circuits stabilisateurs avec les primitives Aer de Qiskit\"\n",
        "description: \"Comment simuler efficacement des circuits stabilisateurs à l'aide des primitives Qiskit Aer.\"\n",
        "---\n",
        "\n",
        "<span id=\"efficient-simulation-of-stabilizer-circuits-with-qiskit-aer-primitives\" />\n",
        "\n",
        "# Simulation efficace des circuits stabilisateurs avec les primitives Aer de Qiskit\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f1bcbbdb-965d-41f0-88dd-bb42834b35b9",
      "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-aer~=0.17\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "386709ed-183b-4759-bb1b-56cdedf80539",
      "metadata": {},
      "source": [
        "Cette page montre comment utiliser les primitives de Qiskit Aer pour simuler efficacement des circuits stabilisateurs, y compris ceux soumis au bruit de Pauli.\n",
        "\n",
        "Les circuits stabilisateurs, également connus sous le nom de circuits de Clifford, constituent une classe restreinte importante de circuits quantiques qui peuvent être efficacement simulés de manière classique. Il existe plusieurs façons équivalentes de définir les circuits stabilisateurs. Une définition est qu'un circuit stabilisateur est un circuit quantique composé uniquement des portes suivantes :\n",
        "\n",
        "* [expérience client](../api/qiskit/qiskit.circuit.library.CXGate)\n",
        "* [Hadamard](../api/qiskit/qiskit.circuit.library.HGate)\n",
        "* [S](../api/qiskit/qiskit.circuit.library.SGate)\n",
        "* [Mesure](../api/qiskit/circuit#qiskit.circuit.Measure)\n",
        "\n",
        "Notez qu'en utilisant Hadamard et S, nous pouvons construire n'importe quelle porte de rotation de Pauli ( [$R_x$](/docs/api/qiskit/qiskit.circuit.library.RXGate), [$R_y$](/docs/api/qiskit/qiskit.circuit.library.RYGate), et [$R_z$](/docs/api/qiskit/qiskit.circuit.library.RZGate) ) dont l'angle est contenu dans l'ensemble $\\{0, \\frac{\\pi}{2}, \\pi, \\frac{3\\pi}{2}\\}$ (jusqu'à la phase globale), de sorte que nous pouvons également inclure ces portes dans la définition.\n",
        "\n",
        "Les circuits stabilisateurs sont importants pour l'étude de la correction quantique des erreurs. Leur simulabilité classique les rend également utiles pour vérifier les résultats des ordinateurs quantiques. Par exemple, supposons que vous souhaitiez exécuter un circuit quantique utilisant 100 qubits sur un ordinateur quantique. Comment savoir si l'ordinateur quantique se comporte correctement? Un circuit quantique de 100 qubits est hors de portée d'une simulation classique par force brute. En modifiant votre circuit pour qu'il devienne un circuit stabilisateur, vous pouvez exécuter sur l'ordinateur quantique des circuits dont la structure est similaire à celle du circuit souhaité, mais que vous pouvez simuler sur un ordinateur classique. En vérifiant la sortie de l'ordinateur quantique sur les circuits stabilisateurs, vous pouvez être sûr qu'il se comporte correctement sur les circuits non stabilisateurs également. Voir [*Evidence for the utility of quantum computing before fault tolerance*](https://www.nature.com/articles/s41586-023-06096-3) pour un exemple de cette idée en pratique.\n",
        "\n",
        "[La simulation exacte et bruyante avec les primitives Qiskit Aer](simulate-with-qiskit-aer) montre comment utiliser [Qiskit Aer](https://qiskit.org/ecosystem/aer/) pour effectuer des simulations exactes et bruyantes de circuits quantiques génériques. Prenons l'exemple du circuit utilisé dans cet article, un circuit de 8 qubits construit à l'aide d'un [système efficace (efficient\\_su2) :](../api/qiskit/qiskit.circuit.library.efficient_su2)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "2d26ac3e-2a6a-4d73-900f-470200a63154",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/simulate-stabilizer-circuits/extracted-outputs/2d26ac3e-2a6a-4d73-900f-470200a63154-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.circuit.library import efficient_su2\n",
        "\n",
        "n_qubits = 8\n",
        "circuit = efficient_su2(n_qubits)\n",
        "circuit.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9f72e683-a828-456d-a5d4-910758cc9add",
      "metadata": {},
      "source": [
        "En utilisant Qiskit Aer, nous avons pu simuler ce circuit facilement. Cependant, supposons que nous fixions le nombre de qubits à 500 :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "43c8277f-3f0d-4d31-a1c2-e4c541083f5d",
      "metadata": {},
      "outputs": [],
      "source": [
        "n_qubits = 500\n",
        "circuit = efficient_su2(n_qubits)\n",
        "# don't try to draw the circuit because it's too large"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ecd975b0-2ec0-4a99-a0f6-790d43af19fb",
      "metadata": {},
      "source": [
        "Étant donné que le coût de la simulation des circuits quantiques augmente de façon exponentielle avec le nombre de qubits, un circuit de cette taille dépasserait généralement les capacités d'un simulateur aussi performant que Qiskit Aer. La simulation classique de circuits quantiques génériques devient infaisable lorsque le nombre de qubits dépasse environ 50 à 100 qubits. Il convient toutefois de noter que le circuit efficient\\_su2 est paramétré par des angles sur les portes $R_y$ et $R_z$. Si tous ces angles sont contenus dans l'ensemble $\\{0, \\frac{\\pi}{2}, \\pi, \\frac{3\\pi}{2}\\}$, alors le circuit est un circuit stabilisateur et il peut être simulé efficacement!\n",
        "\n",
        "Dans la cellule suivante, nous exécutons le circuit avec la primitive Échantillonneur soutenue par le simulateur de circuit stabilisateur, en utilisant des paramètres choisis au hasard de sorte que le circuit soit garanti comme étant un circuit stabilisateur.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "2210bbe3-1a89-48fe-a4ea-f3c9b1cd37d0",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_aer import AerSimulator\n",
        "from qiskit_aer.primitives import SamplerV2 as Sampler\n",
        "\n",
        "measured_circuit = circuit.copy()\n",
        "measured_circuit.measure_all()\n",
        "\n",
        "rng = np.random.default_rng(1234)\n",
        "params = rng.choice(\n",
        "    [0, np.pi / 2, np.pi, 3 * np.pi / 2],\n",
        "    size=circuit.num_parameters,\n",
        ")\n",
        "\n",
        "# Initialize a Sampler backed by the stabilizer circuit simulator\n",
        "exact_sampler = Sampler(\n",
        "    options=dict(backend_options=dict(method=\"stabilizer\"))\n",
        ")\n",
        "# The circuit needs to be transpiled to the AerSimulator target\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    1, AerSimulator(method=\"stabilizer\")\n",
        ")\n",
        "isa_circuit = pass_manager.run(measured_circuit)\n",
        "pub = (isa_circuit, params)\n",
        "job = exact_sampler.run([pub])\n",
        "result = job.result()\n",
        "pub_result = result[0]\n",
        "counts = pub_result.data.meas.get_counts()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "445694b0-3e5b-4fc2-a610-f86674065045",
      "metadata": {},
      "source": [
        "Le simulateur de circuit de stabilisation prend également en charge la simulation bruyante, mais seulement pour une classe restreinte de modèles de bruit. Plus précisément, tout bruit quantique doit être caractérisé par un canal d' [erreur de Pauli](https://qiskit.org/ecosystem/aer/stubs/qiskit_aer.noise.pauli_error.html#qiskit_aer.noise.pauli_error). L' [erreur de dépolarisation](https://qiskit.org/ecosystem/aer/stubs/qiskit_aer.noise.depolarizing_error.html) entre dans cette catégorie et peut donc être simulée. Les canaux de bruit classiques tels que l' [erreur de lecture](https://qiskit.org/ecosystem/aer/stubs/qiskit_aer.noise.ReadoutError.html) peuvent également être simulés.\n",
        "\n",
        "La cellule de code suivante exécute la même simulation que précédemment, mais en spécifiant cette fois un modèle de bruit qui ajoute une erreur de dépolarisation de 2 % à chaque porte CX, ainsi qu'une erreur de lecture qui renverse chaque bit mesuré avec une probabilité de 5 %.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "71dd8d78-6efd-4c4e-900a-1d73deafe46e",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_aer.noise import NoiseModel, depolarizing_error, ReadoutError\n",
        "\n",
        "noise_model = NoiseModel()\n",
        "cx_depolarizing_prob = 0.02\n",
        "bit_flip_prob = 0.05\n",
        "noise_model.add_all_qubit_quantum_error(\n",
        "    depolarizing_error(cx_depolarizing_prob, 2), [\"cx\"]\n",
        ")\n",
        "noise_model.add_all_qubit_readout_error(\n",
        "    ReadoutError(\n",
        "        [\n",
        "            [1 - bit_flip_prob, bit_flip_prob],\n",
        "            [bit_flip_prob, 1 - bit_flip_prob],\n",
        "        ]\n",
        "    )\n",
        ")\n",
        "\n",
        "noisy_sampler = Sampler(\n",
        "    options=dict(\n",
        "        backend_options=dict(method=\"stabilizer\", noise_model=noise_model)\n",
        "    )\n",
        ")\n",
        "job = noisy_sampler.run([pub])\n",
        "result = job.result()\n",
        "pub_result = result[0]\n",
        "counts = pub_result.data.meas.get_counts()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "01b3e796-bd06-419f-a2fc-55c8603f662f",
      "metadata": {},
      "source": [
        "Utilisons maintenant la primitive Estimateur soutenue par le simulateur de stabilisateur pour calculer la valeur de l'espérance de l'observable $ZZ \\cdots Z$. En raison de la structure particulière des circuits stabilisateurs, le résultat a de fortes chances d'être égal à 0.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "57fb0674-5bd2-44b0-a28e-e73deff455cf",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "0.0"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit_aer.primitives import EstimatorV2 as Estimator\n",
        "\n",
        "observable = SparsePauliOp(\"Z\" * n_qubits)\n",
        "\n",
        "exact_estimator = Estimator(\n",
        "    options=dict(backend_options=dict(method=\"stabilizer\")),\n",
        ")\n",
        "isa_circuit = pass_manager.run(circuit)\n",
        "pub = (isa_circuit, observable, params)\n",
        "job = exact_estimator.run([pub])\n",
        "result = job.result()\n",
        "pub_result = result[0]\n",
        "exact_value = float(pub_result.data.evs)\n",
        "exact_value"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9d5e6593-06f0-4e1b-a4f0-7b640a74f6c5",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Etapes suivantes\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recommandations\">\n",
        "  * Pour simuler des circuits avec Qiskit Aer, 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 documentation de [Qiskit Aer.](https://qiskit.org/ecosystem/aer/)\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
}