{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b793601b-95bc-4d36-adfc-c9fc34ce45cd",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Transpiler-Stufen\"\n",
        "description: \"Die Standardphasen der Transpilation-Pipeline für Quantenschaltungen in Qiskit.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore fontsize */}\n",
        "\n",
        "<span id=\"transpiler-stages\" />\n",
        "\n",
        "# Transpiler-Stufen\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4a38c84a-eed2-4fa4-9823-3d544e572398",
      "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": "9f2ecc4b-e6a3-418c-8a65-a9f3ac98c3dc",
      "metadata": {},
      "source": [
        "Diese Seite beschreibt die Stufen der vorgefertigten Transpilierungspipeline im Qiskit SDK. Es gibt sechs Stufen:\n",
        "\n",
        "1. `init`\n",
        "2. `layout`\n",
        "3. `routing`\n",
        "4. `translation`\n",
        "5. `optimization`\n",
        "6. `scheduling`\n",
        "\n",
        "Die Funktion [`generate_preset_pass_manager`](/docs/api/qiskit/qiskit.transpiler.generate_preset_pass_manager#qiskit.transpiler.generate_preset_pass_manager) funktion erstellt einen voreingestellten [gestuften Durchlaufmanager](/docs/api/qiskit/qiskit.transpiler.StagedPassManager), der aus diesen Stufen besteht. Die spezifischen Durchläufe, aus denen die einzelnen Stufen bestehen, hängen von den Argumenten ab, die an `generate_preset_pass_manager` übergeben werden. `optimization_level` ist ein Positionsargument, das angegeben werden muss; es ist eine ganze Zahl, die 0, 1, 2 oder 3 sein kann. Höhere Werte deuten auf eine stärkere, aber kostspieligere Optimierung hin (siehe [Transpilationsvorgaben und Konfigurationsoptionen](defaults-and-configuration-options) ).\n",
        "\n",
        "Es wird empfohlen, einen Schaltkreis zu transpilieren, indem Sie einen voreingestellten gestaffelten Passmanager erstellen und diesen dann auf dem Schaltkreis ausführen, wie in [Transpilieren mit Passmanagern](transpile-with-pass-managers) beschrieben. Eine einfachere, aber weniger anpassbare Alternative ist jedoch die Verwendung der [`transpile`](/docs/api/qiskit/compiler#qiskit.compiler.transpile) funktion. Diese Funktion nimmt den Stromkreis direkt als Argument an. Wie bei `generate_preset_pass_manager` hängt es von den Argumenten ab, die an `transpile` übergeben werden, z. B. `optimization_level`, welche Transpilerpässe verwendet werden. Die Funktion `transpile` ruft intern `generate_preset_pass_manager` auf, um einen voreingestellten, gestaffelten Durchlaufmanager zu erstellen, und führt ihn auf dem Schaltkreis aus.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "18140654-10ff-40c5-ab75-4d19b8a7f5dd",
      "metadata": {},
      "source": [
        "<span id=\"init-stage\" />\n",
        "\n",
        "## Init-Phase\n",
        "\n",
        "Diese erste Stufe tut standardmäßig sehr wenig und ist vor allem dann nützlich, wenn Sie Ihre eigenen anfänglichen Optimierungen vornehmen wollen.  Da die meisten Layout- und Routing-Algorithmen nur für Ein- und Zwei-Qubit-Gatter ausgelegt sind, werden in dieser Phase auch alle Gatter, die mit mehr als zwei Qubits arbeiten, in Gatter übersetzt, die nur mit einem oder zwei Qubits arbeiten.\n",
        "\n",
        "Weitere Informationen zur Implementierung Ihrer eigenen anfänglichen Optimierungen für diese Phase finden Sie im Abschnitt über Plugins und die Anpassung von Pass-Managern.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "506a831f-b317-4335-8124-20ed994292cd",
      "metadata": {},
      "source": [
        "<span id=\"layout-stage\" />\n",
        "\n",
        "## Layoutphase\n",
        "\n",
        "Der nächste Schritt betrifft den Aufbau bzw. die Anbindung des Backends, an das eine Schaltung gesendet wird.  Im Allgemeinen sind Quantenschaltungen abstrakte Einheiten, deren Qubits „virtuelle“ oder „logische“ Darstellungen der tatsächlichen Qubits sind, die bei Berechnungen verwendet werden.  Um eine Folge von Operationen auszuführen, ist eine Eins-zu-Eins-Zuordnung zwischen den „virtuellen“ Qubits und den „physikalischen“ Qubits in einem tatsächlichen Quantenbauelement erforderlich.  Diese Zuordnung wird als Objekt `Layout` gespeichert und ist Teil der Einschränkungen, die in [der Befehlssatzarchitektur (ISA)](/docs/guides/transpile#instruction-set-architecture) eines Backends definiert sind.\n",
        "\n",
        "![Dieses Bild veranschaulicht die Abbildung von Qubits von der Drahtdarstellung auf ein Diagramm, das zeigt, wie die Qubits auf der QPU miteinander verbunden sind.](https://quantum.cloud.ibm.com/docs/images/guides/transpiler-stages/layout-mapping.svg \"Qubit-Abbildung\")\n",
        "\n",
        "Die Wahl des Mappings ist äußerst wichtig, um die Anzahl der SWAP-Operationen zu minimieren, die für die Abbildung der Eingangsschaltung auf die Gerätetopologie erforderlich sind, und um sicherzustellen, dass die am besten kalibrierten Qubits verwendet werden.  Aufgrund der Bedeutung dieser Phase probieren die Manager für die Vorgabe des Passes verschiedene Methoden aus, um das beste Layout zu finden.  In der Regel umfasst dies zwei Schritte: Zunächst wird versucht, ein \"perfektes\" Layout zu finden (ein Layout, das keine SWAP-Operationen erfordert), und dann wird in einem heuristischen Durchgang versucht, das beste Layout zu finden, das zu verwenden ist, wenn kein perfektes Layout gefunden werden kann.  Für diesen ersten Schritt werden in der Regel zwei `Passes` verwendet:\n",
        "\n",
        "* `TrivialLayout`: Ordnet jedes virtuelle Qubit naiv dem gleich nummerierten physischen Qubit auf dem Gerät zu (d. h. \\[`0`,`1`,`1`,`3`] -> \\[`0`,`1`,`1`,`3`] ). Dies ist ein historisches Verhalten, das nur in `optimzation_level=1` um zu versuchen, ein perfektes Layout zu finden.  Gelingt dies nicht, wird als nächstes `VF2Layout` versucht.\n",
        "* `VF2Layout`: Dies ist eine `AnalysisPass` , die ein ideales Layout auswählt, indem sie diese Phase als ein Untergraphen-Isomorphismus-Problem behandelt, das durch den VF2++ Algorithmus gelöst wird.  Wenn mehr als ein Layout gefunden wird, wird eine Bewertungsheuristik durchgeführt, um die Abbildung mit dem geringsten durchschnittlichen Fehler auszuwählen.\n",
        "\n",
        "Für die heuristische Phase werden dann standardmäßig zwei Durchgänge verwendet:\n",
        "\n",
        "* `DenseLayout`: Findet den Untergraphen des Geräts mit der größten Konnektivität und der gleichen Anzahl von Qubits wie die Schaltung (wird für die Optimierungsstufe 1 verwendet, wenn in der Schaltung Kontrollflussoperationen (wie IfElseOp ) vorhanden sind).\n",
        "* `SabreLayout`Dieser Durchlauf wählt ein Layout aus, indem er von einem anfänglichen zufälligen Layout ausgeht und den `SabreSwap` Algorithmus wiederholt ausführt.  Dieser Durchlauf wird nur in den Optimierungsstufen 1, 2 und 3 verwendet, wenn über den `VF2Layout` Durchlauf kein perfektes Layout gefunden wurde.  Weitere Einzelheiten zu diesem Algorithmus finden Sie in dem Artikel „ [arXiv:1809.02573](https://arxiv.org/abs/1809.02573) ” (Ein Algorithmus zur Ermittlung der optimalen Anzahl von Schichten für die Schichtung von Schichten).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cf772b6c-2578-455d-8014-9a7de2f9db19",
      "metadata": {},
      "source": [
        "<span id=\"routing-stage\" />\n",
        "\n",
        "## Routing-Phase\n",
        "\n",
        "Um ein Zwei-Qubit-Gatter zwischen Qubits zu implementieren, die auf einem Quantenbauelement nicht direkt verbunden sind, müssen ein oder mehrere SWAP-Gatter in die Schaltung eingefügt werden, um die Qubit-Zustände zu verschieben, bis sie auf der Gatterkarte des Bauelements nebeneinander liegen.  Jedes SWAP-Gatter ist ein teurer und geräuschvoller Vorgang, der durchgeführt werden muss.  Daher ist die Ermittlung der Mindestanzahl von SWAP-Gattern, die erforderlich sind, um eine Schaltung auf ein bestimmtes Bauelement abzubilden, ein wichtiger Schritt im Transpilationsprozess.  Aus Gründen der Effizienz wird diese Stufe normalerweise zusammen mit der Layout-Stufe berechnet, aber sie sind logisch voneinander getrennt.  Die *Layout-Stufe* wählt die zu verwendenden Hardware-Qubits aus, während die *Routing-Stufe* die entsprechende Anzahl von SWAP-Gattern einfügt, um die Schaltungen mit dem gewählten Layout auszuführen.\n",
        "\n",
        "Es ist jedoch schwierig, die optimale SWAP-Zuordnung zu finden.  Tatsächlich handelt es sich um ein NP-schweres Problem, dessen Berechnung für alle außer den kleinsten Quantengeräten und Eingabeschaltungen unerschwinglich ist.  Um dies zu umgehen, verwendet Qiskit einen stochastischen heuristischen Algorithmus namens `SabreSwap` , um eine gute, aber nicht unbedingt optimale SWAP-Zuordnung zu berechnen. Die Verwendung einer stochastischen Methode bedeutet, dass die erzeugten Schaltkreise bei wiederholten Durchläufen nicht garantiert dieselben sind.  Die wiederholte Ausführung derselben Schaltung führt zu einer Verteilung der Schaltungstiefen und der Anzahl der Gatter am Ausgang.  Aus diesem Grund entscheiden sich viele Benutzer dafür, die Routing-Funktion (oder die gesamte `StagedPassManager`) mehrmals auszuführen und die Schaltungen mit der geringsten Tiefe aus der Verteilung der Ausgänge auszuwählen.\n",
        "\n",
        "Nehmen wir zum Beispiel eine 15-Qubit-GHZ-Schaltung, die 100-mal ausgeführt wird, und zwar mit einer \"schlechten\" (nicht angeschlossenen) `initial_layout`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "62479697-cef1-4a89-ac2a-20051dd294f4",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "Text(0, 0.5, 'Counts')"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/62479697-cef1-4a89-ac2a-20051dd294f4-1.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit.providers.fake_provider import GenericBackendV2\n",
        "\n",
        "backend = GenericBackendV2(15)\n",
        "\n",
        "\n",
        "ghz = QuantumCircuit(15)\n",
        "ghz.h(0)\n",
        "ghz.cx(0, range(1, 15))\n",
        "\n",
        "depths = []\n",
        "for seed in range(100):\n",
        "    pass_manager = generate_preset_pass_manager(\n",
        "        optimization_level=1,\n",
        "        backend=backend,\n",
        "        layout_method=\"trivial\",  # Fixed layout mapped in circuit order\n",
        "        seed_transpiler=seed,  # For reproducible results\n",
        "    )\n",
        "    depths.append(pass_manager.run(ghz).depth())\n",
        "\n",
        "plt.figure(figsize=(8, 6))\n",
        "plt.hist(depths, align=\"left\", color=\"#AC557C\")\n",
        "plt.xlabel(\"Depth\", fontsize=14)\n",
        "plt.ylabel(\"Counts\", fontsize=14)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ff31f484-a816-4479-8827-d56641501319",
      "metadata": {},
      "source": [
        "Diese breite Streuung zeigt, wie schwierig es für den SWAP-Mapper ist, das beste Mapping zu berechnen.  Um einen Einblick zu bekommen, sollten wir uns sowohl die Schaltung, die ausgeführt wird, als auch die Qubits, die auf der Hardware gewählt wurden, ansehen.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "ab89c4ea-06c4-4320-b493-feb691b3570d",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/ab89c4ea-06c4-4320-b493-feb691b3570d-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ghz.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "f6a3a92a-8656-4518-ba2c-c3b0b038f507",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/f6a3a92a-8656-4518-ba2c-c3b0b038f507-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import plot_circuit_layout\n",
        "\n",
        "# Plot the hardware graph and indicate which hardware qubits were chosen to run the circuit\n",
        "transpiled_circ = pass_manager.run(ghz)\n",
        "plot_circuit_layout(transpiled_circ, backend)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0ec2818a-8087-42ba-990d-b3c1258dbf35",
      "metadata": {},
      "source": [
        "Wie Sie sehen, muss diese Schaltung ein Zwei-Qubit-Gatter zwischen den Qubits 0 und 14 ausführen, die auf dem Konnektivitätsgraphen sehr weit voneinander entfernt sind.  Die Ausführung dieser Schaltung erfordert daher das Einfügen von SWAP-Gattern, um alle Zwei-Qubit-Gatter unter Verwendung des `SabreSwap` -Durchgangs auszuführen.\n",
        "\n",
        "Beachten Sie auch, dass sich der Algorithmus `SabreSwap` von der größeren Methode `SabreLayout` in der vorherigen Phase unterscheidet.  Standardmäßig führt `SabreLayout` sowohl das Layout als auch das Routing aus und gibt die transformierte Schaltung zurück.  Dies geschieht aus einigen besonderen technischen Gründen, die auf der [API-Referenzseite](../api/qiskit/qiskit.transpiler.passes.SabreLayout) des Passes aufgeführt sind.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "650f978b-d992-4d67-a356-5bf73902f212",
      "metadata": {},
      "source": [
        "<span id=\"translation-stage\" />\n",
        "\n",
        "## Übersetzungsphase\n",
        "\n",
        "Beim Schreiben eines Quantenschaltkreises können Sie beliebige Quanten-Gatter (unitäre Operationen) verwenden, zusammen mit einer Reihe von Operationen, die keine Gatter sind, wie beispielsweise Qubit-Messungen oder Rücksetzbefehle.  Die meisten Quantenvorrichtungen unterstützen jedoch von Haus aus nur eine Handvoll Quanten- und Nicht-Quantenoperationen.  Diese nativen Gatter sind Teil der Definition der [ISA](/docs/guides/transpile#instruction-set-architecture) eines Ziels, und in dieser Phase der Voreinstellung `PassManagers` werden die in einer Schaltung angegebenen Gatter in die nativen Basisgatter eines bestimmten Backends übersetzt (oder *entrollt* ).  Dies ist ein wichtiger Schritt, da dadurch die Schaltung vom Backend ausgeführt werden kann, führt jedoch in der Regel zu einer Zunahme der Schaltungstiefe und der Anzahl der Logikgatter.\n",
        "\n",
        "Zwei Sonderfälle sind besonders hervorzuheben, um zu verdeutlichen, was diese Phase bewirkt.\n",
        "\n",
        "1. Wenn ein SWAP-Gate kein natives Gate für das Ziel-Backend ist, sind drei CNOT-Gates erforderlich:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "d4d1f65a-3336-4d70-9189-65ba010f2366",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "native gates:['cx', 'delay', 'id', 'measure', 'reset', 'rz', 'sx', 'x']\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/d4d1f65a-3336-4d70-9189-65ba010f2366-1.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "print(\"native gates:\" + str(sorted(backend.operation_names)))\n",
        "qc = QuantumCircuit(2)\n",
        "qc.swap(0, 1)\n",
        "qc.decompose().draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "56347603-8766-4165-af18-1f6fe4c61d4f",
      "metadata": {},
      "source": [
        "Als Produkt von drei CNOT-Gattern ist ein SWAP eine teure Operation, die auf verrauschten Quantengeräten durchgeführt werden muss.  Solche Operationen sind jedoch in der Regel notwendig, um eine Schaltung in die begrenzten Gate-Verbindungen vieler Bauelemente einzubetten.  Daher ist die Minimierung der Anzahl von SWAP-Gattern in einer Schaltung ein Hauptziel des Transpilationsprozesses.\n",
        "\n",
        "2. Ein Toffoli-Gatter oder kontrolliert-kontrolliert-nicht-Gatter (`ccx`) ist ein Drei-Qubit-Gatter.  Da unsere Basisgattermenge nur Ein- und Zwei-Qubit-Gatter umfasst, muss diese Operation zerlegt werden.  Sie ist jedoch recht kostspielig:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "4552b367-75e9-4faa-a59d-8317e25ac145",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/4552b367-75e9-4faa-a59d-8317e25ac145-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(3)\n",
        "qc.ccx(0, 1, 2)\n",
        "qc.decompose().draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "70af8d85-84c2-43cf-96fa-37bcf68f89c9",
      "metadata": {},
      "source": [
        "Für jedes Toffoli-Gatter in einer Quantenschaltung kann die Hardware bis zu sechs CNOT-Gatter und eine Handvoll Ein-Qubit-Gatter ausführen.  Dieses Beispiel zeigt, dass jeder Algorithmus, der mehrere Toffoli-Gatter verwendet, in einer Schaltung mit großer Tiefe endet und daher erheblich durch Rauschen beeinträchtigt wird.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8b396526-b14b-48a3-93ed-37e590b06caf",
      "metadata": {},
      "source": [
        "<span id=\"optimization-stage\" />\n",
        "\n",
        "## Optimierungsphase\n",
        "\n",
        "In dieser Phase geht es um die Zerlegung von Quantenschaltungen in den Basis-Gate-Satz des Zielbauelements und um den Kampf gegen die erhöhte Tiefe der Layout- und Routing-Phasen.  Glücklicherweise gibt es viele Routinen zur Optimierung von Schaltungen durch Kombination oder Eliminierung von Gattern.  In einigen Fällen sind diese Methoden so effektiv, dass die Ausgangsschaltungen eine geringere Tiefe haben als die Eingänge, selbst nach dem Layout und dem Routing zur Hardwaretopologie.  In anderen Fällen kann nicht viel getan werden, und die Berechnungen können auf lauten Geräten schwierig durchzuführen sein.  In dieser Phase beginnen sich die verschiedenen Optimierungsstufen zu unterscheiden.\n",
        "\n",
        "* Für `optimization_level=1` bereitet diese Phase die [`Optimize1qGatesDecomposition`](../api/qiskit/qiskit.transpiler.passes.Optimize1qGatesDecomposition) und [`CXCancellation`](/docs/api/qiskit/1.4/qiskit.transpiler.passes.CXCancellation)vor, die Ketten von Ein-Qubit-Gattern kombinieren und alle hintereinander geschalteten CNOT-Gatter aufheben.\n",
        "* Für `optimization_level=2` verwendet diese Stufe den [`CommutativeCancellation`](../api/qiskit/qiskit.transpiler.passes.CommutativeCancellation) durchgang anstelle von `CXCancellation`, der überflüssige Gatter durch Ausnutzung von Kommutierungsbeziehungen entfernt.\n",
        "* Für `optimization_level=3` bereitet diese Phase die folgenden Durchgänge vor:\n",
        "  * [`Collect2qBlocks`](../api/qiskit/qiskit.transpiler.passes.Collect2qBlocks)\n",
        "  * [`ConsolidateBlocks`](../api/qiskit/qiskit.transpiler.passes.ConsolidateBlocks)\n",
        "  * [`UnitarySynthesis`](../api/qiskit/qiskit.transpiler.passes.UnitarySynthesis)\n",
        "  * [`Optimize1qGateDecomposition`](../api/qiskit/qiskit.transpiler.passes.Optimize1qGatesDecomposition)\n",
        "  * [`CommutativeCancellation`](../api/qiskit/qiskit.transpiler.passes.CommutativeCancellation)\n",
        "\n",
        "Außerdem werden in dieser Phase noch einige abschließende Prüfungen durchgeführt, um sicherzustellen, dass alle Anweisungen in der Schaltung aus den auf dem Ziel-Backend verfügbaren Basisgattern bestehen.\n",
        "\n",
        "Das folgende Beispiel mit einem GHZ-Zustand zeigt die Auswirkungen verschiedener Optimierungseinstellungen auf die Schaltungstiefe und die Anzahl der Gatter.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Die Transpilationsleistung variiert aufgrund des stochastischen SWAP-Mappers. Daher werden sich die Zahlen unten wahrscheinlich jedes Mal ändern, wenn Sie den Code ausführen.\n",
        "</Admonition>\n",
        "\n",
        "![15-qubit GHZ-Zustand](https://quantum.cloud.ibm.com/docs/images/guides/transpiler-stages/transpiler-11.avif \"15-qubit GHZ-Zustand vor der Transpilierung\")\n",
        "\n",
        "Der folgende Code konstruiert einen 15-Qubit-GHZ-Zustand und vergleicht die `optimization_levels` der Transpilierung in Bezug auf die resultierende Schaltungstiefe, die Anzahl der Gatter und die Anzahl der Multi-QuBit-Gatter.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "2700405a-f559-45d3-99a9-5b4447621743",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/2700405a-f559-45d3-99a9-5b4447621743-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "ghz = QuantumCircuit(15)\n",
        "ghz.h(0)\n",
        "ghz.cx(0, range(1, 15))\n",
        "\n",
        "depths = []\n",
        "gate_counts = []\n",
        "multiqubit_gate_counts = []\n",
        "levels = [str(x) for x in range(4)]\n",
        "for level in range(4):\n",
        "    pass_manager = generate_preset_pass_manager(\n",
        "        optimization_level=level,\n",
        "        backend=backend,\n",
        "        seed_transpiler=1234,\n",
        "    )\n",
        "    circ = pass_manager.run(ghz)\n",
        "    depths.append(circ.depth())\n",
        "    gate_counts.append(sum(circ.count_ops().values()))\n",
        "    multiqubit_gate_counts.append(circ.count_ops()[\"cx\"])\n",
        "\n",
        "fig, (ax1, ax2) = plt.subplots(2, 1)\n",
        "ax1.bar(levels, depths, label=\"Depth\")\n",
        "ax1.set_xlabel(\"Optimization Level\")\n",
        "ax1.set_ylabel(\"Depth\")\n",
        "ax1.set_title(\"Output Circuit Depth\")\n",
        "ax2.bar(levels, gate_counts, label=\"Number of Circuit Operations\")\n",
        "ax2.bar(levels, multiqubit_gate_counts, label=\"Number of CX gates\")\n",
        "ax2.set_xlabel(\"Optimization Level\")\n",
        "ax2.set_ylabel(\"Number of gates\")\n",
        "ax2.legend()\n",
        "ax2.set_title(\"Number of output circuit gates\")\n",
        "fig.tight_layout()\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c870a48f-2bc4-4150-83ff-857a06e42ffb",
      "metadata": {},
      "source": [
        "<span id=\"scheduling\" />\n",
        "\n",
        "## Zeitplanung\n",
        "\n",
        "Diese letzte Phase wird nur ausgeführt, wenn sie ausdrücklich gefordert wird (ähnlich wie die Init-Phase), und wird nicht standardmäßig ausgeführt (obwohl eine Methode angegeben werden kann, indem das Argument `scheduling_method` beim Aufruf von `generate_preset_pass_manager` gesetzt wird).  Die Scheduling-Phase wird in der Regel eingesetzt, nachdem die Schaltung in die Zielbasis übersetzt, auf das Gerät abgebildet und optimiert wurde.  Bei diesen Durchläufen geht es darum, die gesamte Leerlaufzeit in einem Stromkreis zu berücksichtigen.  Auf einer hohen Ebene kann man sich den Scheduling-Durchlauf so vorstellen, dass explizit Verzögerungsanweisungen eingefügt werden, um die Leerlaufzeit zwischen den Gatterausführungen zu berücksichtigen und zu prüfen, wie lange die Schaltung auf dem Backend laufen wird.\n",
        "\n",
        "Beispiel:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "ae2d9390-5c26-46f3-9418-a684ba8a406a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/transpiler-stages/extracted-outputs/ae2d9390-5c26-46f3-9418-a684ba8a406a-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ghz = QuantumCircuit(5)\n",
        "ghz.h(0)\n",
        "ghz.cx(0, range(1, 5))\n",
        "\n",
        "\n",
        "# Use fake backend\n",
        "backend = GenericBackendV2(5)\n",
        "\n",
        "# Run with optimization level 3 and 'asap' scheduling pass\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=3,\n",
        "    backend=backend,\n",
        "    scheduling_method=\"asap\",\n",
        "    seed_transpiler=1234,\n",
        ")\n",
        "\n",
        "\n",
        "circ = pass_manager.run(ghz)\n",
        "circ.draw(output=\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "442cb546-3463-4044-8406-1c68d371a2c9",
      "metadata": {},
      "source": [
        "![Schaltung mit Verzögerungsanweisungen](https://quantum.cloud.ibm.com/docs/images/guides/transpiler-stages/transpiler-16.avif)\n",
        "\n",
        "Der Transpiler fügte `Delay` Anweisungen ein, um die Leerlaufzeit auf jedem Qubit zu berücksichtigen. Um eine bessere Vorstellung vom Timing der Schaltung zu bekommen, können wir sie auch mit der Funktion `timeline.draw()` betrachten:\n",
        "\n",
        "![timeline.draw -Ansicht derselben Schaltung](https://quantum.cloud.ibm.com/docs/images/guides/transpiler-stages/transpiler-17.svg)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0b214bba-1f0e-49fc-be7e-29ccb57fff8a",
      "metadata": {},
      "source": [
        "Die Planung eines Schaltkreises besteht aus zwei Teilen: der Analyse und der Zuordnung von Einschränkungen, gefolgt von einem Auffüllungsdurchgang.  Der erste Teil erfordert die Ausführung eines Zeitplan-Analysedurchlaufs (standardmäßig ist dies [`ALAPSchedulingAnalysis`](../api/qiskit/qiskit.transpiler.passes.ALAPScheduleAnalysis)), der die Schaltung analysiert und die Startzeit jeder Anweisung in der Schaltung in einem Zeitplan aufzeichnet.  Sobald der Schaltkreis einen anfänglichen Zeitplan hat, können zusätzliche Durchläufe durchgeführt werden, um etwaige zeitliche Beschränkungen des Ziel-Backends zu berücksichtigen.  Schließlich wird ein Auffüllungspassus wie [`PadDelay`](../api/qiskit/qiskit.transpiler.passes.PadDelay) oder [`PadDynamicalDecoupling`](../api/qiskit/qiskit.transpiler.passes.PadDynamicalDecoupling) ausgeführt werden.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "62c19c54-6dcc-4025-b800-7a74be69808d",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Nächste Schritte\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Empfehlungen\">\n",
        "  * Wenn Sie wissen möchten, wie Sie die Funktion `generate_preset_passmanager` verwenden, beginnen Sie mit dem Thema [Transpilations-Standardeinstellungen und Konfigurationsoptionen](defaults-and-configuration-options).\n",
        "  * Erfahren Sie mehr über die Transpilierung mit dem Thema [„Transpiler mit Passmanagern“](transpile-with-pass-managers).\n",
        "  * Probieren Sie die Anleitung [zum Vergleichen der Transpiler-Einstellungen](/docs/guides/circuit-transpilation-settings) aus.\n",
        "  * Siehe die [Transpile-API-Dokumentation](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": {
    "celltoolbar": "Raw Cell Format",
    "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"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "state": {},
        "version_major": 2,
        "version_minor": 0
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}