{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "33f4bb3c",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Schaltkreistiming visualisieren\"\n",
        "description: \"Stellen Sie den zeitlichen Ablauf der generierten Schaltkreise dar, indem Sie eine Abbildung erstellen, die Sie anzeigen, herunterladen oder beides tun können.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore mactex, backgroundcolor, lightgreen */}\n",
        "\n",
        "<span id=\"visualize-circuit-timing\" />\n",
        "\n",
        "# Schaltkreistiming visualisieren\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bfada4f0",
      "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, diese Versionen oder neuere zu verwenden.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.2\n",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ad24e3a0",
      "metadata": {},
      "source": [
        "Der in Qiskit integrierte [Zeitachsen-Drawer](/docs/guides/visualize-circuit-timing) ist zwar für statische Schaltungen nützlich, spiegelt jedoch aufgrund impliziter Operationen wie Broadcasting und Verzweigungsentscheidung möglicherweise nicht genau das Timing [dynamischer Schaltungen](/docs/guides/classical-feedforward-and-control-flow) wider. Im Rahmen der Unterstützung dynamischer Schaltkreise liefert der „ IBM Quantum -Compute-Service“ auf Anfrage genaue Zeitangaben zu den Schaltkreisen in den Auftragsergebnissen.\n",
        "\n",
        "<Admonition type=\"note\" title=\"Hinweise\">\n",
        "  * Dies ist eine experimentelle Funktion. Es handelt sich um eine Vorabversion, die sich daher noch ändern kann.\n",
        "  * Diese Funktion gilt nur für Sampler-Aufträge unter IBM Quantum.\n",
        "  * Obwohl die Gesamtlaufzeit in den „Compilation“-Metadaten angegeben wird, handelt es sich dabei NICHT um die für die Abrechnung herangezogene Zeit (QPU-Zeit).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "995a99e8",
      "metadata": {},
      "source": [
        "<span id=\"enable-timing-data-retrieval\" />\n",
        "\n",
        "### Abruf von Zeitdaten aktivieren\n",
        "\n",
        "Um das Abrufen von Zeitdaten zu ermöglichen, setzen Sie beim Ausführen des Primitive-Jobs `True` das experimentelle `scheduler_timing` Flag auf.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "ab8c6c23",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "qc = QuantumCircuit(2)\n",
        "qc.h(0)\n",
        "qc.cx(0, 1)\n",
        "qc.measure_all()\n",
        "\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "isa_circuit = pm.run(qc)\n",
        "\n",
        "sampler = SamplerV2(backend)\n",
        "sampler.options.experimental = {\n",
        "    \"execution\": {\n",
        "        \"scheduler_timing\": True,\n",
        "    },\n",
        "}\n",
        "\n",
        "sampler_job = sampler.run([isa_circuit])\n",
        "result = sampler_job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "531b2abd",
      "metadata": {},
      "source": [
        "<span id=\"access-the-circuit-timing-data\" />\n",
        "\n",
        "### Auf die Zeitmessdaten der Rennstrecke zugreifen\n",
        "\n",
        "Auf Anfrage werden die Schaltungslaufzeitdaten für jeden „ PUB “ in den Metadaten des Auftragsergebnisses unter `[\"compilation\"][\"scheduler_timing\"][\"timing\"]`\\[…] zurückgegeben. Dieses Feld enthält die Rohdaten zur Zeitmessung. Um die Zeitangaben anzuzeigen, verwenden Sie das integrierte Visualisierungstool, wie im Abschnitt [„Zeitangaben visualisieren“](#visualize-timings) beschrieben.\n",
        "\n",
        "Verwenden Sie den folgenden Code, um auf die Zeitdaten der ersten Runde von „ PUB “ zuzugreifen:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "b6958d99",
      "metadata": {},
      "outputs": [],
      "source": [
        "job_result = sampler_job.result()\n",
        "circuit_schedule = job_result[0].metadata[\"compilation\"][\"scheduler_timing\"]\n",
        "circuit_schedule_timing = circuit_schedule[\"timing\"]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "20400401",
      "metadata": {},
      "source": [
        "<span id=\"understand-the-raw-timing-data\" />\n",
        "\n",
        "#### Die Rohdaten zum Zeitablauf verstehen\n",
        "\n",
        "Zwar ist die Visualisierung der Schaltungszeitdaten mithilfe dieser `draw_circuit_schedule_timing` Methode der häufigste Anwendungsfall, doch kann es hilfreich sein, die Struktur der zurückgegebenen Rohzeitdaten zu verstehen. Das könnte Ihnen beispielsweise dabei helfen, Informationen programmgesteuert zu extrahieren.\n",
        "\n",
        "Die in `[\"compilation\"][\"scheduler_timing\"][\"timing\"]` zurückgegebenen Zeitdaten sind eine Liste von Zeichenfolgen. Jede Zeichenfolge steht für einen einzelnen Befehl auf einem Kanal und ist durch Kommas in die folgenden Datentypen unterteilt:\n",
        "\n",
        "* `Branch` - Bestimmt, ob sich die Anweisung in einem Kontrollfluss (then / else) oder in einem Hauptzweig befindet.\n",
        "* `Instruction` - Das Gatter und das Qubit, auf das es angewendet werden soll.\n",
        "* `Channel` - Der Kanal, dem der Befehl zugewiesen wird. Dabei kann es sich um Folgendes handeln:\n",
        "  * `Qubit x` - Der Ansteuerungskanal für das Qubit *x*.\n",
        "  * `AWGRx_y` (Anzeige des Arbiträrsignalgenerators) – Wird von den Auslesekanälen zur Kommunikation bei der Messung von Qubits verwendet. Die Argumente *„x“* und *„y“* entsprechen der ID des Auslesegeräts bzw. der Qubit-Nummer.\n",
        "* `T0` - Der Beginn des Unterrichts innerhalb des Gesamtplans\n",
        "* `Duration` - Die Dauer der Anweisung in Einheiten von *dt* Sekunden, wobei 1 dt = 1 Scheduling-Zyklus. Den `dt` Wert eines Backends kannst du mithilfe von [`backend.dt`](/docs/api/qiskit/qiskit.providers.BackendV2#dt)ermitteln.\n",
        "* `Pulse` - Die Art des verwendeten Impulsbetriebs.\n",
        "\n",
        "Beispiel:\n",
        "\n",
        "```python\n",
        "main,barrier,Qubit 0,7,0,barrier # A barrier on the main branch on qubit 0 at time 7 with 0 duration\n",
        "main,reset_0,Qubit 0,7,64,play # A reset instruction on the main branch on qubit 0 at time 7 with duration 64 and a play operation\n",
        "...\n",
        "```\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9d34100f",
      "metadata": {},
      "source": [
        "<span id=\"visualize-timings\" />\n",
        "\n",
        "<span id=\"visualize-the-timings\" />\n",
        "\n",
        "### Stellen Sie sich die Zeitabläufe vor\n",
        "\n",
        "Mit „ `qiskit-ibm-runtime`v0.43.0 “ oder einer neueren Version können Sie Schaltungsabläufe visualisieren. Um die Zeitangaben darzustellen, müssen Sie zunächst die Metadaten des Ergebnisses mithilfe der Funktion `fig` in [`draw_circuit_schedule_timing` Methode](https://github.com/Qiskit/qiskit-ibm-runtime/blob/3d1bf1e1d49e5123841639fce259859c90ce9314/qiskit_ibm_runtime/visualization/draw_circuit_schedule_timings.py#L26)konvertieren. Diese Methode gibt eine `plotly` Abbildung zurück, die Sie direkt anzeigen, in einer Datei speichern oder beides tun können.  Weitere Informationen zu den zu `plotly` verwendenden Befehlen finden Sie unter [`fig.show()`](https://plotly.com/python-api-reference/generated/plotly.io.show.html) und [`fig.write_image(\"<path.format>\")`](https://plotly.com/python-api-reference/generated/plotly.io.write_image.html).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "4ad3acfb",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.visualization import draw_circuit_schedule_timing\n",
        "\n",
        "# Create a figure from the metadata\n",
        "fig = draw_circuit_schedule_timing(\n",
        "    circuit_schedule=circuit_schedule_timing,\n",
        "    included_channels=None,\n",
        "    filter_readout_channels=False,\n",
        "    filter_barriers=False,\n",
        "    width=1000,\n",
        ")\n",
        "\n",
        "# Uncomment the following line to display the figure\n",
        "# fig.show(renderer=\"notebook\")\n",
        "\n",
        "# Save to a file\n",
        "# fig.write_html(\"scheduler_timing.html\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2788e992",
      "metadata": {},
      "source": [
        "![Wenn man mit der Maus über die Ausgabe fährt, werden Informationen wie Start, Ende und Dauer angezeigt.](https://quantum.cloud.ibm.com/docs/images/guides/visualize-circuit-timing/image_1.avif \" Beispiel für eine generierte Abbildung\")\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "323a7d38",
      "metadata": {},
      "source": [
        "<span id=\"understand-the-generated-figure\" />\n",
        "\n",
        "#### Die erstellte Abbildung verstehen\n",
        "\n",
        "Das Bild der von ausgegebenen `draw_circuit_schedule_timing` Schaltungszeitdaten enthält folgende Informationen:\n",
        "\n",
        "* Die X-Achse stellt die Zeit in Einheiten von *dt* Sekunden dar, wobei 1 dt = 1 Planungszyklus. Den `dt` Wert eines Backends kannst du mithilfe von [`backend.dt`](/docs/api/qiskit/qiskit.providers.BackendV2#dt)ermitteln.\n",
        "* Die Y-Achse stellt den Kanal dar (stellen Sie sich Kanäle als Instrumente vor, die Impulse aussenden).\n",
        "  * `Receive channel` - Der einzige Kanal, der kein eigenständiges Instrument ist. Es handelt sich um einen Befehl, der auf allen Kanälen gesendet wird, die zu diesem Zeitpunkt an einem Kommunikationsvorgang mit dem Hub beteiligt sind.\n",
        "  * `Qubit x` - Der Ansteuerungskanal für das Qubit x.\n",
        "  * `AWGRx_y` (Anzeige des Arbiträrsignalgenerators) – Wird von den Auslesekanälen zur Kommunikation bei der Messung von Qubits verwendet. Die Argumente *„x“* und *„y“* entsprechen der ID des Auslesegeräts bzw. der Qubit-Nummer.\n",
        "  * `Hub` - Steuert die Übertragung.\n",
        "\n",
        "Zudem hat jeder Befehl das Format *X\\_Y*, wobei *X* für den Namen des Befehls und *Y* für die Impulsart steht. Ein `play` Typ gibt Steuerimpulse ab, und ein anderer `capture` zeichnet den Zustand des Qubits auf. Sie können auch mit der Maus über die einzelnen Anweisungen fahren, um weitere Informationen anzuzeigen. Die vorangegangene Abbildung zeigt beispielsweise einen Steuerimpuls für das X-Gatter, der bei 1161 dt an das Qubit 10 angelegt wird.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "86af09ca",
      "metadata": {},
      "source": [
        "<span id=\"end-to-end-example\" />\n",
        "\n",
        "### End-to-End-Bespiel\n",
        "\n",
        "Dieses Beispiel zeigt Ihnen, wie Sie die Option aktivieren, die Schaltungszeitinformationen aus den Metadaten abrufen und als Bild anzeigen können.\n",
        "\n",
        "Richten Sie zunächst die Umgebung ein, definieren Sie die Schaltungen und konvertieren Sie diese in ISA-Schaltungen; anschließend definieren und starten Sie die Jobs.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "b46908a0",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>>  Job ID:    dab83qbvpcac73ddf510 (DONE)\n"
          ]
        }
      ],
      "source": [
        "from qiskit_ibm_runtime import SamplerV2, QiskitRuntimeService\n",
        "from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "# Create a dynamic circuit\n",
        "\n",
        "qubits = QuantumRegister(1)\n",
        "clbits = ClassicalRegister(1)\n",
        "qc = QuantumCircuit(qubits, clbits)\n",
        "(q0,) = qubits\n",
        "(c0,) = clbits\n",
        "\n",
        "qc.h(q0)\n",
        "qc.measure(q0, c0)\n",
        "with qc.if_test((c0, 1)):\n",
        "    qc.x(q0)\n",
        "qc.measure(q0, c0)\n",
        "\n",
        "# Convert to an ISA circuit for the given backend\n",
        "\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "isa_circuit = pm.run(qc)\n",
        "\n",
        "# Generate samplers for backend targets\n",
        "sampler = SamplerV2(backend)\n",
        "sampler.options.experimental = {\"execution\": {\"scheduler_timing\": True}}\n",
        "\n",
        "# Submit jobs\n",
        "sampler_job = sampler.run([isa_circuit])\n",
        "result = sampler_job.result()\n",
        "\n",
        "print(\n",
        "    f\">>> {' Job ID:':<10}  {sampler_job.job_id()} ({sampler_job.status()})\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1bd5993c",
      "metadata": {},
      "source": [
        "Als Nächstes rufst du den Zeitplan der Rennstrecke ab:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "7e943812",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'main,rz_0,Qubit 0,1393,0,shift_phase\\nmain,sx_0,Qubit 0,1393,9,play\\nmain,sx_0,Qubit 0,1397,0,shift_phase\\nmain,rz_0,Qubit 0,1402,0,shift_phase\\nmain,barrier,Qubit 0,1402,0,barrier\\nmain,measure_0,Qubit 0,1402,64,play\\nmain,measure_0,Qubit 0,1466,108,play\\nmain,measure_0,AWGR0_0,1523,325,capture\\nmain,measure_0,Qubit 0,1574,64,play\\nmain,measure_0,Qubit 0,1638,64,play\\nmain,barrier,Qubit 0,2049,0,barrier\\nmain,broadcast,Hub,1523,526,broadcast\\nmain,receive,Receive,2049,7,receive\\nthen,x_0,Qubit 0,2064,9,play\\nmain,barrier,Qubit 0,2082,0,barrier\\nmain,measure_0,Qubit 0,2082,64,play\\nmain,measure_0,Qubit 0,2146,108,play\\nmain,measure_0,AWGR0_0,2203,325,capture\\nmain,measure_0,Qubit 0,2254,64,play\\nmain,measure_0,Qubit 0,2318,64,play\\nmain,barrier,Qubit 0,2753,0,barrier\\nmain,barrier,Qubit 0,2753,0,barrier\\nmain,FINI_0,Qubit 0,2753,64,play\\nmain,FINI_0,Qubit 0,2817,108,play\\nmain,FINI_0,AWGR0_0,2874,325,capture\\nmain,FINI_0,Qubit 0,2925,64,play\\nmain,FINI_0,Qubit 0,2989,64,play\\nmain,FINI_0,Qubit 0,3424,9,play\\nmain,FINI_0,Qubit 0,3433,64,play\\nmain,FINI_0,Qubit 0,3497,108,play\\nmain,FINI_0,AWGR0_0,3554,325,capture\\nmain,FINI_0,Qubit 0,3605,64,play\\nmain,FINI_0,Qubit 0,3669,64,play\\nmain,FINI_0,Qubit 0,4104,9,play\\nmain,barrier,Qubit 0,4113,0,barrier\\n'"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Get the circuit schedule timing\n",
        "result[0].metadata[\"compilation\"][\"scheduler_timing\"][\"timing\"]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "04db1f41",
      "metadata": {},
      "source": [
        "Zuletzt kannst du den Zeitablauf anzeigen und speichern:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "9d1901c3",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.visualization import draw_circuit_schedule_timing\n",
        "\n",
        "circuit_schedule = result[0].metadata[\"compilation\"][\"scheduler_timing\"][\n",
        "    \"timing\"\n",
        "]\n",
        "fig = draw_circuit_schedule_timing(\n",
        "    circuit_schedule=circuit_schedule,\n",
        "    included_channels=None,\n",
        "    filter_readout_channels=False,\n",
        "    filter_barriers=False,\n",
        "    width=1000,\n",
        ")\n",
        "\n",
        "# Uncomment the following line to display the figure\n",
        "# fig.show(renderer=\"notebook\")\n",
        "\n",
        "# Save to a file\n",
        "# fig.write_html(\"scheduler_timing.html\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9daa7cf7",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Nächste Schritte\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Empfehlungen\">\n",
        "  * [Klassische Vorwärtsregelung und Regelkreis](/docs/guides/classical-feedforward-and-control-flow) (dynamische Schaltungen)\n",
        "  * [Schaltkreise visualisieren](/docs/guides/visualize-circuits)\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
}