{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "58b1f0a7-d62e-4f71-ba01-b8f0beaeeb83",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Erstellen Sie ein Transpiler-Plugin\"\n",
        "description: \"So erstellen Sie ein Qiskit-Transpiler-Plugin, um Ihren Transpiler-Code mit der Qiskit-Community zu teilen.\"\n",
        "---\n",
        "\n",
        "<span id=\"create-a-transpiler-plugin\" />\n",
        "\n",
        "# Erstellen Sie ein Transpiler-Plugin\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=\"Paketversionen\">\n",
        "    Der Code auf dieser Seite wurde unter Berücksichtigung der folgenden Anforderungen entwickelt.\n",
        "    Wir empfehlen die Verwendung dieser oder neuerer Versionen.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.2\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a7f87a76-b7a1-4dbb-ad45-55ff63c4665b",
      "metadata": {},
      "source": [
        "Die Erstellung eines [Transpiler-Plugins](transpiler-plugins) ist eine gute Möglichkeit, Ihren Transpilationscode mit der breiteren Qiskit-Gemeinschaft zu teilen, so dass andere Benutzer von der von Ihnen entwickelten Funktionalität profitieren können. Vielen Dank für Ihr Interesse, zur Qiskit-Gemeinschaft beizutragen!\n",
        "\n",
        "Bevor Sie ein Transpiler-Plugin erstellen, müssen Sie entscheiden, welche Art von Plugin für Ihre Situation geeignet ist. Es gibt drei Arten von Transpiler-Plugins:\n",
        "\n",
        "* [**Transpiler-Stufen-Plugin**](/docs/api/qiskit/transpiler_plugins). Wählen Sie diese Option, wenn Sie einen Passmanager definieren, der eine der [6 Stufen](transpiler-stages) eines voreingestellten gestaffelten Passmanagers ersetzen kann.\n",
        "* [**Unitarisches Synthese-Plugin**](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin). Wählen Sie dies, wenn Ihr Transpilationscode als Eingabe eine unitäre Matrix (dargestellt als Numpy-Array) erhält und eine Beschreibung einer Quantenschaltung ausgibt, die diese unitäre Matrix implementiert.\n",
        "* [**High-Level-Synthese-Plugin**](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin). Wählen Sie diese Option, wenn Ihr Transpilationscode ein \"High-Level-Objekt\" wie einen Clifford-Operator oder eine lineare Funktion als Eingabe erhält und eine Beschreibung einer Quantenschaltung ausgibt, die dieses High-Level-Objekt implementiert. Objekte der höheren Ebene werden durch Unterklassen der Klasse [Operation](/docs/api/qiskit/qiskit.circuit.Operation) dargestellt.\n",
        "\n",
        "Wenn Sie sich entschieden haben, welche Art von Plugin Sie erstellen möchten, folgen Sie diesen Schritten, um das Plugin zu erstellen:\n",
        "\n",
        "1. Erstellen Sie eine Unterklasse der entsprechenden abstrakten Plugin-Klasse:\n",
        "   * [PassManagerStagePlugin](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin) für ein Transpiler-Stage-Plugin,\n",
        "   * [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) für ein unitäres Synthese-Plugin, und\n",
        "   * [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) für ein High-Level-Synthese-Plugin.\n",
        "2. Stellen Sie die Klasse als [setuptools-Einstiegspunkt](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) in den Paket-Metadaten zur Verfügung, indem Sie typischerweise die Datei `pyproject.toml`, `setup.cfg` oder `setup.py` für Ihr Python -Paket bearbeiten.\n",
        "\n",
        "Es gibt keine Begrenzung für die Anzahl der Plugins, die ein einzelnes Paket definieren kann, aber jedes Plugin muss einen eindeutigen Namen haben. Das Qiskit SDK selbst enthält eine Reihe von Plugins, deren Namen ebenfalls reserviert sind. Die reservierten Namen sind:\n",
        "\n",
        "* Transpiler-Stufen-Plugins: Siehe [diese Tabelle](/docs/api/qiskit/transpiler_plugins#plugin-stages).\n",
        "* Unitäre Synthese-Plugins: `default`, `aqc`, `sk`\n",
        "* High-Level-Synthese-Plugins:\n",
        "\n",
        "| Betriebsklasse                                                                             | Operationsname    | Reservierte Namen                                 |\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",
        "In den nächsten Abschnitten zeigen wir Beispiele für diese Schritte für die verschiedenen Arten von Plugins. In diesen Beispielen gehen wir davon aus, dass wir ein Python Paket namens `my_qiskit_plugin` erstellen. Informationen zur Erstellung von Python Paketen finden Sie in [dieser Anleitung](https://packaging.python.org/en/latest/tutorials/packaging-projects/) auf der Website Python.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4519c0dc-2bcd-48f4-8522-435b72efdb40",
      "metadata": {},
      "source": [
        "<span id=\"example-create-a-transpiler-stage-plugin\" />\n",
        "\n",
        "## Beispiel: Erstellen Sie ein Transpiler-Stage-Plugin\n",
        "\n",
        "In diesem Beispiel erstellen wir ein Transpilerstufen-Plugin für die Stufe `layout` (siehe [Transpilerstufen](transpiler-stages) für eine Beschreibung der 6 Stufen der in Qiskit integrierten Transpilierungspipeline).\n",
        "Unser Plugin läuft einfach [VF2Layout](/docs/api/qiskit/qiskit.transpiler.passes.VF2Layout) für eine Anzahl von Versuchen, die von der gewünschten Optimierungsstufe abhängt.\n",
        "\n",
        "Zunächst erstellen wir eine Unterklasse von [PassManagerStagePlugin](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin). Es gibt eine Methode, die wir implementieren müssen, sie heißt [`pass_manager`](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePlugin#pass_manager). Diese Methode nimmt als Eingabe ein [PassManagerConfig](/docs/api/qiskit/qiskit.transpiler.PassManagerConfig) und gibt den von uns definierten Passmanager zurück. Das PassManagerConfig Objekt speichert Informationen über das Ziel-Backend, wie z.B. seine Kopplungskarte und Basis-Gates.\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": [
        "Jetzt machen wir das Plugin bekannt, indem wir einen Eintragspunkt in den Metadaten unseres Python -Pakets hinzufügen.\n",
        "Hier nehmen wir an, dass die Klasse, die wir definiert haben, in einem Modul namens `my_qiskit_plugin` exponiert ist, z. B. indem sie in der Datei `__init__.py` des Moduls `my_qiskit_plugin` importiert wird.\n",
        "Wir bearbeiten die Datei `pyproject.toml`, `setup.cfg` oder `setup.py` unseres Pakets (je nachdem, welche Art von Datei Sie für die Speicherung Ihrer Python Projekt-Metadaten gewählt haben):\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": [
        "In der [Tabelle der Transpiler-Plugin-Stufen](/docs/api/qiskit/transpiler_plugins#stage-table) finden Sie die Einstiegspunkte und Erwartungen für jede Transpiler-Stufe.\n",
        "\n",
        "Um zu überprüfen, ob Ihr Plugin erfolgreich von Qiskit erkannt wird, installieren Sie Ihr Plugin-Paket und folgen Sie den Anweisungen unter [Transpiler-Plugins](transpiler-plugins#list-available-transpiler-stage-plugins) für die Auflistung der installierten Plugins und stellen Sie sicher, dass Ihr Plugin in der Liste erscheint:\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": [
        "Wenn unser Beispiel-Plugin installiert wäre, würde der Name `my_layout` in dieser Liste erscheinen.\n",
        "\n",
        "Wenn Sie eine eingebaute Transpilerstufe als Ausgangspunkt für Ihr Transpilerstufen-Plugin verwenden möchten, können Sie den Passmanager für eine eingebaute Transpilerstufe mit [PassManagerStagePluginManager](/docs/api/qiskit/qiskit.transpiler.preset_passmanagers.plugin.PassManagerStagePluginManager#passmanagerstagepluginmanager). Die folgende Code-Zelle zeigt, wie man dies tut, um die eingebaute Optimierungsstufe für Optimierungsstufe 3 zu erhalten.\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",
        "## Beispiel: Erstellen Sie ein einheitliches Synthese-Plugin\n",
        "\n",
        "In diesem Beispiel erstellen wir ein unitäres Synthese-Plugin, das einfach den eingebauten [UnitarySynthesis](/docs/api/qiskit/qiskit.transpiler.passes.UnitarySynthesis#unitarysynthesis) transpilationspassus verwendet, um ein Gatter zu synthetisieren. Natürlich wird Ihr eigenes Plugin etwas Interessanteres tun als das.\n",
        "\n",
        "Die Klasse [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) klasse definiert die Schnittstelle und den Vertrag für unitäre Synthese plugins. Die wichtigste Methode ist [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin#run), die als Eingabe ein Numpy-Array zur Speicherung einer unitären Matrix speichert und einen [DAGCircuit](/docs/api/qiskit/qiskit.dagcircuit.DAGCircuit) zurückgibt, der die aus dieser unitären Matrix synthetisierte Schaltung darstellt.\n",
        "Neben der Methode `run` gibt es noch eine Reihe von Eigenschaftsmethoden, die definiert werden müssen.\n",
        "Siehe [UnitarySynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin) finden Sie eine Dokumentation aller erforderlichen Eigenschaften.\n",
        "\n",
        "Lassen Sie uns unsere Unterklasse UnitarySynthesisPlugin erstellen:\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": [
        "Wenn Sie feststellen, dass die verfügbaren Eingänge für [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.UnitarySynthesisPlugin#run) Methode für Ihre Zwecke nicht ausreichen, [öffnen Sie bitte ein Problem](https://github.com/Qiskit/qiskit/issues/new/choose) und erläutern Sie Ihre Anforderungen. Änderungen an der Plugin-Schnittstelle, wie z. B. das Hinzufügen zusätzlicher optionaler Eingaben, werden abwärtskompatibel vorgenommen, so dass sie keine Änderungen an bestehenden Plugins erfordern.\n",
        "\n",
        "<Admonition type=\"note\" title=\"Anmerkung\">\n",
        "  Alle Methoden mit dem Präfix `supports_` sind für eine abgeleitete Klasse `UnitarySynthesisPlugin` als Teil der Schnittstelle reserviert. Sie sollten keine benutzerdefinierten `supports_*` Methoden in einer Unterklasse definieren, die nicht in der abstrakten Klasse definiert sind.\n",
        "</Admonition>\n",
        "\n",
        "Jetzt machen wir das Plugin bekannt, indem wir einen Eintragspunkt in den Metadaten unseres Python -Pakets hinzufügen.\n",
        "Hier nehmen wir an, dass die Klasse, die wir definiert haben, in einem Modul namens `my_qiskit_plugin` exponiert ist, z. B. indem sie in der Datei `__init__.py` des Moduls `my_qiskit_plugin` importiert wird.\n",
        "Wir bearbeiten die Datei `pyproject.toml`, `setup.cfg`, oder `setup.py` unseres Pakets:\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",
        "Wenn Ihr Projekt `setup.cfg` oder `setup.py` anstelle von `pyproject.toml` verwendet, lesen Sie in der [setuptools-Dokumentation](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) nach, wie Sie diese Zeilen für Ihre Situation anpassen können.\n",
        "\n",
        "Um zu überprüfen, ob Ihr Plugin erfolgreich von Qiskit erkannt wird, installieren Sie Ihr Plugin-Paket und folgen Sie den Anweisungen unter [Transpiler-Plugins](transpiler-plugins#list-available-unitary-synthesis-plugins) für die Auflistung der installierten Plugins und stellen Sie sicher, dass Ihr Plugin in der Liste erscheint:\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": [
        "Wenn unser Beispiel-Plugin installiert wäre, würde der Name `my_unitary_synthesis` in dieser Liste erscheinen.\n",
        "\n",
        "Um einheitliche Synthese-Plugins zu ermöglichen, die mehrere Optionen bereitstellen, hat die Plugin-Schnittstelle eine Option, mit der die Benutzer ein Freiform konfigurationswörterbuch bereitzustellen. Dieser wird an die Methode `run` übergeben über das Schlüsselwortargument `options` übergeben. Wenn Ihr Plugin über diese Konfigurationsoptionen verfügt, sollten Sie sie klar dokumentieren.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "651c863d-41d9-41f4-a133-b392dae2f363",
      "metadata": {},
      "source": [
        "<span id=\"example-create-a-high-level-synthesis-plugin\" />\n",
        "\n",
        "## Beispiel: Erstellen Sie ein Plugin für die High-Level-Synthese\n",
        "\n",
        "In diesem Beispiel werden wir ein High-Level-Synthese-Plugin erstellen, das einfach die eingebaute Funktion [synth\\_clifford\\_bm](/docs/api/qiskit/synthesis#synth_clifford_bm) verwendet, um einen Clifford-Operator zu synthetisieren.\n",
        "\n",
        "Die Klasse [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) klasse definiert die Schnittstelle und den Vertrag für High-Level-Synthese-Plugins. Die wichtigste Methode ist [`run`](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin#run).\n",
        "Das Positionsargument `high_level_object` ist eine [Operation](/docs/api/qiskit/qiskit.circuit.Operation), die das zu synthetisierende \"High-Level\"-Objekt darstellt. Es könnte sich zum Beispiel um eine [LinearFunction](/docs/api/qiskit/qiskit.circuit.library.LinearFunction) oder ein [Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford).\n",
        "Die folgenden Schlüsselwortargumente sind vorhanden:\n",
        "\n",
        "* `target` spezifiziert das Ziel-Backend, so dass das Plugin auf alle zielspezifischen Informationen zugreifen kann, wie z. B. die Kopplungskarte, das unterstützte Gate-Set usw\n",
        "* `coupling_map` gibt nur die Kopplungskarte an und wird nur verwendet, wenn `target` nicht angegeben ist.\n",
        "* `qubits` gibt die Liste der Qubits an, über die das high-Level-Objekt definiert ist, falls die Synthese auf der physischen Schaltung durchgeführt wird.\n",
        "  Ein Wert von `None` bedeutet, dass das Layout noch nicht ausgewählt wurde und die physikalischen Qubits in der Ziel- oder Kopplungskarte, auf der diese Operation ausgeführt wird, noch nicht bestimmt wurden.\n",
        "* `options`, ein freies Konfigurationswörterbuch für Plugin-spezifische Optionen. Wenn Ihr Plugin diese Konfigurationsoptionen hat, sollten Sie sollten Sie diese klar dokumentieren.\n",
        "\n",
        "Die Methode `run` gibt eine [QuantumCircuit](/docs/api/qiskit/qiskit.circuit.QuantumCircuit) zurück, das die aus diesem High-Level-Objekt synthetisierte Schaltung darstellt.\n",
        "Es ist auch erlaubt, `None` zurückzugeben, was bedeutet, dass das Plugin nicht in der Lage ist, das angegebene High-Level-Objekt zu synthetisieren.\n",
        "Die eigentliche Synthese von High-Level-Objekten wird von der [HighLevelSynthesis](/docs/api/qiskit/qiskit.transpiler.passes.HighLevelSynthesis) transpiler-Durchgang.\n",
        "\n",
        "Neben der Methode `run` gibt es noch eine Reihe von Eigenschaftsmethoden, die definiert werden müssen.\n",
        "Siehe [HighLevelSynthesisPlugin](/docs/api/qiskit/qiskit.transpiler.passes.synthesis.plugin.HighLevelSynthesisPlugin) finden Sie eine Dokumentation aller erforderlichen Eigenschaften.\n",
        "\n",
        "Definieren wir unsere Unterklasse 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": [
        "Dieses Plugin synthetisiert Objekte vom Typ [Clifford](/docs/api/qiskit/qiskit.quantum_info.Clifford), die höchstens 3 Qubits haben, unter Verwendung der Methode `synth_clifford_bm` .\n",
        "\n",
        "Jetzt machen wir das Plugin bekannt, indem wir einen Eintragspunkt in den Metadaten unseres Python -Pakets hinzufügen.\n",
        "Hier nehmen wir an, dass die Klasse, die wir definiert haben, in einem Modul namens `my_qiskit_plugin` exponiert ist, z. B. indem sie in der Datei `__init__.py` des Moduls `my_qiskit_plugin` importiert wird.\n",
        "Wir bearbeiten die Datei `pyproject.toml`, `setup.cfg`, oder `setup.py` unseres Pakets:\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",
        "Die Website `name` besteht aus zwei Teilen, die durch einen Punkt getrennt sind (`.`):\n",
        "\n",
        "* Der Name des Typs der [Operation](/docs/api/qiskit/qiskit.circuit.Operation), die das Plugin synthetisiert (in diesem Fall `clifford`). Beachten Sie, dass diese Zeichenkette mit dem [`name`](/docs/api/qiskit/qiskit.circuit.Operation#name) attribut der Klasse Operation entspricht, und nicht dem Namen der Klasse selbst.\n",
        "* Der Name des Plugins (in diesem Fall: `special`).\n",
        "\n",
        "Wenn Ihr Projekt `setup.cfg` oder `setup.py` anstelle von `pyproject.toml` verwendet, lesen Sie in der [setuptools-Dokumentation](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) nach, wie Sie diese Zeilen für Ihre Situation anpassen können.\n",
        "\n",
        "Um zu überprüfen, ob Ihr Plugin erfolgreich von Qiskit erkannt wird, installieren Sie Ihr Plugin-Paket und folgen Sie den Anweisungen unter [Transpiler-Plugins](transpiler-plugins#list-available-high-level-synthesis-plugins) für die Auflistung der installierten Plugins und stellen Sie sicher, dass Ihr Plugin in der Liste erscheint:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "fbe1f265",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['rb_default', 'ag', 'bm', 'default', 'greedy', 'layers', 'lnn']"
            ]
          },
          "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": [
        "Wenn unser Beispiel-Plugin installiert wäre, würde der Name `my_clifford_synthesis` in dieser Liste erscheinen.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a48c2d0b-c402-4b83-ae2e-42c33fe1720e",
      "metadata": {},
      "source": [
        "<Admonition type=\"tip\" title=\"Empfehlung\">\n",
        "  * [Senden Sie Ihr Plugin an das Qiskit Ecosystem!](https://github.com/Qiskit/ecosystem?tab=readme-ov-file#how-to-join)\n",
        "  * In den [Tutorien](/docs/tutorials) finden Sie Beispiele für die Transpilierung und den Betrieb von Quantenschaltungen.\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
}