{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "58b1f0a7-d62e-4f71-ba01-b8f0beaeeb83",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Créer un plugin transcompilateur\"\n",
        "description: \"Comment créer un plugin de transpilation Qiskit pour partager votre code de transpilation avec la communauté Qiskit.\"\n",
        "---\n",
        "\n",
        "<span id=\"create-a-transpiler-plugin\" />\n",
        "\n",
        "# Créer un plugin transcompilateur\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5ec7b7a4-5318-4422-ab3d-c88cee551eaa",
      "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",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a7f87a76-b7a1-4dbb-ad45-55ff63c4665b",
      "metadata": {},
      "source": [
        "La création d'un [plugin de transpilation](transpiler-plugins) est un excellent moyen de partager votre code de transpilation avec l'ensemble de la communauté Qiskit, permettant ainsi aux autres utilisateurs de bénéficier des fonctionnalités que vous avez développées. Nous vous remercions de l'intérêt que vous portez à la communauté Qiskit!\n",
        "\n",
        "Avant de créer un plugin de transposition, vous devez décider quel type de plugin est approprié à votre situation. Il existe trois types de plugins de transposition :\n",
        "\n",
        "* [**Transpiler stage plugin**](/docs/api/qiskit/transpiler_plugins). Choisissez cette option si vous définissez un gestionnaire de passage qui peut être substitué à l'une des [six étapes](transpiler-stages) d'un gestionnaire de passage prédéfini.\n",
        "* [**Plugin de synthèse unitaire**](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin). Choisissez cette option si votre code de transpilation prend en entrée une matrice unitaire (représentée sous la forme d'un tableau Numpy) et produit une description d'un circuit quantique mettant en œuvre cette matrice unitaire.\n",
        "* [**Plugin de synthèse de haut niveau**](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin). Choisissez cette option si votre code de transpilation prend en entrée un \"objet de haut niveau\" tel qu'un opérateur de Clifford ou une fonction linéaire et produit en sortie une description d'un circuit quantique mettant en œuvre cet objet de haut niveau. Les objets de haut niveau sont représentés par des sous-classes de la classe [Opération.](/docs/api/qiskit/qiskit.circuit.Operation)\n",
        "\n",
        "Une fois que vous avez déterminé le type de plugin à créer, suivez les étapes suivantes pour créer le plugin :\n",
        "\n",
        "1. Créer une sous-classe de la classe de plugin abstraite appropriée :\n",
        "   * [PassManagerStagePlugin](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin) pour un plugin d'étape de transpilation,\n",
        "   * [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) pour un plugin de synthèse unitaire, et\n",
        "   * [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) pour un plugin de synthèse de haut niveau.\n",
        "2. Exposer la classe en tant que [point d'entrée setuptools](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) dans les métadonnées du paquetage, typiquement en éditant le fichier `pyproject.toml`, `setup.cfg`, ou `setup.py` pour votre paquetage Python.\n",
        "\n",
        "Il n'y a pas de limite au nombre de plugins qu'un paquet peut définir, mais chaque plugin doit avoir un nom unique. Le SDK Qiskit lui-même comprend un certain nombre de plugins, dont les noms sont également réservés. Les noms réservés sont les suivants\n",
        "\n",
        "* Plugins d'étape Transpiler : Voir [ce tableau](/docs/api/qiskit/transpiler_plugins#plugin-stages).\n",
        "* Plugins de synthèse unitaire : `default`, `aqc`, `sk`\n",
        "* Plugins de synthèse de haut niveau :\n",
        "\n",
        "| Classe d'opération                                                                         | Nom de l'opération | Noms réservés                                     |\n",
        "| ------------------------------------------------------------------------------------------ | ------------------ | ------------------------------------------------- |\n",
        "| [Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford#clifford)                         | `clifford`         | `default`, `ag`, `bm`, `greedy`, `layers`, `lnn`  |\n",
        "| [LinearFunction](/docs/api/qiskit/qiskit.circuit.library.LinearFunction#linearfunction)    | `linear_function`  | `default`, `kms`, `pmh`                           |\n",
        "| [PermutationGate](/docs/api/qiskit/qiskit.circuit.library.PermutationGate#permutationgate) | `permutation`      | `default`, `kms`, `basic`, `acg`, `token_swapper` |\n",
        "\n",
        "Dans les sections suivantes, nous présentons des exemples de ces étapes pour les différents types de plugins. Dans ces exemples, nous supposons que nous créons un paquet Python appelé `my_qiskit_plugin`. Pour plus d'informations sur la création de paquets Python, vous pouvez consulter [ce tutoriel](https://packaging.python.org/en/latest/tutorials/packaging-projects/) sur le site Python.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4519c0dc-2bcd-48f4-8522-435b72efdb40",
      "metadata": {},
      "source": [
        "<span id=\"example-create-a-transpiler-stage-plugin\" />\n",
        "\n",
        "## Exemple : créer un plugin de transpilateur\n",
        "\n",
        "Dans cet exemple, nous créons un plugin d'étape de transpilation pour l'étape `layout` (voir [Étapes de transpilation](transpiler-stages) pour une description des 6 étapes du pipeline de transpilation intégré de Qiskit).\n",
        "Notre plugin exécute simplement [VF2Layout](/docs/api/qiskit/qiskit.transpiler.passes.VF2Layout) pendant un nombre d'essais qui dépend du niveau d'optimisation demandé.\n",
        "\n",
        "Tout d'abord, nous créons une sous-classe de [PassManagerStagePlugin](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin). Il existe une méthode que nous devons mettre en œuvre, appelée [`pass_manager`](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin#pass_manager). Cette méthode prend en entrée un [PassManagerConfig](/docs/api/qiskit/qiskit.transpiler.PassManagerConfig) et renvoie le gestionnaire de passe que nous sommes en train de définir. L'objet PassManagerConfig stocke des informations sur le backend cible, telles que sa carte de couplage et ses portes de base.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "f90299d9-5026-424c-b528-6d0defdddb54",
      "metadata": {},
      "outputs": [],
      "source": [
        "# This import is needed for python versions prior to 3.10\n",
        "from __future__ import annotations\n",
        "\n",
        "from qiskit.transpiler import PassManager\n",
        "from qiskit.transpiler.passes import VF2Layout\n",
        "from qiskit.transpiler.passmanager_config import PassManagerConfig\n",
        "from qiskit.transpiler.preset_passmanagers import common\n",
        "from qiskit.transpiler.preset_passmanagers.plugin import (\n",
        "    PassManagerStagePlugin,\n",
        ")\n",
        "\n",
        "\n",
        "class MyLayoutPlugin(PassManagerStagePlugin):\n",
        "    def pass_manager(\n",
        "        self,\n",
        "        pass_manager_config: PassManagerConfig,\n",
        "        optimization_level: int | None = None,\n",
        "    ) -> PassManager:\n",
        "        layout_pm = PassManager(\n",
        "            [\n",
        "                VF2Layout(\n",
        "                    coupling_map=pass_manager_config.coupling_map,\n",
        "                    properties=pass_manager_config.backend_properties,\n",
        "                    max_trials=optimization_level * 10 + 1,\n",
        "                    target=pass_manager_config.target,\n",
        "                )\n",
        "            ]\n",
        "        )\n",
        "        layout_pm += common.generate_embed_passmanager(\n",
        "            pass_manager_config.coupling_map\n",
        "        )\n",
        "        return layout_pm"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d7666879-14bc-479c-a91b-56a800897073",
      "metadata": {},
      "source": [
        "Maintenant, nous exposons le plugin en ajoutant un point d'entrée dans les métadonnées de notre paquet Python.\n",
        "Nous supposons ici que la classe que nous avons définie est exposée dans un module appelé `my_qiskit_plugin`, par exemple en étant importée dans le fichier `__init__.py` du module `my_qiskit_plugin` .\n",
        "Nous éditons le fichier `pyproject.toml`, `setup.cfg`, ou `setup.py` de notre paquet (selon le type de fichier que vous avez choisi pour stocker les métadonnées de votre projet Python ) :\n",
        "\n",
        "<Tabs>\n",
        "  <TabItem value=\"package-table-toml\" label=\"pyproject.toml\" default>\n",
        "    ```toml\n",
        "    [project.entry-points.\"qiskit.transpiler.layout\"]\n",
        "    \"my_layout\" = \"my_qiskit_plugin:MyLayoutPlugin\"\n",
        "    ```\n",
        "  </TabItem>\n",
        "\n",
        "  <TabItem value=\"package-table-cfg\" label=\"setup.cfg\">\n",
        "    ```ini\n",
        "    [options.entry_points]\n",
        "    qiskit.transpiler.layout =\n",
        "        my_layout = my_qiskit_plugin:MyLayoutPlugin\n",
        "    ```\n",
        "  </TabItem>\n",
        "\n",
        "  <TabItem value=\"package-table-py\" label=\"setup.py\">\n",
        "    ```python\n",
        "    from setuptools import setup\n",
        "\n",
        "    setup(\n",
        "        # ...,\n",
        "        entry_points={\n",
        "            'qiskit.transpiler.layout': [\n",
        "                'my_layout = my_qiskit_plugin:MyLayoutPlugin',\n",
        "            ]\n",
        "        }\n",
        "    )\n",
        "    ```\n",
        "  </TabItem>\n",
        "</Tabs>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5c5edd30",
      "metadata": {},
      "source": [
        "Voir le [tableau des étapes du plugin de transposition](/docs/api/qiskit/transpiler_plugins#stage-table) pour les points d'entrée et les attentes pour chaque étape de transposition.\n",
        "\n",
        "Pour vérifier que votre plugin est bien détecté par Qiskit, installez le paquet de votre plugin et suivez les instructions à [Transpiler plugins](transpiler-plugins#list-available-transpiler-stage-plugins) pour lister les plugins installés, et assurez-vous que votre plugin apparaît dans la liste :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "04b07ec3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['default', 'dense', 'sabre', 'trivial']"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler.preset_passmanagers.plugin import list_stage_plugins\n",
        "\n",
        "list_stage_plugins(\"layout\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d62c4edb",
      "metadata": {},
      "source": [
        "Si notre exemple de plugin était installé, le nom `my_layout` apparaîtrait dans cette liste.\n",
        "\n",
        "Si vous souhaitez utiliser une étape de transposition intégrée comme point de départ de votre plugin d'étape de transposition, vous pouvez obtenir le gestionnaire de passes d'une étape de transposition intégrée en utilisant la commande [PassManagerStagePluginManager](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePluginManager#passmanagerstagepluginmanager). La cellule de code suivante montre comment procéder pour obtenir l'étape d'optimisation intégrée pour le niveau d'optimisation 3.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "f4d578d6",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler.preset_passmanagers.plugin import (\n",
        "    PassManagerStagePluginManager,\n",
        ")\n",
        "\n",
        "# Initialize the plugin manager\n",
        "plugin_manager = PassManagerStagePluginManager()\n",
        "\n",
        "# Here we create a pass manager config to use as an example.\n",
        "# Instead, you should use the pass manager config that you already received as input\n",
        "# to the pass_manager method of your PassManagerStagePlugin.\n",
        "pass_manager_config = PassManagerConfig()\n",
        "\n",
        "# Obtain the desired built-in transpiler stage\n",
        "optimization = plugin_manager.get_passmanager_stage(\n",
        "    \"optimization\", \"default\", pass_manager_config, optimization_level=3\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fe3a1a6c-5aa2-4f00-9bdd-45598717be1d",
      "metadata": {},
      "source": [
        "<span id=\"example-create-a-unitary-synthesis-plugin\" />\n",
        "\n",
        "## Exemple : Créer un plugin de synthèse unitaire\n",
        "\n",
        "Dans cet exemple, nous allons créer un plugin de synthèse unitaire qui utilise simplement la passe de transpilation intégrée pour synthétiser une porte [UnitarySynthesis](/docs/api/qiskit/qiskit.transpiler.passes.UnitarySynthesis#unitarysynthesis) pour synthétiser une porte. Bien sûr, votre propre plugin fera quelque chose de plus intéressant que cela.\n",
        "\n",
        "La classe [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) définit l'interface et le contrat pour les plugins de synthèse unitaire de la synthèse unitaire. La méthode principale est [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin#run), qui prend en entrée un tableau Numpy stockant une matrice unitaire et renvoie un [DAGCircuit](/docs/api/qiskit/qiskit.dagcircuit.DAGCircuit) représentant le circuit synthétisé à partir de cette matrice unitaire.\n",
        "Outre la méthode `run` , un certain nombre de méthodes relatives aux propriétés doivent être définies.\n",
        "Voir [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) pour la documentation de toutes les propriétés requises.\n",
        "\n",
        "Créons notre sous-classe UnitarySynthesisPlugin :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "6bc1011c-b15d-4210-973b-d9d530ece880",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "from qiskit.circuit import QuantumCircuit, QuantumRegister\n",
        "from qiskit.converters import circuit_to_dag\n",
        "from qiskit.dagcircuit.dagcircuit import DAGCircuit\n",
        "from qiskit.quantum_info import Operator\n",
        "from qiskit.transpiler.passes import UnitarySynthesis\n",
        "from qiskit.transpiler.passes.synthesis.plugin import UnitarySynthesisPlugin\n",
        "\n",
        "\n",
        "class MyUnitarySynthesisPlugin(UnitarySynthesisPlugin):\n",
        "    @property\n",
        "    def supports_basis_gates(self):\n",
        "        # Returns True if the plugin can target a list of basis gates\n",
        "        return True\n",
        "\n",
        "    @property\n",
        "    def supports_coupling_map(self):\n",
        "        # Returns True if the plugin can synthesize for a given coupling map\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def supports_natural_direction(self):\n",
        "        # Returns True if the plugin supports a toggle for considering\n",
        "        # directionality of 2-qubit gates\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def supports_pulse_optimize(self):\n",
        "        # Returns True if the plugin can optimize pulses during synthesis\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def supports_gate_lengths(self):\n",
        "        # Returns True if the plugin can accept information about gate lengths\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def supports_gate_errors(self):\n",
        "        # Returns True if the plugin can accept information about gate errors\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def supports_gate_lengths_by_qubit(self):\n",
        "        # Returns True if the plugin can accept information about gate lengths\n",
        "        # (The format of the input differs from supports_gate_lengths)\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def supports_gate_errors_by_qubit(self):\n",
        "        # Returns True if the plugin can accept information about gate errors\n",
        "        # (The format of the input differs from supports_gate_errors)\n",
        "        return False\n",
        "\n",
        "    @property\n",
        "    def min_qubits(self):\n",
        "        # Returns the minimum number of qubits the plugin supports\n",
        "        return None\n",
        "\n",
        "    @property\n",
        "    def max_qubits(self):\n",
        "        # Returns the maximum number of qubits the plugin supports\n",
        "        return None\n",
        "\n",
        "    @property\n",
        "    def supported_bases(self):\n",
        "        # Returns a dictionary of supported bases for synthesis\n",
        "        return None\n",
        "\n",
        "    def run(self, unitary: np.ndarray, **options) -> DAGCircuit:\n",
        "        basis_gates = options[\"basis_gates\"]\n",
        "        synth_pass = UnitarySynthesis(basis_gates, min_qubits=3)\n",
        "        qubits = QuantumRegister(3)\n",
        "        circuit = QuantumCircuit(qubits)\n",
        "        circuit.append(Operator(unitary).to_instruction(), qubits)\n",
        "        dag_circuit = synth_pass.run(circuit_to_dag(circuit))\n",
        "        return dag_circuit"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6daebf1b-aa38-44a8-bf62-eea96838e95f",
      "metadata": {},
      "source": [
        "Si vous constatez que les entrées disponibles pour le [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin#run) sont insuffisantes pour vos besoins, veuillez [ouvrir un dossier](https://github.com/Qiskit/qiskit/issues/new/choose) expliquant vos exigences. Les modifications apportées à l'interface du plugin, telles que l'ajout d'entrées optionnelles supplémentaires, seront effectuées de manière à ce qu'elles ne nécessitent pas de modifications des plugins existants.\n",
        "\n",
        "<Admonition type=\"note\" title=\"Remarque\">\n",
        "  Toutes les méthodes précédées du préfixe `supports_` sont réservées à une classe dérivée `UnitarySynthesisPlugin` en tant que partie de l'interface. Vous ne devez pas définir de méthodes `supports_*` personnalisées sur une sous-classe qui ne sont pas définies dans la classe abstraite.\n",
        "</Admonition>\n",
        "\n",
        "Maintenant, nous exposons le plugin en ajoutant un point d'entrée dans les métadonnées de notre paquet Python.\n",
        "Nous supposons ici que la classe que nous avons définie est exposée dans un module appelé `my_qiskit_plugin`, par exemple en étant importée dans le fichier `__init__.py` du module `my_qiskit_plugin` .\n",
        "Nous modifions le fichier `pyproject.toml`, `setup.cfg`, ou `setup.py` de notre paquet :\n",
        "\n",
        "<Tabs>\n",
        "  <TabItem value=\"package-table-toml\" label=\"pyproject.toml\" default>\n",
        "    ```toml\n",
        "    [project.entry-points.\"qiskit.unitary_synthesis\"]\n",
        "    \"my_unitary_synthesis\" = \"my_qiskit_plugin:MyUnitarySynthesisPlugin\"\n",
        "    ```\n",
        "  </TabItem>\n",
        "\n",
        "  <TabItem value=\"package-table-cfg\" label=\"setup.cfg\">\n",
        "    ```ini\n",
        "    [options.entry_points]\n",
        "    qiskit.unitary_synthesis =\n",
        "        my_unitary_synthesis = my_qiskit_plugin:MyUnitarySynthesisPlugin\n",
        "    ```\n",
        "  </TabItem>\n",
        "\n",
        "  <TabItem value=\"package-table-py\" label=\"setup.py\">\n",
        "    ```python\n",
        "    from setuptools import setup\n",
        "\n",
        "    setup(\n",
        "        # ...,\n",
        "        entry_points={\n",
        "            'qiskit.unitary_synthesis': [\n",
        "                'my_unitary_synthesis = my_qiskit_plugin:MyUnitarySynthesisPlugin',\n",
        "            ]\n",
        "        }\n",
        "    )\n",
        "    ```\n",
        "  </TabItem>\n",
        "</Tabs>\n",
        "\n",
        "Comme précédemment, si votre projet utilise `setup.cfg` ou `setup.py` au lieu de `pyproject.toml`, consultez la [documentation de setuptools](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) pour adapter ces lignes à votre situation.\n",
        "\n",
        "Pour vérifier que votre plugin est bien détecté par Qiskit, installez le paquet de votre plugin et suivez les instructions à [Transpiler plugins](transpiler-plugins#list-available-unitary-synthesis-plugins) pour lister les plugins installés, et assurez-vous que votre plugin apparaît dans la liste :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "31bfaf30",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['aqc', 'clifford', 'default', 'gridsynth', 'sk']"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler.passes.synthesis import unitary_synthesis_plugin_names\n",
        "\n",
        "unitary_synthesis_plugin_names()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4faf2d51",
      "metadata": {},
      "source": [
        "Si notre exemple de plugin était installé, le nom `my_unitary_synthesis` apparaîtrait dans cette liste.\n",
        "\n",
        "Pour accommoder les plugins de synthèse unitaire qui exposent des options multiples, l'interface du plugin comporte une option permettant aux utilisateurs de fournir un de configuration de forme libre. Elle sera transmise à la méthode `run` par l'intermédiaire du mot-clé `options` . Si votre plugin dispose de ces options de configuration, vous devez les documenter clairement.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "651c863d-41d9-41f4-a133-b392dae2f363",
      "metadata": {},
      "source": [
        "<span id=\"example-create-a-high-level-synthesis-plugin\" />\n",
        "\n",
        "## Exemple : Créer un plugin de synthèse de haut niveau\n",
        "\n",
        "Dans cet exemple, nous allons créer un plugin de synthèse de haut niveau qui utilise simplement la fonction intégrée [synth\\_clifford\\_bm](/docs/api/qiskit/synthesis#synth_clifford_bm) pour synthétiser un opérateur de Clifford.\n",
        "\n",
        "La classe [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) définit l'interface et le contrat pour les plugins de synthèse de haut niveau. La méthode principale est [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin#run).\n",
        "L'argument positionnel `high_level_object` est une [opération](/docs/api/qiskit/qiskit.circuit.Operation) représentant l'objet de \"haut niveau\" à synthétiser. Par exemple, il peut s'agir d'un [LinearFunction](/docs/api/qiskit/qiskit.circuit.library.LinearFunction) ou un [Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford).\n",
        "Les arguments suivants sont présents dans les mots-clés :\n",
        "\n",
        "* `target` spécifie le backend cible, ce qui permet au plugin d'accéder à toutes les informations spécifiques à la cible, telles que la carte de couplage, le jeu de portes supporté, etc\n",
        "* `coupling_map` ne spécifie que la carte de couplage et n'est utilisé que si `target` n'est pas spécifié.\n",
        "* `qubits` spécifie la liste des qubits sur lesquels l'objet de haut niveau est défini, dans le cas où la synthèse est effectuée sur le circuit physique est défini, dans le cas où la synthèse est effectuée sur le circuit physique.\n",
        "  Une valeur de `None` indique que la disposition n'a pas encore été choisie et que les qubits physiques de la cible ou de la carte de couplage sur laquelle cette opération est effectuée n'ont pas encore été déterminés.\n",
        "* `options`un dictionnaire de configuration de forme libre pour les options spécifiques au plugin. Si votre plugin dispose de ces options de configuration, vous vous devez les documenter clairement.\n",
        "\n",
        "La méthode `run` renvoie un [QuantumCircuit](/docs/api/qiskit/qiskit.circuit.QuantumCircuit) représentant le circuit synthétisé à partir de cet objet de haut niveau.\n",
        "Il est également autorisé à renvoyer `None`, indiquant que le plugin n'est pas en mesure de synthétiser l'objet de haut niveau donné.\n",
        "La synthèse proprement dite des objets de haut niveau est réalisée par le programme [HighLevelSynthesis](/docs/api/qiskit/qiskit.transpiler.passes.HighLevelSynthesis) transpileur.\n",
        "\n",
        "Outre la méthode `run` , un certain nombre de méthodes relatives aux propriétés doivent être définies.\n",
        "Voir [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) pour la documentation de toutes les propriétés requises.\n",
        "\n",
        "Définissons notre sous-classe HighLevelSynthesisPlugin :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "3c0e59d4-85b0-4157-824b-b1f6220e83ad",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.synthesis import synth_clifford_bm\n",
        "from qiskit.transpiler.passes.synthesis.plugin import HighLevelSynthesisPlugin\n",
        "\n",
        "\n",
        "class MyCliffordSynthesisPlugin(HighLevelSynthesisPlugin):\n",
        "    def run(\n",
        "        self,\n",
        "        high_level_object,\n",
        "        coupling_map=None,\n",
        "        target=None,\n",
        "        qubits=None,\n",
        "        **options,\n",
        "    ) -> QuantumCircuit:\n",
        "        if high_level_object.num_qubits <= 3:\n",
        "            return synth_clifford_bm(high_level_object)\n",
        "        else:\n",
        "            return None"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1285dbfd-04ce-494b-8a01-a58040035dbd",
      "metadata": {},
      "source": [
        "Ce plugin synthétise des objets de type [Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford) qui possèdent au plus 3 qubits, en utilisant la méthode `synth_clifford_bm` .\n",
        "\n",
        "Maintenant, nous exposons le plugin en ajoutant un point d'entrée dans les métadonnées de notre paquet Python.\n",
        "Nous supposons ici que la classe que nous avons définie est exposée dans un module appelé `my_qiskit_plugin`, par exemple en étant importée dans le fichier `__init__.py` du module `my_qiskit_plugin` .\n",
        "Nous modifions le fichier `pyproject.toml`, `setup.cfg`, ou `setup.py` de notre paquet :\n",
        "\n",
        "<Tabs>\n",
        "  <TabItem value=\"package-table-toml\" label=\"pyproject.toml\" default>\n",
        "    ```toml\n",
        "    [project.entry-points.\"qiskit.synthesis\"]\n",
        "    \"clifford.my_clifford_synthesis\" = \"my_qiskit_plugin:MyCliffordSynthesisPlugin\"\n",
        "    ```\n",
        "  </TabItem>\n",
        "\n",
        "  <TabItem value=\"package-table-cfg\" label=\"setup.cfg\">\n",
        "    ```ini\n",
        "    [options.entry_points]\n",
        "    qiskit.synthesis =\n",
        "        clifford.my_clifford_synthesis = my_qiskit_plugin:MyCliffordSynthesisPlugin\n",
        "    ```\n",
        "  </TabItem>\n",
        "\n",
        "  <TabItem value=\"package-table-py\" label=\"setup.py\">\n",
        "    ```python\n",
        "    from setuptools import setup\n",
        "\n",
        "    setup(\n",
        "        # ...,\n",
        "        entry_points={\n",
        "            'qiskit.synthesis': [\n",
        "                'clifford.my_clifford_synthesis = my_qiskit_plugin:MyCliffordSynthesisPlugin',\n",
        "            ]\n",
        "        }\n",
        "    )\n",
        "    ```\n",
        "  </TabItem>\n",
        "</Tabs>\n",
        "\n",
        "Le site `name` se compose de deux parties séparées par un point (`.`) :\n",
        "\n",
        "* Le nom du type d' [opération](/docs/api/qiskit/qiskit.circuit.Operation) que le plugin synthétise (dans ce cas, `clifford`). Notez que cette chaîne correspond à l'attribut [`name`](/docs/api/qiskit/qiskit.circuit.Operation#name) de la classe Operation, et non au nom de la classe elle-même.\n",
        "* Le nom du plugin (dans ce cas, `special`).\n",
        "\n",
        "Comme précédemment, si votre projet utilise `setup.cfg` ou `setup.py` au lieu de `pyproject.toml`, consultez la [documentation de setuptools](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) pour adapter ces lignes à votre situation.\n",
        "\n",
        "Pour vérifier que votre plugin est bien détecté par Qiskit, installez le paquet de votre plugin et suivez les instructions à [Transpiler plugins](transpiler-plugins#list-available-high-level-synthesis-plugins) pour lister les plugins installés, et assurez-vous que votre plugin apparaît dans la liste :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "fbe1f265",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['ag', 'bm', 'default', 'greedy', 'layers', 'lnn', 'rb_default']"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler.passes.synthesis import (\n",
        "    high_level_synthesis_plugin_names,\n",
        ")\n",
        "\n",
        "high_level_synthesis_plugin_names(\"clifford\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f1e86f49",
      "metadata": {},
      "source": [
        "Si notre exemple de plugin était installé, le nom `my_clifford_synthesis` apparaîtrait dans cette liste.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a48c2d0b-c402-4b83-ae2e-42c33fe1720e",
      "metadata": {},
      "source": [
        "<Admonition type=\"tip\" title=\"Recommandation\">\n",
        "  * [Soumettez votre plugin à l'écosystème Qiskit!](https://github.com/Qiskit/ecosystem?tab=readme-ov-file#how-to-join)\n",
        "  * Consultez les [didacticiels](/docs/tutorials) pour des exemples de transposition et d'exécution de circuits quantiques.\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": 5
}