{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "cdc8dc1e-0cff-46c1-94d0-97456d278e27",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Schreiben Sie Ihr erstes Programm „ Qiskit Serverless “\"\n",
        "description: \"So erstellen Sie ein paralleles Transpilierungsprogramm und stellen es auf IBM Quantum Platform bereit, um es als wiederverwendbaren Remote-Dienst zu verwenden.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore mypath  */}\n",
        "\n",
        "<span id=\"write-your-first-qiskit-serverless-program\" />\n",
        "\n",
        "# Schreiben Sie Ihr erstes Programm „ Qiskit Serverless “\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b6d632cb-d884-4963-9c8d-8f3a3acd8a7d",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "<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]~=1.3.1\n",
        "    qiskit-ibm-runtime~=0.34.0\n",
        "    qiskit-aer~=0.15.1\n",
        "    qiskit-serverless~=0.27.0\n",
        "    qiskit-ibm-catalog~=0.2\n",
        "    qiskit-addon-sqd~=0.8.1\n",
        "    qiskit-addon-utils~=0.1.0\n",
        "    qiskit-addon-mpf~=0.2.0\n",
        "    qiskit-addon-aqc-tensor~=0.1.2\n",
        "    qiskit-addon-obp~=0.1.0\n",
        "    scipy~=1.15.0\n",
        "    pyscf~=2.8.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1cc46aeb-aff6-4fab-9d78-69f2bfe98d98",
      "metadata": {},
      "source": [
        "<Admonition type=\"tip\">\n",
        "  **Qiskit Serverless wird aktualisiert, und seine Funktionen ändern sich schnell.** Während dieser Entwicklungsphase finden Sie Release Notes und die aktuellste Dokumentation auf der Seite „[ Qiskit Serverless](https://qiskit.github.io/qiskit-serverless/index.html) “ () unter GitHub.\n",
        "</Admonition>\n",
        "\n",
        "Dieses Beispiel zeigt, wie Sie mithilfe `qiskit-serverless` von Tools ein Programm zur parallelen Transpilierung erstellen und dieses anschließend auf IBM Quantum Platform hochladen können, um `qiskit-ibm-catalog` es als wiederverwendbaren Remote-Dienst zu nutzen.\n",
        "\n",
        "<span id=\"workflow-overview\" />\n",
        "\n",
        "## Übersicht über den Arbeitsablauf\n",
        "\n",
        "1. Erstelle ein lokales Verzeichnis und leere die Programmdatei (`./source_files/transpile_remote.py`)\n",
        "2. Füge deinem Programm Code hinzu, der beim Hochladen auf Qiskit Serverless eine Schaltung transpiliert\n",
        "3. Verwenden Sie `qiskit-ibm-catalog` zur Authentifizierung bei Qiskit Serverless\n",
        "4. Laden Sie das Programm auf Qiskit Serverless hoch\n",
        "\n",
        "Nachdem Sie Ihr Programm hochgeladen haben, können Sie es ausführen, um die Schaltung zu transpilieren, indem Sie der Anleitung [„Run your first Qiskit Serverless workload remotely“](/docs/guides/serverless-run-first-workload) folgen.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cad16f43-8548-4849-a4b8-09059a8b747c",
      "metadata": {},
      "source": [
        "<span id=\"example-remote-transpilation-with-qiskit-serverless\" />\n",
        "\n",
        "## Beispiel: Remote-Transpilation mit Qiskit Serverless\n",
        "\n",
        "Dieses Beispiel führt Sie durch die Erstellung und Ergänzung einer Programmdatei, die, sobald Sie sie auf Qiskit Serverless hochladen, ein `circuit` gegenüber einem vorgegebenen `backend` und einer Zielplattform `optimization_level`transpiliert.\n",
        "\n",
        "<Admonition type=\"tip\">\n",
        "  Qiskit Serverless erfordert das Einrichten der `.py` Dateien Ihrer Workloads in einem speziellen Verzeichnis. Die folgende Struktur ist ein Beispiel für eine gute Praxis:\n",
        "\n",
        "  ```text\n",
        "  serverless_program\n",
        "  ├── program_uploader.ipynb\n",
        "  └── source_files\n",
        "      ├── transpile_remote.py\n",
        "      └── *.py\n",
        "  ```\n",
        "</Admonition>\n",
        "\n",
        "Serverless lädt den Inhalt eines bestimmten Verzeichnisses (in diesem Beispiel das `source_files` Verzeichnis) hoch, um es remote auszuführen. Sobald diese eingerichtet sind, können Sie die Einstellungen anpassen, `transpile_remote.py` um Eingaben abzurufen und Ausgaben zurückzugeben.\n",
        "\n",
        "<span id=\"create-the-directory-and-an-empty-program-file\" />\n",
        "\n",
        "### Erstellen Sie das Verzeichnis und eine leere Programmdatei\n",
        "\n",
        "Erstellen Sie zunächst ein Verzeichnis mit dem Namen `source_files`, und legen Sie dann eine Programmdatei in diesem Verzeichnis an, sodass ihr Pfad lautet `./source_files/transpile_remote.py`. Dies ist die Datei, die Sie auf Qiskit Serverless hochladen werden.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a9b3fb7d-abd6-4a3e-b9b1-b21202d8db6d",
      "metadata": {},
      "source": [
        "<span id=\"add-code-to-your-program-file\" />\n",
        "\n",
        "### Füge Code zu deiner Programmdatei hinzu\n",
        "\n",
        "Fügen Sie den folgenden Code in Ihre Programmdatei ein und speichern Sie sie anschließend.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Wenn Sie die Codezellen lokal in einem Notizbuch ausführen, wird der `%%writefile` [magische Befehl](https://ipython.readthedocs.io/en/stable/interactive/magics.html#cellmagic-writefile) angezeigt. Wenn man Zellen mit diesem magischen Befehl ausführt, werden sie auf der Festplatte gespeichert, anstatt ausgeführt zu werden.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "214eb803-d1fa-4ac0-b955-8b24717086f4",
      "metadata": {},
      "outputs": [],
      "source": [
        "# This cell is hidden from users, it creates a new folder\n",
        "from pathlib import Path\n",
        "\n",
        "Path(\"./source_files\").mkdir(exist_ok=True)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "64722041-22ed-42bd-8d83-d8e9f5e5b55b",
      "metadata": {
        "editable": true,
        "slideshow": {
          "slide_type": ""
        },
        "tags": []
      },
      "outputs": [],
      "source": [
        "%%writefile ./source_files/transpile_remote.py\n",
        "# If you include the preceding `%%writefile` command (visible only when you read this\n",
        "# locally in a notebook), running this cell saves to disk rather than executing the code.\n",
        "\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "def transpile_remote(circuit, optimization_level, backend):\n",
        "    \"\"\"Transpiles an abstract circuit into an ISA circuit for a given backend.\"\"\"\n",
        "    pass_manager = generate_preset_pass_manager(\n",
        "        optimization_level=optimization_level,\n",
        "\t\tbackend=backend\n",
        "    )\n",
        "    isa_circuit = pass_manager.run(circuit)\n",
        "    return isa_circuit"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7e80b5bb-0f76-43d1-a68c-97b4b22cc88a",
      "metadata": {},
      "source": [
        "<span id=\"add-code-to-get-program-arguments\" />\n",
        "\n",
        "### Code hinzufügen, um Programmargumente abzurufen\n",
        "\n",
        "Füge nun den folgenden Code in deine Programmdatei ein, der die Programmargumente einrichtet.\n",
        "\n",
        "Ihr ursprüngliches `transpile_remote.py` hat drei Eingänge: `circuits`, `backend_name`, und `optimization_level`. Serverless ist derzeit darauf beschränkt, nur serialisierbare Ein- und Ausgaben zu akzeptieren. Aus diesem Grund können Sie `backend` nicht direkt eingeben, sondern müssen stattdessen `backend_name` als String verwenden.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "6819379b-d7b2-4fda-9e6b-459eec748a79",
      "metadata": {},
      "outputs": [],
      "source": [
        "%%writefile --append ./source_files/transpile_remote.py\n",
        "# If you include the preceding `%%writefile` command (visible only when you read this\n",
        "# locally in a notebook), running this cell saves to disk rather than executing the code.\n",
        "\n",
        "from qiskit_serverless import get_arguments, save_result, distribute_task, get\n",
        "\n",
        "# Get program arguments\n",
        "arguments = get_arguments()\n",
        "circuits = arguments.get(\"circuits\")\n",
        "backend_name = arguments.get(\"backend_name\")\n",
        "optimization_level = arguments.get(\"optimization_level\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5ae9fb12-f06f-4f7d-8f37-1d872285deab",
      "metadata": {},
      "source": [
        "<span id=\"add-code-that-calls-the-backend\" />\n",
        "\n",
        "### Füge Code hinzu, der das Backend aufruft\n",
        "\n",
        "Fügen Sie den folgenden Code in Ihre Programmdatei ein. Dieser ruft einen Laufzeitservice ab und nutzt ihn zur Auswahl Ihres Backends.\n",
        "\n",
        "<Admonition type=\"note\" title=\"Verwenden Sie „get_runtime_service“ in Programmen unter „ Qiskit Serverless “\">\n",
        "  Erstellen Sie im Code, der auf Qiskit Serverless ausgeführt wird, Ihren Laufzeitdienst mit `get_runtime_service()` (importiert aus `qiskit_serverless`) anstelle einer direkten `QiskitRuntimeService()` Instanziierung von.\n",
        "\n",
        "  `get_runtime_service()` Gibt einen Drop-in-Wrapper zurück, der `QiskitRuntimeService` jeden von IBM Quantum gestarteten Primitivjob und jede Sitzung beim übergeordneten Job Qiskit Serverless registriert. Über diese Verknüpfung kann die Plattform einen serverlosen Job mit den von ihm erzeugten QPU-Jobs und -Sitzungen verknüpfen, um den Status zu verfolgen, Protokolle zu erstellen sowie die Nutzung und Abrechnung zu erfassen. Ein „bare“ übermittelt `QiskitRuntimeService` Aufträge, die die Plattform niemals mit Ihrem Serverless-Auftrag verknüpft, sodass diese Verknüpfung verloren geht.\n",
        "\n",
        "  Alle Argumente sind optional. Im Programmquellcode wird die Form `get_runtime_service()` ohne Argumente empfohlen, da dabei Ihre Authentifizierungsdaten aus der Umgebung abgerufen werden. Sie akzeptiert dieselben optionalen Argumente `url` `channel`, `token`, `instance`, und wie `QiskitRuntimeService`.\n",
        "</Admonition>\n",
        "\n",
        "Der folgende Code geht davon aus, dass Sie die Anweisungen zum Speichern Ihrer Anmeldedaten bereits befolgt haben und lädt Ihr standardmäßig gespeichertes Konto `QiskitRuntimeService.save_account`, sofern Sie nichts anderes angeben. Weitere Informationen finden Sie unter [„Speichern Sie Ihre Anmeldedaten“](/docs/guides/save-credentials) und „[Initialisieren Sie Ihr IBM Quantum Compute Service-Konto](/docs/guides/initialize-account) “.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "4b0c7d24-9b87-4e00-bb1d-f82aa967cb1d",
      "metadata": {},
      "outputs": [],
      "source": [
        "%%writefile --append ./source_files/transpile_remote.py\n",
        "# If you include the preceding `%%writefile` command (visible only when you read this\n",
        "# locally in a notebook), running this cell saves to disk rather than executing the code.\n",
        "\n",
        "from qiskit_serverless import get_runtime_service\n",
        "\n",
        "service = get_runtime_service()\n",
        "backend = service.backend(backend_name)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "61e7cb3b-6d62-4b68-817a-39c0c1d95a9b",
      "metadata": {},
      "source": [
        "<span id=\"add-code-to-transpile\" />\n",
        "\n",
        "### Code zum Transpilen hinzufügen\n",
        "\n",
        "Fügen Sie abschließend den folgenden Code in Ihre Programmdatei ein. Dieser Code durchläuft alle `circuits``transpile_remote()` übergebenen Werte und gibt das `transpiled_circuits` Ergebnis zurück:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "041e7f85-e9e8-424d-8694-d54316225cc4",
      "metadata": {},
      "outputs": [],
      "source": [
        "%%writefile --append ./source_files/transpile_remote.py\n",
        "# If you include the preceding `%%writefile` command (visible only when you read this\n",
        "# locally in a notebook), running this cell saves to disk rather than executing the code.\n",
        "\n",
        "# Each circuit is being transpiled and will populate the array\n",
        "results = [\n",
        "    transpile_remote(circuit, 1, backend)\n",
        "    for circuit in circuits\n",
        "]\n",
        "\n",
        "save_result({\n",
        "    \"transpiled_circuits\": results\n",
        "})"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dac118ab-e447-4ddd-a5f8-d13e3953db76",
      "metadata": {},
      "source": [
        "<span id=\"upload-to-qiskit-serverless\" />\n",
        "\n",
        "<span id=\"authenticate-to-qiskit-serverless\" />\n",
        "\n",
        "### Bei Qiskit Serverless anmelden\n",
        "\n",
        "Verwenden Sie `qiskit-ibm-catalog` , um sich bei `QiskitServerless` mit Ihrem API-Schlüssel anzumelden (Sie können Ihren `QiskitRuntimeService` API-Schlüssel verwenden oder einen neuen API-Schlüssel im [IBM Quantum Platform -Dashboard]() erstellen).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "8d1385c3-09a5-42c6-a5bc-53f686d8410e",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_catalog import QiskitServerless, QiskitFunction\n",
        "\n",
        "# Authenticate to the remote cluster and submit the pattern for remote execution\n",
        "serverless = QiskitServerless()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a0f64820-5fb1-41b9-9cb4-5095d0b5db43",
      "metadata": {},
      "source": [
        "<span id=\"run-code-to-upload\" />\n",
        "\n",
        "### Code zum Hochladen ausführen\n",
        "\n",
        "Führe den folgenden Code aus, um das Programm hochzuladen. Qiskit Serverless komprimiert den Inhalt von `working_dir` (in diesem Fall ) `source_files` in eine `tar`, die hochgeladen und anschließend bereinigt wird. Die `entrypoint` gibt die ausführbare Hauptdatei an, die von „ Qiskit Serverless “ ausgeführt werden soll.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "c1cdd46d-71e9-4711-a09b-6eca569ede6a",
      "metadata": {},
      "outputs": [],
      "source": [
        "transpile_remote_demo = QiskitFunction(\n",
        "    title=\"transpile_remote_serverless\",\n",
        "    entrypoint=\"transpile_remote.py\",\n",
        "    working_dir=\"./source_files/\",\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "8b675d04-bde8-4b3d-b9e5-99982ef742e1",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "QiskitFunction(transpile_remote_serverless)"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "serverless.upload(transpile_remote_demo)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3a840c18-3010-4d05-91cb-592e2692c1d7",
      "metadata": {},
      "source": [
        "<span id=\"verify-upload\" />\n",
        "\n",
        "### Upload überprüfen\n",
        "\n",
        "Um zu überprüfen, ob der Upload erfolgreich war, verwenden Sie `serverless.list()`, wie im folgenden Code gezeigt:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "afaa3935-adf7-4b28-a8f0-583a82bbe3f1",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "QiskitFunction(transpile_remote_serverless)"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Get program from serverless.list() that matches the title of the one we uploaded\n",
        "next(\n",
        "    program\n",
        "    for program in serverless.list()\n",
        "    if program.title == \"transpile_remote_serverless\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a416b143-6f70-49dc-ab2f-ad66f042cab1",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Nächste Schritte\n",
        "\n",
        "<Admonition type=\"info\" title=\"Empfehlungen\">\n",
        "  * Erfahren Sie im Abschnitt „[Erste „ Qiskit Serverless “-Workload remote](/docs/guides/serverless-run-first-workload) ausführen“, wie Sie Eingaben übergeben und Ihr Programm remote ausführen können.\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
}