{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "cell-00",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Aggiornamento delle proprietà del backend con analisi comparativa in tempo reale\"\n",
        "description: \"Eseguire rapidamente esperimenti di caratterizzazione per misurare in tempo reale le proprietà della QPU e aggiornare il backend con i dati più recenti relativi a T1, T2, errori di lettura e di gate.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore CPMG dephase ylim */}\n",
        "\n",
        "<span id=\"refresh-backend-properties-with-real-time-benchmarking\" />\n",
        "\n",
        "# Aggiornamento delle proprietà del backend con analisi comparativa in tempo reale\n",
        "\n",
        "Stima della *durata: 3 minuti su ibm\\_kingston (NOTA: si tratta solo di una stima. (La durata potrebbe variare.)*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-01",
      "metadata": {},
      "source": [
        "<span id=\"learning-outcomes\" />\n",
        "\n",
        "## Risultati di apprendimento\n",
        "\n",
        "* Perché le proprietà riportate da una QPU possono non essere aggiornate rispetto al comportamento attuale del dispositivo, e quando conviene ricalcolarle autonomamente\n",
        "* Cosa misura ciascuno dei cinque esperimenti standard di caratterizzazione (readout, benchmarking randomizzato su singolo qubit, benchmarking randomizzato a due qubit stratificato, “ $T_1$ ” e “ $T_2$ ”)\n",
        "* Come eseguire la suite completa di caratterizzazione in un'unica chiamata o passo dopo passo e ottenere un oggetto backend con proprietà aggiornate\n",
        "* Come confrontare le proprietà misurate con quelle riportate, e perché alcune differenze sono dovute alla metodologia di misurazione piuttosto che alla deriva del dispositivo\n",
        "\n",
        "<span id=\"prerequisites\" />\n",
        "\n",
        "## Prerequisiti\n",
        "\n",
        "* Il flusso di lavoro [dei modelli di](/docs/guides/intro-to-patterns) Qiskit\n",
        "* [Qiskit Runtime modalità di esecuzione](/docs/guides/execution-modes), in particolare la modalità batch\n",
        "* Come esaminare [le informazioni relative alla QPU](/docs/guides/qpu-information), quali le proprietà del backend e i dati di calibrazione\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-02",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## Sfondo\n",
        "\n",
        "Ogni QPU IBM Quantum® riporta una serie di proprietà che descrivono il livello di funzionamento attuale di ciascuno dei suoi qubit: tempi di rilassamento ( $T_1$ ), tempi di coerenza ( $T_2$ ), errori di lettura ed errori relativi ai gate a uno e a due qubit. Questi numeri contano nella pratica. Il transpiler li utilizza per decidere su quali qubit fisici debba funzionare il circuito; le tecniche di mitigazione degli errori si basano su di essi e potresti usarli per valutare se un dispositivo funziona abbastanza bene da poter essere utilizzato per un esperimento.\n",
        "\n",
        "I valori riportati derivano da procedure di calibrazione che vengono eseguite in genere una volta al giorno. I qubit superconduttori, tuttavia, possono subire derive su scale temporali più brevi, e i difetti transitori (i cosiddetti sistemi a due livelli) possono degradare temporaneamente un qubit che al momento della calibrazione appariva in condizioni eccellenti. Inoltre, spesso un’operazione viene transpila ben prima della sua effettiva esecuzione, quindi le decisioni basate sulle proprietà riportate potrebbero fondarsi su informazioni non aggiornate. Il tutorial [“Benchmarking in tempo reale per la selezione dei qubit”](/docs/tutorials/real-time-benchmarking-for-qubit-selection) mostra quanto queste proprietà possano variare di giorno in giorno e illustra come costruire manualmente un flusso di lavoro completo di caratterizzazione a partire [dai](https://qiskit-community.github.io/qiskit-experiments/) singoli esperimenti di Qiskit.\n",
        "\n",
        "Questo tutorial illustra la versione semplificata di tale flusso di lavoro, utilizzando l'utilità `BackendCharacterization` di [Qiskit Device Benchmarking](https://github.com/qiskit-community/qiskit-device-benchmarking), che riunisce la creazione dell'esperimento, l'invio del lavoro e l'adattamento della curva in poche chiamate. Si impiegano circa 70 secondi di tempo QPU e si ottiene un oggetto backend le cui proprietà rispecchiano *lo stato attuale* del dispositivo, pronto per essere confrontato con i valori riportati o trasmesso agli strumenti a valle.\n",
        "\n",
        "<span id=\"the-characterization-experiments\" />\n",
        "\n",
        "### Gli esperimenti di caratterizzazione\n",
        "\n",
        "La suite comprende cinque proprietà, ciascuna con un esperimento standard:\n",
        "\n",
        "* **Errore di lettura** (`readout`): Ogni qubit viene preparato in uno stato di tipo “ $|0\\rangle$ ” o “ $|1\\rangle$ ” e misurato immediatamente. La probabilità di rilevare uno stato errato determina l'errore di preparazione e misurazione dello stato (SPAM).\n",
        "* **Errore di gate su un singolo qubit** (`rb_1q`): Il benchmarking randomizzato (RB) esegue sequenze di gate di Clifford casuali su un singolo qubit che, idealmente, si combinano per formare il gate identità. Il modo in cui la probabilità di sopravvivenza diminuisce al crescere della lunghezza della sequenza determina l’errore medio per gate, indipendentemente dagli errori SPAM.\n",
        "* **Errore di gate a due qubit** (`rb_2q`): lo stesso concetto di RB applicato a livelli completi di gate a due qubit non sovrapposti eseguiti simultaneamente, come in un esperimento [sulla fedeltà dei livelli](https://arxiv.org/abs/2311.05933). Poiché molti gate funzionano contemporaneamente, i tassi di errore che ne derivano includono effetti di diafonia e sono più vicini a quelli che si verificano effettivamente in un circuito profondo.\n",
        "* **$T_1$** (`t1`): Ogni qubit viene eccitato e misurato dopo ritardi crescenti. Il decadimento della popolazione dello stato eccitato determina il tempo di rilassamento.\n",
        "* **$T_2$** (`t2`): In un esperimento di eco di Hahn, ogni qubit viene posto in una sovrapposizione, viene applicato un impulso di eco a metà del ritardo e viene misurata la velocità con cui si perde la coerenza di fase. Per impostazione predefinita viene utilizzato un singolo eco; alla fine di questo tutorial viene illustrata una variante con eco multiplo (in stile CPMG).\n",
        "\n",
        "<span id=\"what-refreshing-does-and-does-not-do\" />\n",
        "\n",
        "### Cosa fa e cosa non fa il refresh\n",
        "\n",
        "Quando si utilizza questo flusso di lavoro, è bene tenere a mente tre punti:\n",
        "\n",
        "* Le proprietà aggiornate sono presenti solo nell'oggetto backend che ti viene restituito. Non cambia nulla sul dispositivo stesso né nei dati di calibrazione che IBM Quantum comunica agli altri utenti.\n",
        "* I valori misurati rappresentano un’istantanea ottenuta con una metodologia specifica. Alcuni di essi, in particolare gli errori a due qubit stratificati e i valori di \" $T_2$ \" a eco singolo parallelo, vengono misurati in modo diverso rispetto ai dati di calibrazione riportati; pertanto, parte dello scostamento osservato è di natura metodologica piuttosto che dovuto alla deriva. Questo tutorial spiega dove ciò avviene.\n",
        "* La caratterizzazione stessa richiede tempo di elaborazione della QPU (circa 70 secondi per la suite completa su un processore Heron r2 ), il che rappresenta il prezzo da pagare per disporre di informazioni aggiornate.\n",
        "\n",
        "Il flusso di lavoro segue le quattro fasi di un modello Qiskit:\n",
        "\n",
        "* **Fase 1: Mappare gli input classici su un problema quantistico.** Scegli il dispositivo e l'insieme di proprietà da misurare.\n",
        "* **Fase 2: Ottimizzare il problema per l'esecuzione su hardware quantistico.** L'utilità realizza i circuiti sperimentali direttamente nei gate nativi del dispositivo e li parallelizza su tutto il chip.\n",
        "* **Passaggio 3: Eseguire il comando utilizzando \" Qiskit primitives \".** Gli esperimenti vengono eseguiti come processi Sampler all’interno di un batch.\n",
        "* **Fase 4: Eseguire la post-elaborazione e restituire il risultato nel formato classico desiderato.** Inserire i dati di misura nelle mappe di errore per singolo qubit, aggiornare il backend e confrontare le proprietà misurate con quelle riportate.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-03",
      "metadata": {},
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## Requisiti\n",
        "\n",
        "Prima di iniziare questo tutorial, assicurati di avere installato quanto segue:\n",
        "\n",
        "* Qiskit SDK v2.0 o versioni successive, con supporto [alla visualizzazione](/docs/api/qiskit/visualization)\n",
        "* Qiskit Runtime v0.40 o versioni successive (`pip install qiskit-ibm-runtime`)\n",
        "* Qiskit Device Benchmarking, che installa anche [Qiskit Experiments](https://qiskit-community.github.io/qiskit-experiments/) (`pip install git+https://github.com/qiskit-community/qiskit-device-benchmarking.git`)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-04",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## Configura\n",
        "\n",
        "Importa le librerie necessarie.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "cell-05",
      "metadata": {},
      "outputs": [],
      "source": [
        "import logging\n",
        "import sys\n",
        "\n",
        "import numpy as np\n",
        "from qiskit_ibm_runtime import Batch, QiskitRuntimeService\n",
        "\n",
        "from qiskit_device_benchmarking.utilities.characterization_utils import (\n",
        "    BackendCharacterization,\n",
        "    plot_characterization_comparison,\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-06",
      "metadata": {},
      "source": [
        "La suite di caratterizzazione avvia diversi esperimenti, invia più lavori ed elabora i risultati; l’operazione può richiedere in totale un paio di minuti. Abilita la registrazione a livello INFO in modo che ogni fase visualizzi lo stato di avanzamento man mano che procede.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "cell-07",
      "metadata": {},
      "outputs": [],
      "source": [
        "logger = logging.getLogger(\"qiskit_device_benchmarking\")\n",
        "logger.setLevel(logging.INFO)\n",
        "logger.addHandler(logging.StreamHandler(stream=sys.stdout))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-08",
      "metadata": {},
      "source": [
        "<span id=\"small-scale-simulator-example\" />\n",
        "\n",
        "## Esempio di simulatore su piccola scala\n",
        "\n",
        "Questo tutorial non include un esempio di simulazione. Il flusso di lavoro misura le imperfezioni fisiche di un dispositivo specifico: la velocità con cui i suoi qubit si rilassano e subiscono una defasatura, nonché la frequenza con cui i suoi gate e le operazioni di lettura falliscono. Un simulatore ideale non presenta nessuna di queste imperfezioni, quindi non c'è nulla da caratterizzare. Si potrebbe associare un modello di rumore sintetico a un backend fittizio, ma in tal caso gli esperimenti riproducerebbero solo i numeri inseriti dall'utente stesso. Per questo motivo, passiamo direttamente all’hardware, suddividendo il processo nei quattro passaggi tipici di un modello Qiskit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-09",
      "metadata": {},
      "source": [
        "<span id=\"large-scale-hardware-example\" />\n",
        "\n",
        "## Esempio di hardware su larga scala\n",
        "\n",
        "<span id=\"step-1-map-classical-inputs-to-a-quantum-problem\" />\n",
        "\n",
        "### Fase 1: Mappare gli input classici su un problema quantistico\n",
        "\n",
        "In questo flusso di lavoro il \"problema\" è il dispositivo stesso: gli input classici sono la QPU che si desidera caratterizzare e l'elenco delle proprietà da misurare, mentre gli esperimenti quantistici sono i circuiti di caratterizzazione generati a partire da essi.\n",
        "\n",
        "Per prima cosa, seleziona un backend. Questo tutorial utilizza un processore Heron r2 da 156 qubit `ibm_kingston`; è possibile sostituirlo con qualsiasi dispositivo IBM Quantum a cui si abbia accesso (oppure sceglierne uno con `service.least_busy()`).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "cell-10",
      "metadata": {},
      "outputs": [],
      "source": [
        "service = QiskitRuntimeService()\n",
        "device = \"ibm_kingston\"\n",
        "backend = service.backend(device)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-11",
      "metadata": {},
      "source": [
        "Successivamente, scegli quali proprietà misurare. È possibile superare qualsiasi sottoinsieme dei seguenti esperimenti:\n",
        "\n",
        "* `readout`: Esperimento SPAM (preparazione e misurazione dello stato)\n",
        "* `rb_1q`: benchmarking randomizzato su un singolo qubit isolato\n",
        "* `rb_2q`: benchmarking randomizzato simultaneo su due qubit derivante da un esperimento sulla fedeltà a livello di strato\n",
        "* `t2`: $T_2$ Esperimento di eco di Hahn (un singolo eco per impostazione predefinita)\n",
        "* `t1`: Esperimento di rilassamento “ $T_1$ ”\n",
        "\n",
        "Esegui la suite completa per ottenere un quadro completo del dispositivo; elimina le voci dall'elenco se ti interessano solo alcune proprietà e vuoi risparmiare tempo di elaborazione della QPU.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "cell-12",
      "metadata": {},
      "outputs": [],
      "source": [
        "experiments = [\"readout\", \"rb_1q\", \"rb_2q\", \"t1\", \"t2\"]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-13",
      "metadata": {},
      "source": [
        "<span id=\"step-2-optimize-problem-for-quantum-hardware-execution\" />\n",
        "\n",
        "### Fase 2: Ottimizzare il problema per l'esecuzione su hardware quantistico\n",
        "\n",
        "Nella maggior parte dei tutorial, è proprio a questo punto che si procederebbe alla transpilazione dei circuiti. In questo caso, `BackendCharacterization` se ne occupa internamente. Costruisce i circuiti sperimentali direttamente nei gate nativi del dispositivo, esegue gli esperimenti su singolo qubit su tutti i qubit in parallelo e pianifica i test di benchmarking a due qubit su livelli disgiunti della mappa di accoppiamento, in modo che l’intero dispositivo venga coperto con una manciata di processi. Grazie a questa parallelizzazione, l'intera suite richiede solo circa 70 secondi di tempo di elaborazione della QPU.\n",
        "\n",
        "Inizializza la classe che gestisce il flusso di lavoro:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "cell-14",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Initialize the class used to run the experiments\n",
        "characterizer = BackendCharacterization(backend)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-15",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-qiskit-primitives\" />\n",
        "\n",
        "### Passaggio 3: Eseguire il comando utilizzando Qiskit primitives\n",
        "\n",
        "Il metodo `run_experiments` crea i circuiti e li invia come processi [Sampler](/docs/guides/get-started-with-sampler). Eseguirlo all’interno di un contesto [`Batch`](/docs/guides/run-jobs-batch) in modo che i lavori vengano pianificati insieme sulla QPU e che il metodo restituisca un risultato solo dopo che tutti i lavori sono stati inviati. (È anche possibile eseguirlo al di fuori di un batch o all'interno di un `Session`.)\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Potresti visualizzare un avviso relativo al passaggio di un backend mentre è aperto un gestore del contesto di sessione. Si tratta di un fenomeno previsto e può essere tranquillamente ignorato.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "cell-16",
      "metadata": {},
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "base_primitive.get_mode_service_backend:WARNING:2026-07-14 14:23:02,051: A backend was passed in as the mode but a session context manager is open so this job will run inside this session/batch instead of in job mode.\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Building readout experiments\n",
            "Building 1Q RB experiments\n",
            "Building 2Q RB experiments\n",
            "Building T1 experiments\n",
            "Building T2 experiments\n",
            "Layered two-qubit RB submitted: ['d9b7tfu6hjac73ffba2g', 'd9b7tjug26ic73dfju3g', 'd9b7u3u6hjac73ffban0', 'd9b7u7rv6alc73csmicg']\n",
            "Readout job submitted: d9b7u8bv6alc73csmidg\n",
            "T1 experiment submitted: ['d9b7u8ug26ic73dfjuqg']\n",
            "T2 (Hahn) experiment submitted: ['d9b7u9fu62qs738othg0']\n",
            "Single-qubit RB submitted: ['d9b7v8m6hjac73ffbc40', 'd9b7veeg26ic73dfk040']\n"
          ]
        }
      ],
      "source": [
        "# Run the characterization experiments inside a Batch\n",
        "with Batch(backend=backend):\n",
        "    jobs = characterizer.run_experiments(experiments=experiments)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-17",
      "metadata": {},
      "source": [
        "Il metodo restituisce i lavori inviati sotto forma di dizionario con chiave \"esperimento\", utile per monitorarli sulla [dashboard di IBM Quantum Platform o per il debug.](/docs/guides/monitor-job)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "cell-18",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "{'rb_2q': [<RuntimeJobV2('d9b7tfu6hjac73ffba2g', 'sampler')>,\n",
              "  <RuntimeJobV2('d9b7tjug26ic73dfju3g', 'sampler')>,\n",
              "  <RuntimeJobV2('d9b7u3u6hjac73ffban0', 'sampler')>,\n",
              "  <RuntimeJobV2('d9b7u7rv6alc73csmicg', 'sampler')>],\n",
              " 'readout': [<RuntimeJobV2('d9b7u8bv6alc73csmidg', 'sampler')>],\n",
              " 't1': [<RuntimeJobV2('d9b7u8ug26ic73dfjuqg', 'sampler')>],\n",
              " 't2': [<RuntimeJobV2('d9b7u9fu62qs738othg0', 'sampler')>],\n",
              " 'rb_1q': [<RuntimeJobV2('d9b7v8m6hjac73ffbc40', 'sampler')>,\n",
              "  <RuntimeJobV2('d9b7veeg26ic73dfk040', 'sampler')>]}"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Print all the job IDs for debugging purposes\n",
        "jobs"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-19",
      "metadata": {},
      "source": [
        "<span id=\"step-4-post-process-and-return-result-in-desired-classical-format\" />\n",
        "\n",
        "### Fase 4: Elaborazione successiva e restituzione del risultato nel formato classico desiderato\n",
        "\n",
        "<span id=\"analyze-the-results\" />\n",
        "\n",
        "#### Analizzare i risultati\n",
        "\n",
        "Il metodo `analyze_results` attende il completamento dei lavori e effettua l'adattamento dei dati di misurazione: decadimenti esponenziali per $T_1$ e $T_2$, decadimenti della probabilità di sopravvivenza per gli esperimenti RB e matrici di assegnazione per la lettura dei risultati. Restituisce un dizionario di *mappe di errore*, con una voce per ogni proprietà misurata, ciascuna delle quali associa un qubit (o una coppia di qubit) al relativo valore misurato.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "cell-20",
      "metadata": {},
      "outputs": [],
      "source": [
        "error_maps = characterizer.analyze_results()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "cell-21",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The following error maps are available: ['readout_error', 'oneq_error_x', 'oneq_error_sx', 'lf_error_map', 't1_map', 't2_map']\n",
            "For example, readout error for qubit 0 is 0.007600000000000051\n"
          ]
        }
      ],
      "source": [
        "print(f\"The following error maps are available: {list(error_maps.keys())}\")\n",
        "readout_q0 = error_maps[\"readout_error\"][0]\n",
        "print(f\"For example, readout error for qubit 0 is {readout_q0}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-22",
      "metadata": {},
      "source": [
        "Le mappe riportano l’errore di lettura, gli errori relativi al singolo qubit e `x` ai gate `sx` , gli errori a due qubit stratificati (`lf_error_map`derivati dall’esperimento sulla fedeltà a livelli) e i tempi di $T_1$ e e di $T_2$ e espressi in secondi.\n",
        "\n",
        "<span id=\"update-the-backend-properties\" />\n",
        "\n",
        "#### Aggiorna le proprietà del backend\n",
        "\n",
        "Il metodo `update_backend` scrive i valori misurati nelle proprietà di una copia del backend e la restituisce. L'oggetto `backend` originale conserva i dati di calibrazione riportati, in modo da poterli confrontare, come illustrato di seguito. Ricorda che questo aggiornamento riguarda esclusivamente la tua sessione su Python; non comporta alcuna modifica sul dispositivo né per gli altri utenti.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "cell-23",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Updating readout error\n",
            "Updating single-qubit X error\n",
            "Updating single-qubit SX error\n",
            "Updating two-qubit error\n",
            "Updating T1\n",
            "Updating T2\n"
          ]
        }
      ],
      "source": [
        "backend_updated = characterizer.update_backend()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-24",
      "metadata": {},
      "source": [
        "<span id=\"compare-the-measured-properties-against-the-reported-ones\" />\n",
        "\n",
        "#### Confronta le proprietà misurate con quelle riportate\n",
        "\n",
        "Infine, tracciare un grafico delle proprietà misurate in tempo reale rispetto ai valori riportati dal backend. In ogni pannello i qubit (o le coppie di qubit) sono ordinati in base al valore misurato, quindi la curva di misura risulta per definizione regolare e la dispersione dei valori riportati attorno ad essa evidenzia i punti in cui i due dati non coincidono. Per l'RB a singolo qubit viene mostrato un unico grafico, poiché lo stesso errore misurato per gate viene assegnato sia al gate che `x` al gate `sx` . I limiti degli assi vengono scelti in base alla maggior parte dei dati, in modo che pochi valori anomali estremi non comprimano i grafici; eventuali punti al di fuori dell'intervallo vengono indicati in un'annotazione sul grafico (oppure si può scegliere `ylim` di sovrascrivere i limiti).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "cell-25",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/refresh-backend-properties-with-real-time-benchmarking/extracted-outputs/cell-25-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/refresh-backend-properties-with-real-time-benchmarking/extracted-outputs/cell-25-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/refresh-backend-properties-with-real-time-benchmarking/extracted-outputs/cell-25-2.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/refresh-backend-properties-with-real-time-benchmarking/extracted-outputs/cell-25-3.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/refresh-backend-properties-with-real-time-benchmarking/extracted-outputs/cell-25-4.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "plot_characterization_comparison(\n",
        "    old_props=backend.properties().to_dict(),\n",
        "    new_props=backend_updated.properties().to_dict(),\n",
        "    plots=[\"readout\", \"rb_1q\", \"rb_2q\", \"t1\", \"t2\"],\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-26",
      "metadata": {},
      "source": [
        "Questi grafici richiedono un'attenta lettura, poiché non tutti gli scostamenti tra le due curve indicano necessariamente una deriva del dispositivo:\n",
        "\n",
        "* **Lettura e errori sui singoli qubit** : i valori misurati corrispondono a quelli riportati per la maggior parte dei qubit, mentre il valore riportato per alcuni qubit si discosta notevolmente dalla curva dei valori misurati. Sono proprio queste discrepanze localizzate che questo flusso di lavoro è stato progettato per individuare.\n",
        "* **$T_1$** : I due insiemi di dati presentano una distribuzione casuale l’uno rispetto all’altro, senza alcun scostamento sistematico, il che è coerente con il fatto che l’ $T_1$ e fluttui naturalmente nel tempo.\n",
        "* **Errori a due qubit** : i valori misurati risultano sistematicamente *superiori* a quelli riportati. Ciò è prevedibile, poiché i valori riportati sono stati misurati su gate isolati, mentre l'esperimento sulla fedeltà dello strato prevede il funzionamento simultaneo di molti gate e quindi include il crosstalk. I valori stratificati sono più rilevanti per i circuiti profondi, ma non sono direttamente comparabili ai dati di calibrazione riportati.\n",
        "* **$T_2$** e: I valori misurati sono nettamente *inferiori* a quelli riportati per la maggior parte dei qubit. Anche in questo caso, la metodologia riveste un ruolo importante, come vedremo nella sezione successiva.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-27",
      "metadata": {},
      "source": [
        "<span id=\"inspect-individual-experiment-results\" />\n",
        "\n",
        "#### Esaminare i risultati dei singoli esperimenti\n",
        "\n",
        "È inoltre possibile esaminare i risultati grezzi dei singoli esperimenti di caratterizzazione tramite la proprietà `experiment_data` , che restituisce gli oggetti `ExperimentData` [Qiskit Experiments](https://qiskit-community.github.io/qiskit-experiments/) sottostanti. Ad esempio, il grafico seguente mostra la curva di decadimento misurata dell' $T_1$ e di un singolo qubit; ciò è utile per verificare la qualità di un adattamento prima di considerare attendibile il valore ottenuto.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "cell-28",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "156 figures available, e.g. T1_Q0_c78ef792.svg\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/refresh-backend-properties-with-real-time-benchmarking/extracted-outputs/cell-28-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "t1_data = characterizer.experiment_data[\"t1\"]\n",
        "\n",
        "# Each qubit has its own fit figure\n",
        "n_figs = len(t1_data.figure_names)\n",
        "print(f\"{n_figs} figures available, e.g. {t1_data.figure_names[0]}\")\n",
        "\n",
        "# Show the T1 decay curve of the first qubit\n",
        "t1_data.figure(0)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-29",
      "metadata": {},
      "source": [
        "<span id=\"measure-t2-with-a-dynamical-decoupling-train\" />\n",
        "\n",
        "#### Misura dell’ T2 e con una catena di disaccoppiamento dinamico\n",
        "\n",
        "Per impostazione predefinita, l'esperimento \" $T_2$ \" applica un singolo eco di Hahn e misura tutti i qubit in parallelo; ciò, come ha mostrato il grafico di confronto riportato sopra, può portare a valori di \" $T_2$ \" notevolmente inferiori rispetto a quelli riportati dal backend. Un'ipotesi riguarda il numero di echi: i valori riportati potrebbero essere stati calibrati mediante disaccoppiamento dinamico, che sopprime il rumore a bassa frequenza. Per verificarlo, eseguire una caratterizzazione “ $T_2$ ” con il parametro impostato `t2_num_echoes` su un valore più elevato, in modo da applicare una sequenza di impulsi di eco in stile CPMG. I ritardi rappresentano il tempo totale di evoluzione libera in entrambi i casi, pertanto i valori di $T_2$ e ricavati sono direttamente comparabili ai risultati ottenuti con l’eco singolo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "cell-30",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Building T2 experiments\n",
            "T2 (Hahn) experiment submitted: ['d9b96s6g26ic73dflcn0']\n",
            "Updating T2\n"
          ]
        }
      ],
      "source": [
        "# Run a T2-only characterization using a CPMG-style train of 8 echoes\n",
        "characterizer_dd = BackendCharacterization(backend)\n",
        "backend_updated_dd = characterizer_dd.run_and_update(\n",
        "    experiments=[\"t2\"], t2_num_echoes=8\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "cell-31",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/refresh-backend-properties-with-real-time-benchmarking/extracted-outputs/cell-31-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Median T2 — reported: 142 us | single echo: 53 us | 8-echo CPMG: 56 us\n"
          ]
        }
      ],
      "source": [
        "# Compare the multi-echo T2 against the backend-reported values\n",
        "plot_characterization_comparison(\n",
        "    old_props=backend.properties().to_dict(),\n",
        "    new_props=backend_updated_dd.properties().to_dict(),\n",
        "    plots=[\"t2\"],\n",
        "    title_prefix=\"8-echo CPMG\",\n",
        ")\n",
        "\n",
        "# Compare medians across the reported values, the single-echo run,\n",
        "# and the 8-echo run\n",
        "reported_t2s = [\n",
        "    prop[\"value\"]\n",
        "    for qubit in backend.properties().to_dict()[\"qubits\"]\n",
        "    for prop in qubit\n",
        "    if prop[\"name\"] == \"T2\"\n",
        "]\n",
        "t2_reported = np.median(reported_t2s)\n",
        "t2_single = np.median(list(error_maps[\"t2_map\"].values())) * 1e6\n",
        "t2_dd = (\n",
        "    np.median(list(characterizer_dd.analyze_results()[\"t2_map\"].values()))\n",
        "    * 1e6\n",
        ")\n",
        "print(\n",
        "    f\"Median T2 — reported: {t2_reported:.0f} us | \"\n",
        "    f\"single echo: {t2_single:.0f} us | 8-echo CPMG: {t2_dd:.0f} us\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-32",
      "metadata": {},
      "source": [
        "In questa esecuzione, gli echi aggiuntivi non hanno praticamente modificato il risultato: la mediana degli 8 echi (56 µs) è vicina a quella del singolo eco (53 µs) ed entrambe rimangono ben al di sotto della mediana riportata (142 µs). Il numero di echi da solo non spiega questo divario; entrano in gioco altre differenze metodologiche, quali i dettagli della procedura di calibrazione, la misurazione di tutti i qubit in parallelo anziché singolarmente, e così via.\n",
        "\n",
        "La lezione pratica è quella di considerare con cautela i confronti relativi all’ $T_2$ e (e all’errore a due qubit a più livelli) tra le diverse metodologie. I valori aggiornati costituiscono un’istantanea coerente, ottenuta in condizioni simili a quelle di un carico di lavoro reale, il che li rende particolarmente adatti per confrontare i qubit tra loro o per monitorare l’andamento di un dispositivo nel tempo. Una discrepanza rispetto ai dati di calibrazione riportati, tuttavia, non costituisce automaticamente una prova di deriva.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-33",
      "metadata": {},
      "source": [
        "<span id=\"steps-1–4-compressed-into-a-single-call\" />\n",
        "\n",
        "### I passaggi da 1 a 4 raggruppati in un'unica chiamata\n",
        "\n",
        "Nell'uso quotidiano, i risultati intermedi servono raramente. Il metodo `run_and_update` raggruppa tutte le operazioni eseguite in precedenza (creazione, invio, adattamento e aggiornamento) in un'unica chiamata che restituisce il backend aggiornato. Accetta lo stesso `experiments` elenco (e inoltra opzioni come `t2_num_echoes`), e può anch’esso essere racchiuso in un contesto `Session` `Batch` o.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  La cella seguente non restituisce alcun risultato finché tutti i lavori e le operazioni di post-elaborazione non sono stati completati.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "cell-34",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Building readout experiments\n",
            "Building 1Q RB experiments\n",
            "Building 2Q RB experiments\n",
            "Building T1 experiments\n",
            "Building T2 experiments\n",
            "Layered two-qubit RB submitted: ['d9b7oqnu62qs738otat0', 'd9b7p76g26ic73dfjolg', 'd9b7pnm6hjac73ffb57g', 'd9b7q4fu62qs738otce0']\n",
            "Readout job submitted: d9b7q4mg26ic73dfjprg\n",
            "T1 experiment submitted: ['d9b7q57u62qs738otcfg']\n",
            "T2 (Hahn) experiment submitted: ['d9b7q5m6hjac73ffb5pg']\n",
            "Single-qubit RB submitted: ['d9b7r4e6hjac73ffb71g', 'd9b7reu6hjac73ffb7d0']\n",
            "Updating readout error\n",
            "Updating single-qubit X error\n",
            "Updating single-qubit SX error\n",
            "Updating two-qubit error\n",
            "Updating T1\n",
            "Updating T2\n"
          ]
        }
      ],
      "source": [
        "# Initialize a fresh characterizer\n",
        "characterizer = BackendCharacterization(backend)\n",
        "\n",
        "# Run all of the experiments and update the backend in a single call\n",
        "backend_updated = characterizer.run_and_update(experiments=experiments)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-35",
      "metadata": {},
      "source": [
        "L'oggetto `backend_updated` aggiornato è ora pronto per essere utilizzato ovunque le proprietà del backend vengano integrate nel tuo flusso di lavoro. Prova questa procedura insieme al tutorial “[Benchmarking in](/docs/tutorials/real-time-benchmarking-for-qubit-selection) tempo reale per la selezione dei qubit” per scegliere i qubit più performanti durante la transpilazione di un circuito. Poiché il dispositivo continua a presentare una deriva, aggiorna le proprietà in prossimità del momento in cui esegui effettivamente il tuo carico di lavoro.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cell-36",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Passi successivi\n",
        "\n",
        "Se questo lavoro ti è sembrato interessante, potrebbero interessarti i seguenti materiali:\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Suggerimenti\">\n",
        "  * Utilizza le proprietà aggiornate per selezionare qubit migliori nel tutorial [“Benchmarking in tempo reale per la selezione dei qubit”](/docs/tutorials/real-time-benchmarking-for-qubit-selection)\n",
        "  * Scopri come vengono presentati i dati di calibrazione riportati nella guida [informativa sulla](/docs/guides/qpu-information) QPU\n",
        "  * Scopri i singoli esperimenti di caratterizzazione nella [documentazione](https://qiskit-community.github.io/qiskit-experiments/) di Qiskit Experiments\n",
        "  * Scopri altri benchmark a livello di dispositivo nel [repository](https://github.com/qiskit-community/qiskit-device-benchmarking) Qiskit Device Benchmarking\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": 5
}