{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "e6e50bd6-8ac4-40b1-ac0f-6e22b6af1377",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Simulieren Sie ein gekickt Ising-Modell mit der TEM-Funktion\"\n",
        "description: \"Einführung in TEM, eine Qiskit-Funktion von Algorithmiq, zur Berechnung von Schätzungen mit Software-Nachbearbeitung zur Fehlerminderung unter Verwendung von Tensor-Netzwerken.\"\n",
        "---\n",
        "\n",
        "<span id=\"simulate-a-kicked-ising-model-with-the-tem-function\" />\n",
        "\n",
        "# Simulieren Sie ein gekickt Ising-Modell mit der TEM-Funktion\n",
        "\n",
        "{/* cspell:ignore Floquet, linestyles */}\n",
        "\n",
        "Die Tensor-Network Error Mitigation (TEM)-Methode von Algorithmiq ist ein hybrider quantenklassischer Algorithmus, der für die vollständige Rauschunterdrückung innerhalb der klassischen Nachbearbeitungsphase entwickelt wurde. Mit TEM kann der Benutzer die Erwartungswerte von Observablen berechnen und so die unvermeidlichen rauschbedingten Fehler, die bei Quantenhardware auftreten, mit erhöhter Genauigkeit und Kosteneffizienz mindern, was es zu einer äußerst attraktiven Option für Quantenforscher und Industriepraktiker gleichermaßen macht.\n",
        "\n",
        "Dieses Tutorial zeigt, wie TEM aussagekräftige Ergebnisse für die Dynamik eines Quantensystems erzielen kann, die ohne Fehlerminderung nicht zugänglich wären und die bei Verwendung anderer Fehlerminderungsmethoden wie PEC und ZNE wesentlich mehr Quantenressourcen erfordern würden.\n",
        "\n",
        "*Geschätzte Nutzung: Dieses Notebook verbraucht etwa 10 QPU-Minuten auf Heron- r3 -Geräten. Die Laufzeit kann erheblich vom gewählten Gerät abhängen. Die geschätzten Verbrauchswerte pro Abschnitt finden Sie unten.*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1f5e328d-fe93-4ee2-995b-2e70b36ea0de",
      "metadata": {},
      "source": [
        "<span id=\"run-error-mitigated-many-body-physics-experiments-with-the-tem-function\" />\n",
        "\n",
        "## Führen Sie mit der TEM-Funktion fehlerreduzierte Vielteilchenphysik-Experimente durch\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b63a662c-a4e9-4b5f-92fd-46352a2bd0bd",
      "metadata": {},
      "source": [
        "Dieses Tutorial basiert auf folgender Referenz: [L. E. Fischer et al., Nat. Phys. (2026)](https://www.nature.com/articles/s41567-025-03144-9). Diese Referenz behandelt eine reale Simulation auf Quantenhardware mit bis zu 91 Qubits. In diesem Tutorial erstellen wir eine ähnliche Simulation auf einer kleineren Schaltungsgröße.\n",
        "\n",
        "Das gekickte Ising-Modell entspricht dem üblichen Ising-Modell:\n",
        "\n",
        "$\\hat{H}_{\\text{I}} = J \\sum_{n=0}^{N-2} \\hat{Z}_n \\hat{Z}_{n+1} + h \\sum_{n=0}^{N-1} \\hat{Z}_n$\n",
        "\n",
        "auf den ein Querkick angewendet wird:\n",
        "\n",
        "$\\hat{H}_{K} = b \\sum_{n=0}^{N-1} \\hat{X}_n$\n",
        "\n",
        "Das Ziel besteht darin, die Dynamik eines Zustands unter dem transversalen gekickten Ising-Hamiltonian zu simulieren, dessen zeitliche Entwicklung durch eine Floquet-Unitar $\\hat{U}_{\\text{KI}} = e^{-i \\hat{H}_K} e^{-i \\hat{H}_I} $ implementiert werden kann. Der auszuführende Anfangszustand ist derjenige, in dem sich das erste Qubit im Zustand $|+\\rangle$ befindet, während die anderen gepaart und im Bell-Zustand $(|00\\rangle + |11\\rangle)/\\sqrt{2}$ gesetzt sind.\n",
        "\n",
        "Die Größe, die wir beobachten wollen, ist die Korrelationsfunktion. Das [Referenzpapier](https://www.nature.com/articles/s41567-025-03144-9) erörtert, wie diese Größe als ein Pauli-Operator $\\hat{X}$ auf dem Qubit $n^{th}$ umgeschrieben werden kann.\n",
        "Nach einer Reihe von physikalischen Zeitschritten $t$ berechnen wir den Wert des Pauli-Operators $\\hat{X}_{n=t}$.\n",
        "Abhängig von den Parametern des Systems entspricht der Wert dieser Observablen einem Wert, der entweder exakt berechnet oder nur durch approximative Methoden simuliert werden kann. Konkret entspricht „ $|J|=|b|=\\pi/4$ “ dem Wert „ $[\\cos(2h)]^t$ “, den wir zum Vergleich der Ergebnisse dieses Tutorials verwenden werden. Außerdem ist zu einem bestimmten Zeitschritt $t$, $\\langle\\hat{X}_{n\\neq t}\\rangle$ gleich Null. Einzelheiten zur Ermittlung dieser Werte und zum Vergleich mit ungefähren klassischen Simulationsergebnissen außerhalb dieser Parameter finden Sie [bei L. E. Fischer et al., Nat. Phys. (2026)](https://www.nature.com/articles/s41567-025-03144-9).\n",
        "\n",
        "TEM funktioniert, indem zunächst das Rauschen für jede einzelne Schicht von Zwei-Qubit-Gates im Schaltkreis charakterisiert wird und anschließend der Auslesefehler charakterisiert wird. Anschließend wird der Schaltkreis auf der Quantenmaschine ausgeführt. Schließlich wird die Fehlerminderung des Tensornetzwerks auf den klassischen Ressourcen in „ IBM Cloud® “ durchgeführt und der geminderte Wert zurückgegeben. In diesem Beispiel hat die Schaltung zwei einzigartige Schichten, die charakterisiert werden müssen.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4b30f191-9759-49de-ba8f-7cc616b61ec6",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## Einrichtung\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9cf6d15e-324b-474a-886c-c3dca5a24141",
      "metadata": {},
      "source": [
        "Als Voraussetzung muss sichergestellt werden, dass die erforderlichen Abhängigkeiten installiert sind.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "1eeec332-29ca-4882-8129-d1c93ed82b2b",
      "metadata": {},
      "outputs": [],
      "source": [
        "%pip install numpy matplotlib qiskit qiskit-ibm-catalog qiskit-ibm-runtime pylatexenc qiskit_qasm3_import"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "ad0002b7-dbff-4699-af52-ba0df72ed200",
      "metadata": {},
      "outputs": [],
      "source": [
        "import os\n",
        "from matplotlib import pyplot as plt\n",
        "import numpy as np\n",
        "\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.qasm3 import load\n",
        "\n",
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b95b9e75-37fe-4f86-a923-0a833c7960f8",
      "metadata": {},
      "source": [
        "<span id=\"error-mitigation-with-tem\" />\n",
        "\n",
        "## Fehlerbehebung mit TEM\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "651a3f04-c8ba-4a39-8415-52d7e313ba2a",
      "metadata": {},
      "source": [
        "Wir stellen hier eine Schaltung vor, die das oben beschriebene Kicked-Ising-Modell implementiert. Die Schaltung wird wie folgt vorbereitet. Zunächst gibt es eine Zustandsvorbereitungsphase, in der sich das erste Qubit im Zustand $|+\\rangle$ befindet, während sich die anderen in Bell-Paaren $(|00\\rangle + |11\\rangle)/\\sqrt{2}$ befinden. Darauf folgt die Brickwork-Struktur, die die unitäre Entwicklung $\\hat{U}_{\\text{KI}}$ implementiert. Die Anzahl der physikalischen Zeitschritte entspricht $t/2$ den Schaltungsschichten.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "11e42656-76ba-452c-af22-8f4cd22ff174",
      "metadata": {},
      "source": [
        "Der folgende Code lädt die beiden für dieses Tutorial erforderlichen QASM-Dateien herunter.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "39bf7188-3771-4994-a6c6-e9cfcae3484f",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Download required QASM files\n",
        "import urllib\n",
        "\n",
        "urllib.request.urlretrieve(\n",
        "    \"https://ibm.box.com/shared/static/swy5jtq309b0xpzluzlmsmj908yphes8.qasm\",\n",
        "    \"ki_30q.qasm\",\n",
        ")\n",
        "urllib.request.urlretrieve(\n",
        "    \"https://ibm.box.com/shared/static/et3gkodonw6gsp2trs43lzaozrdtiu7s.qasm\",\n",
        "    \"ki_12q.qasm\",\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1f6f9970-63fb-40f4-9586-261cba23cb88",
      "metadata": {},
      "source": [
        "Wir können uns eine kleine Version des Schaltkreises mit 12 Qubits und sechs Zeitschritten vorstellen:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "381a4e25-bc9c-47d0-b9f1-172eb5516484",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/simulate-kicked-ising-tem/extracted-outputs/381a4e25-bc9c-47d0-b9f1-172eb5516484-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Parameters of the kicked Ising model\n",
        "h = 0.0\n",
        "num_qubits = 12\n",
        "t_steps = 6\n",
        "\n",
        "# Load the circuit for the kicked Ising model\n",
        "small_circuit = load(\"ki_12q.qasm\")\n",
        "\n",
        "# Draw the circuit\n",
        "small_circuit.draw(\"mpl\", scale=0.25, fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a674e407-504d-4812-82bf-98e91ec9a4b4",
      "metadata": {},
      "source": [
        "Als Nächstes erstellen Sie die Beobachtungsgröße „ $\\hat{X}_{n=t}$ “. Diese wird als einfache Pauli-Kette konstruiert, deren Reihenfolge mit der von Qiskit verwendeten übereinstimmt:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "a9a87f6c-176d-4c85-85e5-6751aea0c90b",
      "metadata": {},
      "outputs": [],
      "source": [
        "def xt_observable(n_qubits, t_steps):\n",
        "    pauli_str = \"\".join([\"I\" * t_steps, \"X\", \"I\" * (n_qubits - t_steps - 1)])\n",
        "    pauli_str = pauli_str[::-1]  # Reverse the string to match qiskit order\n",
        "    return SparsePauliOp(data=pauli_str, coeffs=1.0)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ba5f7042-4abd-4ae7-a091-591678377e8f",
      "metadata": {},
      "source": [
        "In unserem kleinen 12-Qubit-Beispiel sieht die Beobachtungsgröße wie folgt aus:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "b2608df1-b4e4-4143-bea5-a65ab8045fd4",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "SparsePauliOp(['IIIIIXIIIIII'],\n",
            "              coeffs=[1.+0.j])\n"
          ]
        }
      ],
      "source": [
        "# Build the observable for the kicked Ising model\n",
        "small_observable = xt_observable(n_qubits=12, t_steps=6)\n",
        "print(small_observable)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e588fafe-8db8-4445-8893-a78190b27b64",
      "metadata": {},
      "source": [
        "Qiskit Functions Verwenden Sie PUBs als Mittel zum Sammeln der Eingaben. In unserem Fall betrachten wir einen einzelnen Schaltkreis und eine Beobachtung als unsere „ PUB “:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "fc48eb54-148b-4b0d-8424-a135cb92039e",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Collect the input PUBs, in this case composed of a\n",
        "# single circuit and observable\n",
        "pubs = [(small_circuit, [small_observable])]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9a4bcd8d-ae21-40ab-b0e2-510236ba92de",
      "metadata": {},
      "source": [
        "Als Nächstes erhalten wir Zugriff auf die TEM-Funktion. Zuerst richten wir die erforderliche Authentifizierung für IBM Cloud ein und wählen ein Backend aus den verfügbaren Geräten aus. Das Token, die verfügbaren Backends und die entsprechenden Cloud-Ressourcennamen (CRN) können Sie erhalten, indem Sie sich bei Ihrem Konto auf dem [Dashboard „ IBM Quantum Platform “](/) anmelden.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "6c9f80a8-4a65-4daa-94bb-a98edd6a1989",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Set IBM Quantum credentials and backend configuration\n",
        "personal_token = os.environ.get(\n",
        "    \"QISKIT_IBM_TOKEN\", \"<API-KEY>\"\n",
        ")  # Replace with your personal token or set the environment variable\n",
        "channel = \"ibm_quantum_platform\"\n",
        "crn = \"your_crn\"  # Replace with the Cloud Resource Name (CRN)\n",
        "\n",
        "# Select the QPU backend\n",
        "backend_name = \"ibm_qpu_name\"  # Replace with your desired backend's name"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "10df1803-5245-42b2-8eea-c0773cd655b6",
      "metadata": {},
      "source": [
        "Laden Sie die TEM-Funktion aus dem „ [Qiskit Functions Catalog](/functions) ” (Verzeichnis der TEM-Funktionen):\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "2473b284-108f-45fe-a8d8-3aed584137f6",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Load the TEM function from the Qiskit Functions Catalog\n",
        "catalog = QiskitFunctionsCatalog(\n",
        "    channel=channel,\n",
        "    token=personal_token,\n",
        "    instance=crn,\n",
        ")\n",
        "tem = catalog.load(\"algorithmiq/tem\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3c732819-4dca-421c-bc2b-45ff5a5912db",
      "metadata": {},
      "source": [
        "Wir können nun ein Experiment mit dem gekickten Ising-Schaltkreis durchführen, wobei TEM für die Fehlerminderung sorgt. Mit den Standardeinstellungen kann TEM auf einfache Weise ausgeführt werden, wobei die erwartete QPU-Laufzeit je nach QPU etwa 2.5 Minuten beträgt:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "b826e025-f36b-4fb5-90bd-e1ef36f5c1b2",
      "metadata": {},
      "outputs": [],
      "source": [
        "tem_job = tem.run(pubs=pubs, backend_name=backend_name)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4b692a80-5a10-4131-9d7f-785fedbe4221",
      "metadata": {},
      "source": [
        "Mit den Standardoptionen führt die TEM-Funktion drei Aufgaben auf dem Quantencomputer aus: Rauschlernen, Auslesungsminderung und Schaltungsabtastung. Die Anzahl der von jedem dieser Elemente verwendeten Schüsse kann in den an die Funktion übergebenen Optionen geändert werden. Standardmäßig sind diese Parameter so eingestellt, dass eine Genauigkeit von 0.05 bei den geminderten Erwartungswerten erreicht wird.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "25b6f313-a928-493e-837f-45e6e7836aef",
      "metadata": {},
      "source": [
        "Sie können den Status Ihres Auftrags auf dem [Dashboard „ IBM Quantum Platform “](/) oder mit folgendem Befehl überprüfen:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "05e202ff-5b86-4a93-a693-86fbb1cf3e02",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QUEUED\n"
          ]
        }
      ],
      "source": [
        "print(tem_job.status())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8e427c75-72fb-4a97-b723-97d695a692d3",
      "metadata": {},
      "source": [
        "Wenn der Status „“ ist `DONE`, können wir die Rohdaten und die gemilderten Ergebnisse überprüfen. Die unten `tem_evs` definierten Werte sind die Erwartungswerte der angeforderten Observablen, in diesem Fall nur eine Observable, $\\langle \\hat X_{n=t}\\rangle$, und `tem_std` sind die entsprechenden Standardabweichungen.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "3ca34069-1363-4e37-9718-91639d817a82",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "TEM Result: 1.031 ± 0.046\n"
          ]
        }
      ],
      "source": [
        "# Get the results of the TEM job\n",
        "tem_results = tem_job.result()[\n",
        "    0\n",
        "]  # Get the first and only result from the job\n",
        "tem_evs = tem_results.data.evs[0]\n",
        "tem_std = tem_results.data.stds[0]\n",
        "\n",
        "print(f\"TEM Result: {tem_evs:.3f} ± {tem_std:.3f}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f90f503e-ab80-4550-a7cf-dfeea12babb0",
      "metadata": {},
      "source": [
        "Wir können auch überprüfen, wie viel Quantenlaufzeit für jeden Aufruf verwendet wurde, und zwar unter [IBM Quantum Platform]() oder durch Überprüfen der Ergebnismetadaten aus dem Code Python.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "b05818d6-b680-483e-9084-f3fd2de067ab",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "TEM Runtime: 155.0 seconds\n"
          ]
        }
      ],
      "source": [
        "# Get the TEM job runtime\n",
        "tem_runtime = tem_job.result().metadata[\"resource_usage\"][\n",
        "    \"RUNNING: EXECUTING_QPU\"\n",
        "][\"QPU_TIME\"]\n",
        "\n",
        "print(f\"TEM Runtime: {tem_runtime} seconds\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6be333a8-41c9-4ba9-b07d-a0ac50149add",
      "metadata": {},
      "source": [
        "<span id=\"customize-tem-parameters-and-advanced-options\" />\n",
        "\n",
        "## TEM-Parameter und erweiterte Optionen anpassen\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "abee6fc2-90d6-4608-ad21-c606c936dd94",
      "metadata": {},
      "source": [
        "Die TEM-Funktion bietet mehrere erweiterte Optionen zur Anpassung Ihres Workflows zur Fehlerbehebung. Mit diesen Optionen können Sie die Genauigkeit, die Anzahl der Schüsse, die Strategien zum Lernen von Rauschen und andere Parameter steuern, um sie besser an die Anforderungen Ihres Experiments und die verfügbaren Quantenressourcen anzupassen.\n",
        "\n",
        "Häufige erweiterte Optionen sind:\n",
        "\n",
        "* **`precision`**: Geben Sie die Zielgenauigkeit für die gemilderten Erwartungswerte an.\n",
        "* \\*\\*`default_shots`\\*\\*Anstelle von können Sie die Anzahl der vom `precision`Messauftrag verwendeten Aufnahmen angeben.\n",
        "* \\*\\*`tem_max_bond_dimension`\\*\\*Die maximale Bindungsdimension, die im Tensornetzwerk verwendet wird.\n",
        "* \\*\\*`tem_compression_cutoff`\\*\\*Der für das Tensornetzwerk zu verwendende Grenzwert.\n",
        "* **Optionen für das Geräuschlernen** : Konfigurieren Sie, wie Geräusche charakterisiert werden, z. B. die Anzahl der Wiederholungen oder bestimmte Kalibrierungsschaltungen.\n",
        "* \\*\\*`private`\\*\\*Stellen Sie sicher, dass Schaltkreise und Versuchsergebnisse für Sie privat bleiben, und deaktivieren Sie mehrere Downloads von Auftragsergebnissen.\n",
        "\n",
        "Eine vollständige Liste der unterstützten Optionen und deren Beschreibungen finden Sie in der [TEM-Dokumentation](/docs/guides/algorithmiq-tem) oder unter [Qiskit Functions Catalog](/functions). Sie können diese Parameter anpassen, um ein Gleichgewicht zwischen Laufzeit, Ressourcenverbrauch und Genauigkeit der Ergebnisse herzustellen.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "24db681c-b306-41e0-8507-626ef279b076",
      "metadata": {},
      "source": [
        "Sie können diese Optionen als Wörterbuch an das `options` Argument übergeben, wenn Sie die TEM-Funktion ausführen:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a2e9a032-91cb-4a18-9a00-00a149e60459",
      "metadata": {},
      "outputs": [],
      "source": [
        "options = {\n",
        "    \"default_shots\": 10_000,\n",
        "    \"tem_max_bond_dimension\": 512,\n",
        "    \"tem_compression_cutoff\": 1e-16,\n",
        "    # This option helps optimizing the measurement\n",
        "    # stage since the observable is strongly biased\n",
        "    # toward the X operator for all the qubits.\n",
        "    \"compute_shadows_bias_from_observable\": True,\n",
        "    # set to True to keep experiment results private,\n",
        "    # recommended for confidential circuits\n",
        "    \"private\": False,\n",
        "}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "db700868-4dae-48c8-be1a-668ef2e63177",
      "metadata": {},
      "source": [
        "Es können auch benutzerdefinierte Optionen für den Noise-Learner übergeben werden. Sie folgen den Definitionen, die im verwendet werden: `qiskit-ibm-runtime`[`NoiseLearnerOptions`](/docs/api/qiskit-ibm-runtime/options-noise-learner-options)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 29,
      "id": "30591014-3bc6-4548-ba0d-dc5cc22e9dcc",
      "metadata": {},
      "outputs": [],
      "source": [
        "nl_options = {\n",
        "    \"num_randomizations\": 32,\n",
        "    \"max_layers_to_learn\": 2,\n",
        "    \"shots_per_randomization\": 128,\n",
        "    \"layer_pair_depths\": [0, 1, 2, 4, 16, 32],\n",
        "}\n",
        "\n",
        "# add noise learning options to the overall options\n",
        "options |= nl_options"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "216ad12c-8c70-4073-8515-b07fd57f74d4",
      "metadata": {},
      "source": [
        "Wiederholen Sie das Experiment mit diesen speziell auf unsere Schaltung abgestimmten Optionen. Die erwartete Laufzeit beträgt etwa vier QPU-Minuten.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 30,
      "id": "ebce8e14-433f-4858-96c6-9d90ff0353af",
      "metadata": {},
      "outputs": [],
      "source": [
        "tem_job_custom = tem.run(\n",
        "    pubs=pubs, backend_name=backend_name, options=options\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bd8d2c12-c9da-4ac3-97c0-d53be1455091",
      "metadata": {},
      "source": [
        "Wenn der Auftrag nicht als privat gekennzeichnet ist, können wir das Ergebnis zu einem späteren Zeitpunkt wiederherstellen. Speichern Sie dazu die hier angegebene Auftrags-ID und verwenden Sie `tem_job_custom = catalog.get_job_by_id(\"your-job-id\")`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 31,
      "id": "0f99101b-9e72-45c8-8b00-9f3a257b8b3b",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Job ID: 1ba10094-a541-457a-9287-dbd49306d12d\n"
          ]
        }
      ],
      "source": [
        "job_id = tem_job_custom.job_id\n",
        "print(f\"Job ID: {job_id}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 33,
      "id": "0c751dac-e856-4371-aaed-f67aca31061f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "TEM Result: 0.956 ± 0.018\n"
          ]
        }
      ],
      "source": [
        "results_custom = tem_job_custom.result()\n",
        "tem_evs = results_custom[0].data.evs[0]\n",
        "tem_std = results_custom[0].data.stds[0]\n",
        "\n",
        "print(f\"TEM Result: {tem_evs:.3f} ± {tem_std:.3f}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "edfef6f9-6bac-42bb-8bd2-95f977f7b31b",
      "metadata": {},
      "source": [
        "Wir können nun die Ergebnisse und Metadaten überprüfen, um Einblicke in das Experiment zu gewinnen:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 34,
      "id": "dd189b2d-860b-4b9a-88c2-7e5c62b1f160",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Unmitigated Result: 0.894 ± 0.015\n",
            "Exact Result: 1.0\n"
          ]
        }
      ],
      "source": [
        "metadata_custom = results_custom[0].metadata\n",
        "\n",
        "unmitigated_evs = metadata_custom[\"evs_non_mitigated\"][0]\n",
        "unmitigated_stds = metadata_custom[\"stds_non_mitigated\"][0]\n",
        "print(f\"Unmitigated Result: {unmitigated_evs:.3f} ± {unmitigated_stds:.3f}\")\n",
        "\n",
        "# Exact result for the kicked Ising model from the reference paper\n",
        "exact_evs = np.cos(2 * h) ** t_steps\n",
        "print(\"Exact Result:\", exact_evs)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 35,
      "id": "c3a2168d-98df-491e-a1f8-05de5684ab96",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/simulate-kicked-ising-tem/extracted-outputs/c3a2168d-98df-491e-a1f8-05de5684ab96-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Plot comparing the different expectation values\n",
        "plt.bar(\n",
        "    [\"Unmitigated\", \"TEM\"],\n",
        "    [unmitigated_evs, tem_evs],\n",
        "    yerr=[unmitigated_stds, tem_std],\n",
        "    color=[\"grey\", \"c\"],\n",
        ")\n",
        "plt.hlines(y=exact_evs, xmin=-0.5, xmax=1.5, colors=\"r\", linestyles=\"dashed\")\n",
        "plt.ylabel(\"Expectation Value\")\n",
        "plt.ylim(0, 1.1)\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d643bdb4-22e0-4f55-b3a8-d5ef39f6e696",
      "metadata": {},
      "source": [
        "Schließlich können wir die Auswirkungen der benutzerdefinierten Optionen auf die QPU und die klassische Laufzeit überprüfen:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "id": "09cf2226-c48c-483b-aa49-80186229ae95",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QPU Runtime: 342.0 seconds\n",
            "Classical Runtime: 107.632604 seconds\n"
          ]
        }
      ],
      "source": [
        "# Get the metadata of the TEM job\n",
        "job_metadata = results_custom.metadata\n",
        "\n",
        "# Get the runtime of the TEM job\n",
        "qpu_runtime = job_metadata[\"resource_usage\"][\"RUNNING: EXECUTING_QPU\"][\n",
        "    \"QPU_TIME\"\n",
        "]\n",
        "classical_runtime = (\n",
        "    job_metadata[\"resource_usage\"][\"RUNNING: OPTIMIZING_FOR_HARDWARE\"][\n",
        "        \"CPU_TIME\"\n",
        "    ]\n",
        "    + job_metadata[\"resource_usage\"][\"RUNNING: POST_PROCESSING\"][\"CPU_TIME\"]\n",
        ")\n",
        "\n",
        "print(f\"QPU Runtime: {qpu_runtime} seconds\")\n",
        "print(f\"Classical Runtime: {classical_runtime} seconds\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7cea6cf1-5530-4bf6-83da-ad2e9ff96806",
      "metadata": {},
      "source": [
        "<span id=\"scale-tem-to-large-circuits\" />\n",
        "\n",
        "## TEM auf große Schaltkreise skalieren\n",
        "\n",
        "Große Schaltungen können grundsätzlich mit der TEM-Funktion betrieben werden. Es ist jedoch wichtig, sich der Grenzen der klassischen Ressourcen bewusst zu sein, da TEM auf IBM Cloud -Runnern mit potenziell sehr langen Laufzeiten ausgeführt wird. Bei extrem großen Schaltkreisen wenden Sie sich bitte an das TEM-Supportteam unter [qiskit\\ \\_ibm@algorithmiq.fi](mailto:qiskit_ibm@algorithmiq.fi).\n",
        "\n",
        "Hier führen wir ein Beispiel mit einer größeren Schaltung im Versorgungsmaßstab mit 30 Qubits durch, wobei die TEM-Parameter eher auf Geschwindigkeit als auf Genauigkeit optimiert werden.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f7ea1d3c-d745-48cc-8922-b070b2b5fd44",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Kicked Ising model parameters\n",
        "n_qubits = 30\n",
        "t_steps = 15\n",
        "h = 0.0\n",
        "\n",
        "# Load the circuit for the kicked Ising model\n",
        "circuit = load(\"ki_30q.qasm\")\n",
        "\n",
        "\n",
        "# Build the observable for the kicked Ising model\n",
        "observable = xt_observable(n_qubits=n_qubits, t_steps=t_steps)\n",
        "\n",
        "# Collect the input PUBs, in this case composed of a\n",
        "# single circuit and observable\n",
        "pubs = [(circuit, [observable])]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "854c3208-8c0f-4f7d-b260-0abba2bc71a0",
      "metadata": {},
      "source": [
        "Lassen Sie uns einige leistungsorientierte Optionen definieren:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 49,
      "id": "64882a71-3027-4e25-b714-9e9d6b13cd49",
      "metadata": {},
      "outputs": [],
      "source": [
        "options = {\n",
        "    \"num_randomizations\": 32,\n",
        "    \"max_layers_to_learn\": 2,\n",
        "    \"shots_per_randomization\": 128,\n",
        "    \"layer_pair_depths\": [0, 1, 2, 4, 16, 32, 64],\n",
        "    \"default_shots\": 5_000,\n",
        "    \"tem_max_bond_dimension\": 128,\n",
        "    \"tem_compression_cutoff\": 1e-10,\n",
        "    \"compute_shadows_bias_from_observable\": True,\n",
        "    \"private\": False,\n",
        "}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4ba36257-1974-4274-b04c-6daf3afe9d72",
      "metadata": {},
      "source": [
        "Führen Sie schließlich das Experiment durch, erhalten Sie das Ergebnis und visualisieren Sie es. Dies dauert ungefähr 3.5 QPU-Minuten.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 50,
      "id": "6faf7f80-dec9-49d2-80e7-d4e6fdea5100",
      "metadata": {},
      "outputs": [],
      "source": [
        "tem_job_large = tem.run(pubs=pubs, backend_name=backend_name, options=options)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 51,
      "id": "333b2335-b480-4bf9-854c-5155eedee900",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Job ID: 9f3f190f-f4b0-4dcb-bb83-5f71f37d0d77\n"
          ]
        }
      ],
      "source": [
        "job_id = tem_job_large.job_id\n",
        "print(f\"Job ID: {job_id}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 53,
      "id": "a04dd421-a212-473c-a8a9-4c8edcfc3667",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "TEM Result: 0.794 ± 0.026\n",
            "QPU Runtime: 203.0 seconds\n",
            "Classical Runtime: 251.71805499999996 seconds\n"
          ]
        }
      ],
      "source": [
        "results_large = tem_job_large.result()\n",
        "tem_evs = results_large[0].data.evs[0]\n",
        "tem_std = results_large[0].data.stds[0]\n",
        "\n",
        "print(f\"TEM Result: {tem_evs:.3f} ± {tem_std:.3f}\")\n",
        "\n",
        "\n",
        "# Get the metadata of the TEM job\n",
        "job_metadata = tem_job_large.result().metadata\n",
        "\n",
        "# Get the runtime of the TEM job\n",
        "qpu_runtime = job_metadata[\"resource_usage\"][\"RUNNING: EXECUTING_QPU\"][\n",
        "    \"QPU_TIME\"\n",
        "]\n",
        "classical_runtime = (\n",
        "    job_metadata[\"resource_usage\"][\"RUNNING: OPTIMIZING_FOR_HARDWARE\"][\n",
        "        \"CPU_TIME\"\n",
        "    ]\n",
        "    + job_metadata[\"resource_usage\"][\"RUNNING: POST_PROCESSING\"][\"CPU_TIME\"]\n",
        ")\n",
        "\n",
        "print(f\"QPU Runtime: {qpu_runtime} seconds\")\n",
        "print(f\"Classical Runtime: {classical_runtime} seconds\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 54,
      "id": "24894c44-e399-4b9d-a3ff-38a28ff32ece",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/simulate-kicked-ising-tem/extracted-outputs/24894c44-e399-4b9d-a3ff-38a28ff32ece-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Plot comparing the different expectation values\n",
        "metadata_large = results_large[0].metadata\n",
        "unmitigated_evs = metadata_large[\"evs_non_mitigated\"][0]\n",
        "unmitigated_stds = metadata_large[\"stds_non_mitigated\"][0]\n",
        "\n",
        "exact_evs = np.cos(2 * h) ** t_steps\n",
        "\n",
        "plt.bar(\n",
        "    [\"Unmitigated\", \"TEM\"],\n",
        "    [unmitigated_evs, tem_evs],\n",
        "    yerr=[unmitigated_stds, tem_std],\n",
        "    color=[\"grey\", \"c\"],\n",
        ")\n",
        "plt.hlines(y=exact_evs, xmin=-0.5, xmax=1.5, colors=\"r\", linestyles=\"dashed\")\n",
        "plt.ylabel(\"Expectation Value\")\n",
        "plt.ylim(0, 1.1)\n",
        "plt.show()"
      ]
    },
    {
      "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"
    },
    "hours": 1.5,
    "qpuSeconds": 600
  },
  "nbformat": 4,
  "nbformat_minor": 4
}