{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "ce3d197d-7b14-4c60-8d39-a202146d0663",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Eingaben und Ausgaben des Executors\"\n",
        "description: \"Machen Sie sich mit den Ein- und Ausgängen der Executor-Primitive vertraut.\"\n",
        "---\n",
        "\n",
        "<span id=\"executor-inputs-and-outputs\" />\n",
        "\n",
        "# Eingaben und Ausgaben des Executors\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "44219323-9419-471a-86c4-488ef0162420",
      "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",
        "    samplomatic~=0.21.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "43c044dc-259d-4759-b6a7-a05bd9d3667f",
      "metadata": {},
      "source": [
        "Die Executor-Primitive ist Teil des [gerichteten Ausführungsmodells](/docs/guides/directed-execution-model), das mehr Flexibilität bei der Anpassung eines Workflows zur Fehlerbehebung bietet.\n",
        "\n",
        "Die Ein- und Ausgänge der Executor-Primitive unterscheiden sich erheblich von denen der [Sampler-](/docs/guides/sampler-input-output) und [Estimator](/docs/guides/estimator-input-output) -Primitive. `QuantumProgram`Anstatt beispielsweise eine Liste von PUBs als Eingabe zu verwenden, nimmt Executor ein Objekt entgegen, das eine Liste von `QuantumProgramItem` Objekten enthält. Diese Containerklassen bieten Ihnen mehr Flexibilität als ein „ PUB “, bei dem es sich um eine einfache Tupel-Datenstruktur handelt.\n",
        "\n",
        "`QuantumProgramItem`Die Ausgabe von `executor` ist ein `QuantumProgramResult``Iterable`, der für jede Eingabe ein Element enthält.\n",
        "\n",
        "<span id=\"programs\" />\n",
        "\n",
        "<span id=\"inputs-quantum-programs\" />\n",
        "\n",
        "## Eingaben: Quantum-Programme\n",
        "\n",
        "Wie bereits erwähnt, ist die Eingabe für eine Executor-Primitive ein [`QuantumProgram`](/docs/api/qiskit-ibm-runtime/quantum-program-quantum-program), bei dem es sich um eine iterierbare Sammlung von\n",
        "[`QuantumProgramItem`](/docs/api/qiskit-ibm-runtime/quantum-program-quantum-program-item) Objekten handelt.  Es gibt zwei Arten dieser Objekte:\n",
        "\n",
        "* `CircuitItem`, in der in der Regel eine Schaltung und ihre Parameterwerte (sofern vorhanden) gespeichert sind.\n",
        "* `SamplexItem`, in der in der Regel Folgendes gespeichert wird:\n",
        "  * Eine Schaltungsvorlage\n",
        "  * Ein Samplex-Objekt, das dazu dient, zur Laufzeit zufällige Parametersätze zu generieren (beispielsweise um Twirling durchzuführen oder Rauschen einzuspielen)\n",
        "  * Argumente für den Samplex, die Parameterwerte für die ursprüngliche Schaltung enthalten können\n",
        "\n",
        "Jeder dieser Punkte stellt eine andere Aufgabe dar, die der Testamentsvollstrecker zu erledigen hat.\n",
        "\n",
        "<span id=\"before-you-begin\" />\n",
        "\n",
        "### Vorbereitende Schritte\n",
        "\n",
        "Einige der Code-Beispiele auf dieser Seite verwenden `samplex`, das zum Samplomatic-Paket gehört.  Bevor Sie diese Code-Blöcke ausführen, müssen Sie daher Samplomatic installieren, wie im folgenden Code-Block gezeigt.  Weitere Informationen finden Sie in der [Samplomatic-Dokumentation](https://qiskit.github.io/samplomatic).\n",
        "\n",
        "```python\n",
        "pip install samplomatic\n",
        "\n",
        "# For visualization support, include the visualization dependencies.\n",
        "# pip install samplomatic[vis]\n",
        "```\n",
        "\n",
        "<span id=\"example-create-a-quantumprogram-with-two-different-tasks\" />\n",
        "\n",
        "### Beispiel: Erstellen Sie eine `QuantumProgram` mit zwei verschiedenen Aufgaben\n",
        "\n",
        "Initialisieren Sie zunächst Ihr Quantenprogramm und fügen Sie dann Programmelemente hinzu, indem Sie entweder `append_circuit_item` oder `append_samplex_item` verwenden (sofern ein Samplex vorhanden ist), wie in den folgenden Beispielen gezeigt.\n",
        "\n",
        "Die folgende Zelle initialisiert a `QuantumProgram` und legt fest, dass für jede Konfiguration jedes Elements im Programm 1024 Durchläufe ausgeführt werden sollen.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Im Gegensatz zu Sampler nimmt ein `QuantumProgram` nur einen einzigen Wert entgegen. `QuantumProgram`Wenn Sie einen anderen Belichtungswert wünschen, benötigen Sie eine separate Aufnahme, was einen separaten Auftrag darstellen würde.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "81fc7c9e-2cc9-416a-b3d5-74f45eab48fc",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_ibm_runtime.quantum_program import QuantumProgram\n",
        "from qiskit_ibm_runtime import Executor, QiskitRuntimeService\n",
        "from qiskit.circuit import Parameter, QuantumCircuit\n",
        "import numpy as np\n",
        "from samplomatic import build\n",
        "from samplomatic.transpiler import generate_boxing_pass_manager\n",
        "\n",
        "# Initialize an empty program\n",
        "program = QuantumProgram(shots=1024)\n",
        "\n",
        "# Initialize and transpile a 3-qubit quantum circuit with 2 parameters.\n",
        "circuit = QuantumCircuit(3)\n",
        "circuit.h(0)\n",
        "circuit.cx(0, 1)\n",
        "circuit.cx(1, 2)\n",
        "circuit.rz(Parameter(\"theta\"), 0)\n",
        "circuit.rz(Parameter(\"phi\"), 1)\n",
        "\n",
        "# `measure_all` adds a 3-bit classical register named \"meas\"\n",
        "circuit.measure_all()\n",
        "\n",
        "# Choose the least busy backend\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "# Generate a preset pass manager\n",
        "# This will be used to convert the abstract circuit to an\n",
        "# equivalent Instruction Set Architecture (ISA) circuit.\n",
        "preset_pass_manager = generate_preset_pass_manager(\n",
        "    backend=backend, optimization_level=0\n",
        ")\n",
        "\n",
        "# Transpile the circuit\n",
        "isa_circuit = preset_pass_manager.run(circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a1cc6580-3f31-4322-b0ea-f6bcf032a872",
      "metadata": {},
      "source": [
        "<span id=\"append-a-circuititem\" />\n",
        "\n",
        "### Anhängen `CircuitItem`\n",
        "\n",
        "Anschließend wird die Zielschaltung, die entsprechend der Befehlssatzarchitektur (ISA) des Backends transpiliert wurde, an die `QuantumProgram`. Da diese Schaltung zwei Parameter hat, müssen wir auch die Parameterwerte angeben (in diesem Beispiel 10 Sätze). Die Ausführung dieses Befehls `CircuitItem` ist die erste Aufgabe, die das Programm ausführt.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "e6f6762f-1627-450a-b74b-96ad4a3b1c9c",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Append the transpiled circuit and an array\n",
        "# containing 10 sets of parameter values to the program\n",
        "program.append_circuit_item(\n",
        "    isa_circuit,\n",
        "    circuit_arguments=np.random.rand(\n",
        "        10, 2\n",
        "    ),  # 10 sets of parameter values and 2 parameters\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "96f9ac43-8ce4-4389-bff4-5bd68b799974",
      "metadata": {},
      "source": [
        "<span id=\"append-a-samplexitem\" />\n",
        "\n",
        "### Anhängen `SamplexItem`\n",
        "\n",
        "Die Elemente der Schleife werden ohne jegliche Zufallsauswahl ausgeführt. Im Gegenteil: Bei Samplex-Elementen können Sie festlegen, wie deren Inhalt zufällig angeordnet werden soll. In der nächsten Zelle werden mithilfe der `generate_boxing_pass_manager()` Funktion die Logikgatter und Messwerte der Schaltung in Kästchen zusammengefasst und jedem Kästchen eine rotierende Beschriftung hinzugefügt. Anschließend generiert es mithilfe der `build()` Funktion eine Schaltungsvorlage und ein Samplex-Paar.\n",
        "\n",
        "Die Ausführung dieser Aufgabe `SamplexItem` ist die zweite Aufgabe, die das Programm ausführt.\n",
        "\n",
        "Ausführliche Informationen zu `samplex` und seinen Argumenten finden Sie in der [Sam](https://github.com/Qiskit/samplomatic/) plomatic-API-Dokumentation. Informationen zur Verwendung der `generate_boxing_pass_manager()` Funktion finden Sie im [Sam](https://qiskit.github.io/samplomatic/guides/transpiler.html) plomatic-Transpiler-Handbuch.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "4ac19f46-226b-4b13-b278-1e39e719484b",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "TensorInterface(<\n",
            "  - 'parameter_values' <float64[2]>: Input parameter values to use during sampling.\n",
            ">)\n"
          ]
        }
      ],
      "source": [
        "# Transpile the circuit, additionally grouping gates and measurements into annotated boxes\n",
        "preset_pass_manager = generate_preset_pass_manager(\n",
        "    backend=backend, optimization_level=0\n",
        ")\n",
        "\n",
        "# Use the boxing pass manager to group gates\n",
        "# and measurements into boxes and add\n",
        "# a`Twirl` annotation.\n",
        "preset_pass_manager.post_scheduling = generate_boxing_pass_manager(\n",
        "    # Add gate twirling\n",
        "    enable_gates=True,\n",
        "    # Add measurement twirling\n",
        "    enable_measures=True,\n",
        ")\n",
        "boxed_circuit = preset_pass_manager.run(circuit)\n",
        "\n",
        "# Build the template circuit and the samplex.  The template circuit has parametric gates\n",
        "# without fixed values and the samplex randomly generates the parameter\n",
        "# values on the server side at runtime to perform twirling.\n",
        "template_circuit, samplex = build(boxed_circuit)\n",
        "\n",
        "# Determine what arguments are required by the samplex.\n",
        "# Input the arguments in samplex_arguments.\n",
        "print(samplex.inputs())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "0e3b4d3d-12ea-47f2-a605-b64eed03cf95",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Append the template circuit and samplex as a samplex item\n",
        "program.append_samplex_item(\n",
        "    template_circuit,\n",
        "    samplex=samplex,\n",
        "    samplex_arguments={\n",
        "        # the arguments required by the samplex.sample method\n",
        "        \"parameter_values\": np.random.rand(10, 2),\n",
        "    },\n",
        "    shape=(28, 10),  # 28 randomizations and 10 sets of parameter values\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "eb850401-3d4f-4fac-8965-fb9ac4827ebd",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Initialize an Executor with the default options\n",
        "executor = Executor(mode=backend)\n",
        "\n",
        "# Submit the job\n",
        "job = executor.run(program)\n",
        "\n",
        "# Retrieve the result\n",
        "result = job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "541f5d2d-b974-4ae5-81e0-ef2b6e1dbe82",
      "metadata": {},
      "source": [
        "<span id=\"outputs\" />\n",
        "\n",
        "## Ausgaben\n",
        "\n",
        "Die Ausgabe von `Executor` ist ein [`QuantumProgramResult`](/docs/api/qiskit-ibm-runtime/results-quantum-program-result), das iterierbar ist. Es enthält einen Eintrag pro Eingabe `QuantumProgramItem` in derselben Reihenfolge wie die Eingabeelemente. Jedes dieser Ausgabeelemente ist ein Wörterbuch, dessen Schlüssel Zeichenfolgen sind, die (unter anderem) den Namen der klassischen Register in den Eingangsschaltungen entsprechen, sodass du dir diese Namen nicht mehr merken musst, wie es beim Sampler-Ausgang der Fall war. Die Werte des Wörterbuchs sind vom Typ `np.ndarray`.\n",
        "\n",
        "Das Ergebnis des vorangegangenen Beispiels enthält folgende Elemente:\n",
        "\n",
        "<span id=\"circuititem-result\" />\n",
        "\n",
        "### `CircuitItem` Ergebnis\n",
        "\n",
        "`CircuitItem`Der erste Eintrag enthält die Ergebnisse der Ausführung der ersten Aufgabe (a) im Programm. Es enthält einen einzigen Schlüssel, `meas`, der den Namen des klassischen Registers in der Eingangsschaltung angibt. `(parameter sets, shots, register bits)`Der Wert dieses Schlüssels wird einem Array `np.ndarray` der Form zugeordnet, die im obigen Beispiel (10, 1024, 3) lautet.\n",
        "\n",
        "Der folgende Code zeigt, wie man auf diese Informationen zugreifen kann:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "d652d69a-7a4e-4e5c-8469-97cb9ec92010",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Result shape: (10, 1024, 3)\n"
          ]
        }
      ],
      "source": [
        "# Access the results of the classical register of task #0, a CircuitItem\n",
        "result_0 = result[0][\"meas\"]\n",
        "print(f\"Result shape: {result_0.shape}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ce5d4f6e-edbc-4278-bf30-1ba5b9da4dc5",
      "metadata": {},
      "source": [
        "Die Achse ganz rechts von `result_0` läuft über klassische Bits in Little-Endian-Reihenfolge. Somit enthält der Index 0 den Wert des klassischen Bits 0, also des niedrigstwertigen Bits.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7185353a-e7a0-4bb2-b605-664184e684ed",
      "metadata": {},
      "source": [
        "<span id=\"samplexitem-result\" />\n",
        "\n",
        "### `SamplexItem` Ergebnis\n",
        "\n",
        "Der zweite Eintrag enthält die Ergebnisse der Ausführung der zweiten Aufgabe (a `SamplexItem`) im Programm. Dieser Eintrag enthält mehrere Schlüssel. Der Schlüssel `meas` , bei dem es sich um den Namen des klassischen Registers der Eingangsschaltung handelt, wird auf das Ergebnisarray dieses Registers abgebildet. Dieses Array hat die Form `(randomizations, parameter sets, shots, classical bits)`, in diesem Beispiel also (28, 10, 1024, 3).\n",
        "\n",
        "Zudem enthält die Ausgabe einen Schlüssel `measurement_flips.meas` , bei dem es sich um die Bit-Flip-Korrekturen handelt, mit denen die Messabweichung für das Register `meas` rückgängig gemacht wird.  In unserem Beispiel ergibt sich daraus die Ausgabestruktur (28, 10, 1, 3), da für die Bitumkehr nur ein Durchlauf erforderlich ist.\n",
        "\n",
        "Beachten Sie, dass die Achse ganz rechts über klassische Bits in Little-Endian-Reihenfolge verläuft `result_1` .\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "884af6e2-614a-4b18-83dc-04505ddbc488",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Result shape: (28, 10, 1024, 3)\n",
            "Bit-flip corrections shape: (28, 10, 1, 3)\n"
          ]
        }
      ],
      "source": [
        "# Access the results of the classical register of task #1\n",
        "result_1 = result[1][\"meas\"]\n",
        "print(f\"Result shape: {result_1.shape}\")\n",
        "\n",
        "# Access the bit-flip corrections\n",
        "flips_1 = result[1][\"measurement_flips.meas\"]\n",
        "print(f\"Bit-flip corrections shape: {flips_1.shape}\")\n",
        "\n",
        "# Undo the bit flips via classical XOR\n",
        "unflipped_result_1 = result_1 ^ flips_1"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bb0c9225-9a52-4d94-b75d-6ae408f4e029",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Nächste Schritte\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Empfehlungen\">\n",
        "  * Entdecken Sie [Beispiele](/docs/guides/executor-examples) für die Verwendung von Executor.\n",
        "  * Erfahren Sie mehr über das [Modell der gerichteten Ausführung](/docs/guides/directed-execution-model).\n",
        "  * Verstehen Sie [die Executor-Übertragung](/docs/guides/executor-broadcasting).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}