{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "3a5616bf-6edb-4539-872a-03217649edcb",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Créer un gestionnaire de passes pour un découplage dynamique\"\n",
        "description: \"Comment créer un gestionnaire de passe pour le découplage dynamique dans Qiskit.\"\n",
        "---\n",
        "\n",
        "<span id=\"create-a-pass-manager-for-dynamical-decoupling\" />\n",
        "\n",
        "# Créer un gestionnaire de passes pour un découplage dynamique\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a5662d8c-46f8-40a8-92b5-af63c32d303f",
      "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",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1ed6dc8d-b6f2-43dc-bb40-ceec0f311764",
      "metadata": {},
      "source": [
        "Cette page montre comment utiliser le [`PadDynamicalDecoupling`](/docs/api/qiskit/qiskit.transpiler.passes.PadDynamicalDecoupling) pour ajouter au circuit une technique de suppression des erreurs appelée *découplage dynamique*.\n",
        "\n",
        "Le découplage dynamique consiste à ajouter des séquences d'impulsions (connues sous le nom de *séquences de découplage dynamique* ) à des qubits inactifs pour les faire basculer autour de la sphère de Bloch, ce qui annule l'effet des canaux de bruit et supprime ainsi la décohérence. Ces séquences d'impulsions sont similaires aux impulsions de recentrage utilisées en résonance magnétique nucléaire. Pour une description complète, voir [A Quantum Engineer's Guide to Superconducting Qubits](https://arxiv.org/abs/1904.06560).\n",
        "\n",
        "Étant donné que la passe `PadDynamicalDecoupling` ne fonctionne que sur des circuits programmés et implique des portes qui ne sont pas nécessairement des portes de base de notre cible, vous aurez besoin des éléments suivants [`ALAPScheduleAnalysis`](/docs/api/qiskit/qiskit.transpiler.passes.ALAPScheduleAnalysis) et [`BasisTranslator`](/docs/api/qiskit/qiskit.transpiler.passes.BasisTranslator) également.\n",
        "\n",
        "Récupérez les `target` informations dans le `backend` et enregistrez les noms des opérations sous le nom de `basis_gates` car le `target` devra être modifié afin d'y ajouter les informations de synchronisation pour les portes utilisées dans le découplage dynamique.\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.  Vos résultats peuvent varier.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "c55c6e3b-4016-4866-b2ec-19793e89d215",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.fake_provider import FakeSherbrooke\n",
        "\n",
        "backend = FakeSherbrooke()\n",
        "\n",
        "target = backend.target\n",
        "basis_gates = list(target.operation_names)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b8dfccd9-30c9-48dc-88bc-50af3256f187",
      "metadata": {},
      "source": [
        "Créez un circuit `efficient_su2` à titre d'exemple. Tout d'abord, transpilez le circuit vers le backend car les impulsions de découplage dynamique doivent être ajoutées après que le circuit a été transpilé et programmé. Le découplage dynamique fonctionne souvent mieux lorsqu'il y a beaucoup de temps mort dans les circuits quantiques, c'est-à-dire lorsque des qubits ne sont pas utilisés alors que d'autres sont actifs. C'est le cas dans ce circuit parce que les portes `ecr` à deux qubits sont appliquées séquentiellement dans cet ansatz.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "9479a60c-d5d0-45c7-a93e-a2a488ba8985",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/dynamical-decoupling-pass-manager/extracted-outputs/9479a60c-d5d0-45c7-a93e-a2a488ba8985-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit.circuit.library import efficient_su2\n",
        "\n",
        "qc = efficient_su2(12, entanglement=\"circular\", reps=1)\n",
        "pm = generate_preset_pass_manager(1, target=target, seed_transpiler=12345)\n",
        "qc_t = pm.run(qc)\n",
        "qc_t.draw(\"mpl\", fold=-1, idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d3ab848d-2782-431c-b028-69a46cf94360",
      "metadata": {},
      "source": [
        "Une séquence de découplage dynamique est une série de portes qui composent l'identité et sont régulièrement espacées dans le temps. Par exemple, commencez par créer une séquence simple appelée XY4, composée de quatre portes.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "368df772-aee7-4b59-b096-a47e5bc94577",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.circuit.library import XGate, YGate\n",
        "\n",
        "X = XGate()\n",
        "Y = YGate()\n",
        "\n",
        "dd_sequence = [X, Y, X, Y]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d5eafd85-6fea-42ac-8bcb-0abf15635456",
      "metadata": {},
      "source": [
        "En raison de la régularité des séquences de découplage dynamique, les informations relatives au `YGate` doivent être ajoutées au `target` car il *ne* s'agit pas d'une porte de base, contrairement au `XGate` . Nous savons *a priori* que le `YGate` a la même durée et la même erreur que le `XGate`, cependant, nous pouvons donc simplement récupérer ces propriétés à partir du `target` et les rajouter pour les `YGate` objets. C'est également la raison pour laquelle les `basis_gates` ont été enregistrés séparément, puisque nous ajoutons `YGate` l'instruction au `target` bien qu'il ne s'agisse pas d'une porte de base réelle de `ibm_fez`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "cabac6ca-c845-4c05-8c7d-2940717b3120",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler import InstructionProperties\n",
        "\n",
        "y_gate_properties = {}\n",
        "for qubit in range(target.num_qubits):\n",
        "    y_gate_properties.update(\n",
        "        {\n",
        "            (qubit,): InstructionProperties(\n",
        "                duration=target[\"x\"][(qubit,)].duration,\n",
        "                error=target[\"x\"][(qubit,)].error,\n",
        "            )\n",
        "        }\n",
        "    )\n",
        "\n",
        "target.add_instruction(YGate(), y_gate_properties)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d33f64d6-c4e3-4881-a924-f30dfce35106",
      "metadata": {},
      "source": [
        "Les circuits d'Ansatz tels que `efficient_su2` sont paramétrés, ils doivent donc être associés à une valeur avant d'être envoyés au backend. Il s'agit ici d'attribuer des paramètres aléatoires.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "788839cc-9378-4c9d-95fd-df0ec6bc2d64",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "\n",
        "rng = np.random.default_rng(1234)\n",
        "qc_t.assign_parameters(\n",
        "    rng.uniform(-np.pi, np.pi, qc_t.num_parameters), inplace=True\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "36d54ded-1786-41c0-9c8a-75f339dbd160",
      "metadata": {},
      "source": [
        "Ensuite, exécutez les passes personnalisées. Instanciez le site `PassManager` avec `ALAPScheduleAnalysis` et `PadDynamicalDecoupling`.  Exécutez d'abord `ALAPScheduleAnalysis` pour ajouter des informations temporelles sur le circuit quantique avant d'ajouter les séquences de découplage dynamique régulièrement espacées. Ces passages sont effectués sur le circuit avec `.run()`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "334796e7-fb37-42fa-be54-4135b485246b",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler import PassManager\n",
        "from qiskit.transpiler.passes.scheduling import (\n",
        "    ALAPScheduleAnalysis,\n",
        "    PadDynamicalDecoupling,\n",
        ")\n",
        "\n",
        "dd_pm = PassManager(\n",
        "    [\n",
        "        ALAPScheduleAnalysis(target=target),\n",
        "        PadDynamicalDecoupling(target=target, dd_sequence=dd_sequence),\n",
        "    ]\n",
        ")\n",
        "qc_dd = dd_pm.run(qc_t)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b0f68880-066c-4586-a27c-5d0f90d674f7",
      "metadata": {},
      "source": [
        "Utilisez l'outil de [`timeline_drawer`](/docs/api/qiskit/qiskit.visualization.timeline_drawer) visualisation pour voir la synchronisation du circuit et confirmer qu'une séquence régulièrement espacée `XGate` d'objets et `YGate` d'objets apparaît dans le circuit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "7a552621-a96f-4bb8-ae9b-4ab5a65bbb64",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/dynamical-decoupling-pass-manager/extracted-outputs/7a552621-a96f-4bb8-ae9b-4ab5a65bbb64-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import timeline_drawer\n",
        "\n",
        "timeline_drawer(qc_dd, idle_wires=False, target=target)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "836a4094-0e55-4028-9e2e-cdf561d27049",
      "metadata": {},
      "source": [
        "Enfin, comme le site `YGate` n'est pas une porte de base réelle de notre backend, appliquez manuellement la passe `BasisTranslator` (il s'agit d'une passe par défaut, mais elle est exécutée avant l'ordonnancement, et doit donc être appliquée à nouveau). La bibliothèque d'équivalences de sessions est une bibliothèque d'équivalences de circuits qui permet au transpileur de décomposer les circuits en portes de base, également spécifiées en tant qu'argument.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "f0f4b29d-1c95-47d2-a7ad-8e130eaff74a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/dynamical-decoupling-pass-manager/extracted-outputs/f0f4b29d-1c95-47d2-a7ad-8e130eaff74a-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.circuit.equivalence_library import (\n",
        "    SessionEquivalenceLibrary as sel,\n",
        ")\n",
        "from qiskit.transpiler.passes import BasisTranslator\n",
        "\n",
        "qc_dd = BasisTranslator(sel, basis_gates)(qc_dd)\n",
        "qc_dd.draw(\"mpl\", fold=-1, idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fafca471-0042-41f8-964c-606b4ee0d5cd",
      "metadata": {},
      "source": [
        "À présent, `YGate` les objets sont absents de notre circuit, et il existe des informations de synchronisation explicites sous la forme de `Delay` portes. Ce circuit transposé avec découplage dynamique est désormais prêt à être envoyé au backend.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "95fee5f9-9e7d-47db-83c2-309ca03d357a",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Etapes suivantes\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recommandations\">\n",
        "  * Pour apprendre à utiliser la fonction `generate_preset_passmanager` au lieu d'écrire vos propres passes, commencez par la rubrique [Paramètres par défaut et options de configuration de la transpilation](defaults-and-configuration-options).\n",
        "  * Consultez le guide [Comparer les paramètres du transpiler](/docs/guides/circuit-transpilation-settings#compare-transpiler-settings).\n",
        "  * Consultez la [documentation de l'API Transpile](https://docs.quantum-computing.ibm.com/api/qiskit/transpiler).\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
}