{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "2132f318",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Esecuzione del debug dei processi con NEAT\"\n",
        "description: \"Utilizza la classe `Neat` del modulo degli strumenti di debug `qiskit-ibm-runtime` per eseguire il debug e analizzare i lavori.\"\n",
        "---\n",
        "\n",
        "<span id=\"debug-jobs-with-neat\" />\n",
        "\n",
        "# Esecuzione del debug dei processi con NEAT\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=\"Versioni del pacchetto\">\n",
        "    Il codice di questa pagina è stato sviluppato in base ai seguenti requisiti.\n",
        "    Si consiglia di utilizzare queste versioni o versioni più recenti.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.1\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": [
        "È possibile utilizzare la `Neat` classe per analizzare l'impatto del rumore su un carico di lavoro di Estimator. Per la verifica della sintassi, utilizza [la modalità di test locale](/docs/guides/local-testing-mode).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c5fc18ff",
      "metadata": {},
      "source": [
        "<span id=\"neat-class-usage\" />\n",
        "\n",
        "## `Neat` utilizzo della classe\n",
        "\n",
        "Prima di inviare un carico di lavoro che richiede un elevato impiego di risorse per l'esecuzione sull'hardware, è possibile utilizzare la classe [NEAT (Noisy Estimator Analyzer Tool)](/docs/api/qiskit-ibm-runtime/debug-tools-neat#neat) di IBM Quantum Compute per verificare che il carico di lavoro dell'Estimator sia configurato correttamente, che sia in grado di restituire risultati accurati, che utilizzi le opzioni più appropriate per il problema specificato e altro ancora.\n",
        "\n",
        "`Neat` Cliffordizza i circuiti di ingresso per una simulazione efficiente, pur mantenendo la sua struttura e profondità. I circuiti Clifford soffrono di livelli simili di rumore e sono un buon proxy per studiare il circuito originale di interesse.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a04de1ab",
      "metadata": {},
      "source": [
        "Per prima cosa, importa i pacchetti necessari ed [effettua l'autenticazione al servizio di comput IBM Quantum](/docs/guides/cloud-setup).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "04647f90",
      "metadata": {},
      "source": [
        "<span id=\"prepare-the-environment\" />\n",
        "\n",
        "### Prepara l'ambiente\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, EstimatorV2 as 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",
        "### Inizializzare un circuito di destinazione\n",
        "\n",
        "Si consideri un circuito a sei qubit con le seguenti proprietà:\n",
        "\n",
        "* Alterna rotazioni `RZ` casuali e strati di porte `CNOT`.\n",
        "* Ha una struttura speculare, cioè applica un `U` unitario seguito dal suo inverso.\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.avif\" 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": [
        "Scegliere gli operatori single-Pauli `Z` come osservabili e usarli per inizializzare i blocchi primitivi unificati (PUB).\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",
        "### Cliffordizza i circuiti\n",
        "\n",
        "I circuiti PUB definiti in precedenza non sono Clifford, il che li rende difficili da simulare in modo classico. Tuttavia, è possibile utilizzare il metodo `Neat` [`to_clifford`](/docs/api/qiskit-ibm-runtime/debug-tools-neat#to_clifford) per mapparli in circuiti di Clifford per una simulazione più efficiente.  Il metodo [`to_clifford`](/docs/api/qiskit-ibm-runtime/debug-tools-neat#to_clifford) è un wrapper attorno al passaggio [`ConvertISAToClifford`](/docs/api/qiskit-ibm-runtime/transpiler-passes-convert-isa-to-clifford) che può essere usato anche indipendentemente. In particolare, sostituisce le porte a singolo qubit non Clifford del circuito originale con porte a singolo qubit Clifford, ma non modifica le porte a due qubit, il numero di qubit o la profondità del circuito.\n",
        "\n",
        "Per ulteriori informazioni sulla simulazione dei circuiti Clifford, vedere [Simulazione efficiente di circuiti stabilizzatori con le primitive Aer di Qiskit](/docs/guides/simulate-stabilizer-circuits).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f9918e16",
      "metadata": {},
      "source": [
        "Per prima cosa, inizializzare `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": [
        "Quindi, Cliffordizzare i PUB.\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.avif\" 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",
        "## Applicazione 1: Analizzare l'impatto del rumore sulle uscite del circuito\n",
        "\n",
        "Questo esempio mostra come utilizzare `Neat` per studiare l'impatto di diversi modelli di rumore sui PUB in funzione della profondità del circuito, eseguendo simulazioni sia in condizioni ideali ([`ideal_sim`](/docs/api/qiskit-ibm-runtime/debug-tools-neat#ideal_sim)) che rumorose ([`noisy_sim`](/docs/api/qiskit-ibm-runtime/debug-tools-neat#noisy_sim)). Questo può essere utile per definire le aspettative sulla qualità dei risultati sperimentali prima di eseguire un lavoro su una QPU. Per ulteriori informazioni sui modelli di rumore, consultare [Simulazione esatta e rumorosa con le primitive Aer di Qiskit](/docs/guides/simulate-with-qiskit-aer#exact-and-noisy-simulation-with-qiskit-aer-primitives).\n",
        "\n",
        "I risultati simulati supportano le operazioni matematiche e possono quindi essere confrontati tra loro (o con i risultati sperimentali) per calcolare le cifre di merito.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Una QPU può essere influenzata da diversi tipi di rumore. Il modello di rumore di Qiskit Aer utilizzato qui simula solo alcuni di essi e quindi è probabile che il rumore sia meno grave di quello di una QPU reale.\n",
        "\n",
        "  Per i dettagli su quali errori vengono inclusi quando si inizializza un modello di rumore da una QPU, si veda il riferimento all'API di Aer [`NoiseModel`](https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.noise.NoiseModel.html#qiskit_aer.noise.NoiseModel.from_backend) API.\n",
        "</Admonition>\n",
        "\n",
        "Iniziare eseguendo simulazioni classiche ideali e rumorose.\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",
            "Noisy results:\n",
            " NeatResult([NeatPubResult(vals=array([0.9921875 , 0.99414062, 1.        , 0.99609375, 0.99609375,\n",
            "       0.99609375])), NeatPubResult(vals=array([0.97460938, 0.97851562, 0.98046875, 0.99609375, 0.99414062,\n",
            "       0.99609375])), NeatPubResult(vals=array([0.96679688, 0.98242188, 0.97460938, 0.98046875, 0.99414062,\n",
            "       0.99609375])), NeatPubResult(vals=array([0.96679688, 0.96289062, 0.97460938, 0.9765625 , 0.98632812,\n",
            "       0.99414062])), NeatPubResult(vals=array([0.921875  , 0.92773438, 0.95898438, 0.9609375 , 0.97265625,\n",
            "       0.98242188])), NeatPubResult(vals=array([0.90820312, 0.92773438, 0.95507812, 0.9609375 , 0.97460938,\n",
            "       0.984375  ]))])\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": [
        "Successivamente, applicare le operazioni matematiche per calcolare la differenza assoluta. Il resto della guida utilizza la differenza assoluta come cifra di merito per confrontare i risultati ideali con quelli rumorosi o sperimentali, ma è possibile impostare cifre di merito simili.\n",
        "\n",
        "La differenza assoluta mostra che l'impatto del rumore cresce con le dimensioni dei circuiti.\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",
            "  0.42%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 2 layers:\n",
            "  1.34%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 3 layers:\n",
            "  1.76%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 4 layers:\n",
            "  2.31%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 5 layers:\n",
            "  4.59%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 6 layers:\n",
            "  4.82%\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": [
        "Per migliorare i circuiti di questo tipo è possibile seguire queste linee guida approssimative e semplificate:\n",
        "\n",
        "* Se la differenza media assoluta è superiore al 90%, è probabile che la mitigazione non sia utile.\n",
        "* Se la differenza assoluta media è inferiore al 90%, l' [amplificazione probabilistica degli errori (PEA)](/docs/guides/error-mitigation-and-suppression-techniques#probabilistic-error-amplification-pea) sarà probabilmente in grado di migliorare i risultati.\n",
        "* Se la differenza media assoluta è inferiore all'80%, anche la [ZNE con ripiegamento delle porte](/docs/guides/error-mitigation-and-suppression-techniques#zero-noise-extrapolation-zne) sarà probabilmente in grado di migliorare i risultati.\n",
        "\n",
        "Poiché tutte le differenze assolute di cui sopra sono inferiori al 90%, applicando la PEA al circuito originale si spera di migliorare la qualità dei risultati.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0ac8c13a",
      "metadata": {},
      "source": [
        "Nell'analizzatore è possibile specificare diversi modelli di rumore. L'esempio seguente esegue lo stesso test, ma aggiunge un modello di rumore personalizzato.\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",
            "  3.78%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 2 layers:\n",
            "  6.38%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 3 layers:\n",
            "  13.84%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 4 layers:\n",
            "  18.88%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 5 layers:\n",
            "  22.95%\n",
            "\n",
            "Mean absolute difference between ideal and noisy results for circuits with 6 layers:\n",
            "  26.2%\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": [
        "Come mostrato, dato un modello di rumore, è possibile cercare di quantificare l'impatto del rumore sui PUB (versione Cliffordizzata dei PUB) di interesse prima di eseguirli su una QPU.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "90571f2f",
      "metadata": {},
      "source": [
        "<span id=\"application-2-benchmark-different-strategies\" />\n",
        "\n",
        "## Applicazione 2: Confronto tra diverse strategie\n",
        "\n",
        "Questo esempio utilizza `Neat` per aiutare a identificare le opzioni migliori per i vostri PUB. A tal fine, si consideri l'esecuzione di un problema di stima con PEA, che non può essere simulato con `qiskit_aer`. È possibile utilizzare `Neat` per determinare quali fattori di amplificazione del rumore funzionano meglio, quindi utilizzare tali fattori quando si esegue l'esperimento originale su una QPU.\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": null,
      "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",
        "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": null,
      "id": "efd9afc3",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Perform a noiseless simulation\n",
        "ideal_results = analyzer.ideal_sim(clifford_pubs)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "d409906c",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Mean absolute difference for factors [1, 1.1]:\n",
            "  3.92%\n",
            "\n",
            "Mean absolute difference for factors [1, 1.1, 1.2]:\n",
            "  3.64%\n",
            "\n",
            "Mean absolute difference for factors [1, 1.5, 2]:\n",
            "  4.41%\n",
            "\n",
            "Mean absolute difference for factors [1, 1.5, 2, 2.5, 3]:\n",
            "  3.84%\n",
            "\n",
            "Mean absolute difference for factors [1, 4]:\n",
            "  5.14%\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": [
        "Il risultato con la differenza minore suggerisce quali opzioni scegliere.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "741b162c",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Suggerimenti\">\n",
        "  * Leggi una panoramica sugli [strumenti di debug di Qiskit](/docs/guides/debugging-tools).\n",
        "  * Scopri [la simulazione esatta e rumorosa con le primitive Aer di Qiskit](/docs/guides/simulate-with-qiskit-aer).\n",
        "  * Scopri [le opzioni disponibili per Compute su IBM Quantum](/docs/guides/runtime-options-overview).\n",
        "  * Scopri [le tecniche](/docs/guides/error-mitigation-and-suppression-techniques) di mitigazione e soppressione degli errori.\n",
        "  * Visitate l'argomento [Transpile con i pass manager](transpile-with-pass-managers).\n",
        "  * Scopri [come traspilare i circuiti](/docs/guides/circuit-transpilation-settings#compare-transpiler-settings) nell'ambito dei flussi di lavoro dei pattern di Qiskit.\n",
        "  * Consulta [la documentazione relativa alle API degli strumenti di debug](/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
}