{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "2132f318",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Jobs mit NEAT debuggen\"\n",
        "description: \"Verwenden Sie die Klasse „Neat“ aus dem Modul „qiskit-ibm-runtime debugging tools“, um Jobs zu debuggen und zu analysieren.\"\n",
        "---\n",
        "\n",
        "<span id=\"debug-jobs-with-neat\" />\n",
        "\n",
        "# Jobs mit NEAT debuggen\n",
        "\n",
        "{/* cspell:ignore ZIIIII, IZIIII,IIZIII, IIIZII, IIIIZI, IIIIIZ, rdiff */}\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3e4d6f78",
      "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",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    qiskit-aer~=0.17\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "82c75c11",
      "metadata": {},
      "source": [
        "Sie können die `Neat` Klasse verwenden, um die Auswirkungen von Rauschen auf eine Estimator-Workload zu analysieren. Verwenden Sie zur Syntaxprüfung [den lokalen Testmodus](/docs/guides/local-testing-mode).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c5fc18ff",
      "metadata": {},
      "source": [
        "<span id=\"neat-class-usage\" />\n",
        "\n",
        "## `Neat` Verwendung der Klasse\n",
        "\n",
        "Bevor Sie eine ressourcenintensive Arbeitslast zur Ausführung auf der Hardware übermitteln, können Sie mithilfe der [NEAT-Klasse (Noisy Estimator Analyzer Tool)](/docs/api/qiskit-ibm-runtime/debug-tools-neat#neat) von „ IBM Quantum “ Compute überprüfen, ob Ihre Estimator-Arbeitslast korrekt eingerichtet ist, voraussichtlich genaue Ergebnisse liefert, die für das jeweilige Problem am besten geeigneten Optionen verwendet und vieles mehr.\n",
        "\n",
        "`Neat` Die Eingangsschaltungen werden für eine effiziente Simulation cliffordisiert, wobei ihre Struktur und Tiefe erhalten bleiben. Clifford-Schaltungen weisen ein ähnliches Maß an Rauschen auf und sind ein guter Ersatz für die Untersuchung der ursprünglichen Schaltung von Interesse.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a04de1ab",
      "metadata": {},
      "source": [
        "Importieren Sie zunächst die entsprechenden Pakete und [authentifizieren Sie sich beim IBM Quantum Compute Service](/docs/guides/cloud-setup).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "04647f90",
      "metadata": {},
      "source": [
        "<span id=\"prepare-the-environment\" />\n",
        "\n",
        "### Vorbereitung der Umgebung\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "85d72148",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "import random\n",
        "\n",
        "from qiskit.circuit import QuantumCircuit\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService, NoiseLearnerV3\n",
        "\n",
        "# Legacy server-side primitive before qiskit-ibm-runtime 0.50.0\n",
        "# from qiskit_ibm_runtime import Estimator\n",
        "\n",
        "# Client-side primitive introduced in qiskit-ibm-runtime 0.50.0\n",
        "from qiskit_ibm_runtime.executor_estimator import Estimator\n",
        "from qiskit_ibm_runtime.debug_tools import Neat\n",
        "\n",
        "from qiskit_aer.noise import NoiseModel, depolarizing_error"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "8a98c131",
      "metadata": {},
      "outputs": [],
      "source": [
        "# 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 equivalent\n",
        "# Instruction Set Architecture (ISA) circuit.\n",
        "\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=0)\n",
        "\n",
        "# Set the random seed\n",
        "random.seed(10)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "067fb74b",
      "metadata": {},
      "source": [
        "<span id=\"initialize-a-target-circuit\" />\n",
        "\n",
        "### Initialisieren Sie eine Zielschaltung\n",
        "\n",
        "Betrachten Sie eine Sechs-Qubit-Schaltung, die die folgenden Eigenschaften hat:\n",
        "\n",
        "* Wechselt zwischen zufälligen \"RZ\"-Drehungen und Schichten von \"CNOT\"-Toren.\n",
        "* Hat eine spiegelbildliche Struktur, d. h. sie wendet eine einheitliche `U` gefolgt von ihrer Umkehrung an.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "a9018f3a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/debug-qiskit-runtime-jobs/extracted-outputs/a9018f3a-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "def generate_circuit(n_qubits, n_layers):\n",
        "    r\"\"\"\n",
        "    A function to generate a pseudo-random a circuit with ``n_qubits`` qubits\n",
        "    and ``2*n_layers`` entangling layers of the type used in this notebook.\n",
        "    \"\"\"\n",
        "    # An array of random angles\n",
        "    angles = [\n",
        "        [random.random() for q in range(n_qubits)] for s in range(n_layers)\n",
        "    ]\n",
        "\n",
        "    qc = QuantumCircuit(n_qubits)\n",
        "    qubits = list(range(n_qubits))\n",
        "\n",
        "    # do random circuit\n",
        "    for layer in range(n_layers):\n",
        "        # rotations\n",
        "        for q_idx, qubit in enumerate(qubits):\n",
        "            qc.rz(angles[layer][q_idx], qubit)\n",
        "\n",
        "        # cx gates\n",
        "        control_qubits = (\n",
        "            qubits[::2] if layer % 2 == 0 else qubits[1 : n_qubits - 1 : 2]\n",
        "        )\n",
        "        for qubit in control_qubits:\n",
        "            qc.cx(qubit, qubit + 1)\n",
        "\n",
        "    # undo random circuit\n",
        "    for layer in range(n_layers)[::-1]:\n",
        "        # cx gates\n",
        "        control_qubits = (\n",
        "            qubits[::2] if layer % 2 == 0 else qubits[1 : n_qubits - 1 : 2]\n",
        "        )\n",
        "        for qubit in control_qubits:\n",
        "            qc.cx(qubit, qubit + 1)\n",
        "\n",
        "        # rotations\n",
        "        for q_idx, qubit in enumerate(qubits):\n",
        "            qc.rz(-angles[layer][q_idx], qubit)\n",
        "\n",
        "    return qc\n",
        "\n",
        "\n",
        "# Generate a random circuit\n",
        "qc = generate_circuit(6, 3)\n",
        "# Convert the abstract circuit to an equivalent ISA circuit.\n",
        "isa_qc = pm.run(qc)\n",
        "\n",
        "qc.draw(\"mpl\", idle_wires=0)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "03d46401",
      "metadata": {},
      "source": [
        "Wählen Sie Einzel-Pauli `Z` Operatoren als Observablen und verwenden Sie sie, um die primitiven vereinheitlichten Blöcke (PUBs) zu initialisieren.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "edf0d8f7",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Observables: ['ZIIIII', 'IZIIII', 'IIZIII', 'IIIZII', 'IIIIZI', 'IIIIIZ']\n"
          ]
        }
      ],
      "source": [
        "# Initialize the observables\n",
        "obs = [\"ZIIIII\", \"IZIIII\", \"IIZIII\", \"IIIZII\", \"IIIIZI\", \"IIIIIZ\"]\n",
        "print(f\"Observables: {obs}\")\n",
        "\n",
        "# Map the observables to the backend's layout\n",
        "isa_obs = [SparsePauliOp(o).apply_layout(isa_qc.layout) for o in obs]\n",
        "\n",
        "# Initialize the PUBs, which consist of six-qubit circuits\n",
        "# with `n_layers` 1, ..., 6\n",
        "all_n_layers = [1, 2, 3, 4, 5, 6]\n",
        "\n",
        "pubs = [(pm.run(generate_circuit(6, n)), isa_obs) for n in all_n_layers]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6f832a19",
      "metadata": {},
      "source": [
        "<span id=\"cliffordize-the-circuits\" />\n",
        "\n",
        "### Die Schaltkreise cliffordisieren\n",
        "\n",
        "Die zuvor definierten PUB Schaltungen sind nicht Clifford, was ihre klassische Simulation erschwert. Sie können jedoch mit der Methode `Neat` [`to_clifford`](/docs/api/qiskit-ibm-runtime/debug-tools-neat#to_clifford) verwenden, um sie für eine effizientere Simulation auf Clifford-Schaltungen abzubilden.  Die Methode [`to_clifford`](/docs/api/qiskit-ibm-runtime/debug-tools-neat#to_clifford) methode ist ein Wrapper um den [`ConvertISAToClifford`](/docs/api/qiskit-ibm-runtime/transpiler-passes-convert-isa-to-clifford) transpiler-Pass, der auch unabhängig davon verwendet werden kann. Insbesondere werden nicht-Clifford-Ein-Qubit-Gatter in der ursprünglichen Schaltung durch Clifford-Ein-Qubit-Gatter ersetzt, aber die Zwei-Qubit-Gatter, die Anzahl der Qubits oder die Schaltungstiefe werden nicht verändert.\n",
        "\n",
        "Weitere Informationen über die Simulation von Clifford-Schaltungen finden Sie unter [Effiziente Simulation von Stabilisierungsschaltungen mit Qiskit Aer-Primitiven](/docs/guides/simulate-stabilizer-circuits).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f9918e16",
      "metadata": {},
      "source": [
        "Initialisieren Sie zunächst `Neat`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "9dda57a5",
      "metadata": {},
      "outputs": [],
      "source": [
        "# You could specify a custom `NoiseModel` here. If `None`, `Neat`\n",
        "# pulls the noise model from the given backend\n",
        "noise_model = None\n",
        "\n",
        "# Initialize `Neat`\n",
        "analyzer = Neat(backend, noise_model)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "968c6d2b",
      "metadata": {},
      "source": [
        "Als Nächstes müssen Sie die PUBs cliffordisieren.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "67152273",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/debug-qiskit-runtime-jobs/extracted-outputs/67152273-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "clifford_pubs = analyzer.to_clifford(pubs)\n",
        "\n",
        "clifford_pubs[0].circuit.draw(\"mpl\", idle_wires=0)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8ce5da6d",
      "metadata": {},
      "source": [
        "<span id=\"application-1-analyze-the-impact-of-noise-on-the-circuit-outputs\" />\n",
        "\n",
        "## Anwendung 1: Analyse der Auswirkungen von Störgeräuschen auf die Schaltungsausgänge\n",
        "\n",
        "Dieses Beispiel zeigt, wie man mit Hilfe `Neat` von die Auswirkungen verschiedener Rauschmodelle auf PUBs als Funktion der Schaltungstiefe untersuchen kann, indem Simulationen sowohl unter idealen ([`ideal_sim`](/docs/api/qiskit-ibm-runtime/debug-tools-neat#ideal_sim)) als auch unter verrauschten ([`noisy_sim`](/docs/api/qiskit-ibm-runtime/debug-tools-neat#noisy_sim)) Bedingungen durchgeführt werden. Dies kann nützlich sein, um Erwartungen an die Qualität der Versuchsergebnisse zu formulieren, bevor ein Auftrag auf einer QPU ausgeführt wird. Weitere Informationen zu Rauschmodellen finden Sie unter [Exakte und verrauschte Simulation mit Qiskit Aer-Primitiven](/docs/guides/simulate-with-qiskit-aer#exact-and-noisy-simulation-with-qiskit-aer-primitives).\n",
        "\n",
        "Die simulierten Ergebnisse unterstützen mathematische Operationen und können daher miteinander (oder mit experimentellen Ergebnissen) verglichen werden, um Leistungskennzahlen zu berechnen.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Ein QPU kann durch verschiedene Arten von Lärm beeinträchtigt werden. Das hier verwendete Qiskit-Aer-Rauschmodell simuliert nur einige davon und ist daher wahrscheinlich weniger stark als das Rauschen auf einer echten QPU.\n",
        "\n",
        "  Einzelheiten darüber, welche Fehler bei der Initialisierung eines Rauschmodells von einer QPU enthalten sind, finden Sie in der Aer [`NoiseModel`](https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.noise.NoiseModel.html#qiskit_aer.noise.NoiseModel.from_backend) API-Referenz.\n",
        "</Admonition>\n",
        "\n",
        "Beginnen Sie mit der Durchführung idealer und verrauschter klassischer Simulationen.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "e2f936c5",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Ideal results:\n",
            " NeatResult([NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.])), NeatPubResult(vals=array([1., 1., 1., 1., 1., 1.]))])\n",
            "\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Noisy results:\n",
            " NeatResult([NeatPubResult(vals=array([0.99609375, 0.99414062, 0.98632812, 0.9921875 , 0.97460938,\n",
            "       0.97851562])), NeatPubResult(vals=array([0.984375  , 0.98828125, 0.98046875, 0.98632812, 0.96679688,\n",
            "       0.98828125])), NeatPubResult(vals=array([0.9609375 , 0.9765625 , 0.953125  , 0.95898438, 0.95703125,\n",
            "       0.96679688])), NeatPubResult(vals=array([0.96875   , 0.97070312, 0.93164062, 0.94335938, 0.93164062,\n",
            "       0.97460938])), NeatPubResult(vals=array([0.9140625 , 0.9296875 , 0.91796875, 0.92382812, 0.90429688,\n",
            "       0.91992188])), NeatPubResult(vals=array([0.89648438, 0.9140625 , 0.921875  , 0.94921875, 0.92773438,\n",
            "       0.95117188]))])\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# Perform a noiseless simulation\n",
        "ideal_results = analyzer.ideal_sim(clifford_pubs)\n",
        "print(f\"Ideal results:\\n {ideal_results}\\n\")\n",
        "\n",
        "# Perform a noisy simulation with the backend's noise model\n",
        "noisy_results = analyzer.noisy_sim(clifford_pubs)\n",
        "print(f\"Noisy results:\\n {noisy_results}\\n\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5dcca742",
      "metadata": {},
      "source": [
        "Wenden Sie anschließend mathematische Operationen an, um die absolute Differenz zu berechnen. Im weiteren Verlauf des Leitfadens wird die absolute Differenz als Leistungskennzahl verwendet, um ideale Ergebnisse mit verrauschten oder experimentellen Ergebnissen zu vergleichen, aber es können ähnliche Leistungskennzahlen aufgestellt werden.\n",
        "\n",
        "Die absolute Differenz zeigt, dass die Auswirkungen des Rauschens mit der Größe der Schaltkreise zunehmen.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "00fed421",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Mean absolute difference between ideal and noisy results for circuits with 1 layers:\n",
            "  1.3%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 2 layers:\n",
            "  1.76%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 3 layers:\n",
            "  3.78%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 4 layers:\n",
            "  4.66%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 5 layers:\n",
            "  8.17%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 6 layers:\n",
            "  7.32%\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# Figure of merit: Absolute difference\n",
        "def rdiff(res1, res2):\n",
        "    r\"\"\"The absolute difference between `res1` and res2`.\n",
        "\n",
        "    --> The closer to `0`, the better.\n",
        "    \"\"\"\n",
        "    d = abs(res1 - res2)\n",
        "    return np.round(d.vals * 100, 2)\n",
        "\n",
        "\n",
        "for idx, (ideal_res, noisy_res) in enumerate(\n",
        "    zip(ideal_results, noisy_results)\n",
        "):\n",
        "    vals = rdiff(ideal_res, noisy_res)\n",
        "\n",
        "    # Print the mean absolute difference for the observables\n",
        "    mean_vals = np.round(np.mean(vals), 2)\n",
        "    print(\n",
        "        f\"Mean absolute difference between ideal and noisy results \"\n",
        "        f\"for circuits with {all_n_layers[idx]} layers:\\n  {mean_vals}%\\n\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "288463ca",
      "metadata": {},
      "source": [
        "Sie können diese groben und vereinfachten Richtlinien befolgen, um Schaltungen dieser Art zu verbessern:\n",
        "\n",
        "* Wenn die mittlere absolute Differenz mehr als 90 % beträgt, ist eine Milderung wahrscheinlich nicht sinnvoll.\n",
        "* Wenn die mittlere absolute Differenz weniger als 90 % beträgt, kann die [probabilistische Fehlerverstärkung (PEA](/docs/guides/error-mitigation-and-suppression-techniques#probabilistic-error-amplification-pea) ) die Ergebnisse wahrscheinlich verbessern.\n",
        "* Wenn die mittlere absolute Differenz weniger als 80 % beträgt, können die Ergebnisse wahrscheinlich auch durch [ZNE mit Gate-Faltung](/docs/guides/error-mitigation-and-suppression-techniques#zero-noise-extrapolation-zne) verbessert werden.\n",
        "\n",
        "Da alle oben genannten absoluten Unterschiede weniger als 90 % betragen, wird die Anwendung der PEA auf den ursprünglichen Schaltkreis hoffentlich die Qualität der Ergebnisse verbessern.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0ac8c13a",
      "metadata": {},
      "source": [
        "Sie können im Analysator verschiedene Rauschmodelle angeben. Das folgende Beispiel führt denselben Test durch, fügt aber ein benutzerdefiniertes Rauschmodell hinzu.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "baf16779",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Mean absolute difference between ideal and noisy results for circuits with 1 layers:\n",
            "  4.16%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 2 layers:\n",
            "  8.92%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 3 layers:\n",
            "  12.86%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 4 layers:\n",
            "  17.45%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 5 layers:\n",
            "  25.82%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 6 layers:\n",
            "  27.96%\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# Set up a noise model with strength 0.02 on every two-qubit gate\n",
        "noise_model = NoiseModel()\n",
        "for qubits in backend.coupling_map:\n",
        "    noise_model.add_quantum_error(\n",
        "        depolarizing_error(0.02, 2), [\"ecr\", \"cx\", \"cz\"], qubits\n",
        "    )\n",
        "\n",
        "# Update the analyzer's noise model\n",
        "analyzer.noise_model = noise_model\n",
        "\n",
        "# Perform a noiseless simulation\n",
        "ideal_results = analyzer.ideal_sim(clifford_pubs)\n",
        "\n",
        "# Perform a noisy simulation with the backend's noise model\n",
        "noisy_results = analyzer.noisy_sim(clifford_pubs)\n",
        "\n",
        "# Compare the results\n",
        "for idx, (ideal_res, noisy_res) in enumerate(\n",
        "    zip(ideal_results, noisy_results)\n",
        "):\n",
        "    values = rdiff(ideal_res, noisy_res)\n",
        "\n",
        "    # Print the mean absolute difference for the observables\n",
        "    mean_values = np.round(np.mean(values), 2)\n",
        "    print(\n",
        "        f\"Mean absolute difference between ideal and noisy results \"\n",
        "        f\"for circuits with {all_n_layers[idx]} layers:\\n  {mean_values}%\\n\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "baa3d516",
      "metadata": {},
      "source": [
        "Wie gezeigt, kann man mit einem Rauschmodell versuchen, die Auswirkungen des Rauschens auf die (Clifford'sche Version der) PUBs von Interesse zu quantifizieren, bevor man sie auf einer QPU laufen lässt.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "90571f2f",
      "metadata": {},
      "source": [
        "<span id=\"application-2-benchmark-different-strategies\" />\n",
        "\n",
        "## Anwendung 2: Vergleich verschiedener Strategien\n",
        "\n",
        "Dieses Beispiel verwendet `Neat` , um die besten Optionen für Ihre PUBs zu ermitteln. Betrachten Sie dazu ein Schätzungsproblem mit PEA, das nicht mit `qiskit_aer` simuliert werden kann. Sie können `Neat` verwenden, um zu bestimmen, welche Rauschverstärkungsfaktoren am besten funktionieren, und diese Faktoren dann bei der Durchführung des ursprünglichen Experiments auf einer QPU verwenden.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "bd87c90d",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Generate a circuit with six qubits and six layers\n",
        "isa_qc = pm.run(generate_circuit(6, 3))\n",
        "\n",
        "# Use the same observables as previously\n",
        "pubs = [(isa_qc, isa_obs)]\n",
        "clifford_pubs = analyzer.to_clifford(pubs)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "96d41662",
      "metadata": {},
      "outputs": [],
      "source": [
        "noise_factors = [\n",
        "    [1, 1.1],\n",
        "    [1, 1.1, 1.2],\n",
        "    [1, 1.5, 2],\n",
        "    [1, 1.5, 2, 2.5, 3],\n",
        "    [1, 4],\n",
        "]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "696076bb",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Run the PUBs on a QPU\n",
        "estimator = Estimator(backend)\n",
        "estimator.options.default_shots = 100000\n",
        "estimator.options.twirling.enable_gates = True\n",
        "estimator.options.twirling.enable_measure = True\n",
        "estimator.options.twirling.shots_per_randomization = 100\n",
        "estimator.options.resilience.measure_mitigation = True\n",
        "estimator.options.resilience.zne_mitigation = True\n",
        "estimator.options.resilience.zne.amplifier = \"pea\"\n",
        "\n",
        "# Learn noise model\n",
        "layers = estimator.find_unique_layers(clifford_pubs)\n",
        "learner = NoiseLearnerV3(backend)\n",
        "learner_job = learner.run(layers)\n",
        "learner_result = learner_job.result()\n",
        "\n",
        "# Convert results to Pauli-Lindblad noise maps.\n",
        "pauli_lindblad_maps = learner_result.to_pauli_lindblad_maps()\n",
        "\n",
        "# Assign the learned noise maps so PEA uses them.\n",
        "estimator.options.resilience.layer_noise_model = zip(\n",
        "    layers, pauli_lindblad_maps\n",
        ")\n",
        "\n",
        "jobs = []\n",
        "for factors in noise_factors:\n",
        "    estimator.options.resilience.zne.noise_factors = factors\n",
        "    jobs.append(estimator.run(clifford_pubs))\n",
        "\n",
        "results = [job.result() for job in jobs]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "efd9afc3",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Perform a noiseless simulation\n",
        "ideal_results = analyzer.ideal_sim(clifford_pubs)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "d409906c",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Mean absolute difference for factors [1, 1.1]:\n",
            "  10.9%\n",
            "\n",
            "Mean absolute difference for factors [1, 1.1, 1.2]:\n",
            "  4.64%\n",
            "\n",
            "Mean absolute difference for factors [1, 1.5, 2]:\n",
            "  4.33%\n",
            "\n",
            "Mean absolute difference for factors [1, 1.5, 2, 2.5, 3]:\n",
            "  5.66%\n",
            "\n",
            "Mean absolute difference for factors [1, 4]:\n",
            "  4.53%\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# Look at the mean absolute difference to quickly determine\n",
        "# the best choice for your options\n",
        "for factors, res in zip(noise_factors, results):\n",
        "    d = rdiff(ideal_results[0], res[0])\n",
        "    print(\n",
        "        f\"Mean absolute difference for factors \"\n",
        "        f\"{factors}:\\n  {np.round(np.mean(d), 2)}%\\n\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "66735c1a",
      "metadata": {},
      "source": [
        "Das Ergebnis mit der geringsten Differenz zeigt an, welche Optionen zu wählen sind.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "741b162c",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Nächste Schritte\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Empfehlungen\">\n",
        "  * Lesen Sie eine Übersicht über [die Debugging-Tools von Qiskit](/docs/guides/debugging-tools).\n",
        "  * Erfahren Sie mehr über [exakte und verrauschte Simulationen mit Qiskit Aer-Primitiven](/docs/guides/simulate-with-qiskit-aer).\n",
        "  * Erfahren Sie mehr über [die verfügbaren „ IBM Quantum “-Rechenoptionen](/docs/guides/runtime-options-overview).\n",
        "  * Erfahren Sie mehr über [Techniken zur Fehlerminderung und -unterdrückung](/docs/guides/error-mitigation-and-suppression-techniques).\n",
        "  * Besuchen Sie das Thema [Transpile mit Passmanagern](transpile-with-pass-managers).\n",
        "  * Erfahren Sie, [wie Sie Schaltkreise](/docs/guides/circuit-transpilation-settings#compare-transpiler-settings) im Rahmen von Qiskit-Patterns-Workflows transpilieren können.\n",
        "  * Lesen Sie [die Dokumentation zur Debugging-Tools-API](/docs/api/qiskit-ibm-runtime/debug-tools).\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
}