{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "0d58aa59",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"QESEM - Una funzione Qiskit di Qedma\"\n",
        "description: \"Esegui circuiti quantistici su QPU rumorose per ottenere risultati altamente accurati e privi di errori con overhead di tempo QPU altamente efficienti, vicini ai limiti fondamentali.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore DESY Multibase, Quasicrystal, Downfolding, Aharonov, Goldack, wavefunctions, Sakuma */}\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dde95705",
      "metadata": {},
      "source": [
        "<span id=\"qesem-a-qiskit-function-by-qedma\" />\n",
        "\n",
        "# QESEM: una funzione Qiskit di Qedma\n",
        "\n",
        "*Consulta la [documentazione dell'API](/docs/api/functions/qedma-qesem)*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6256578e",
      "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 presente in questa pagina è stato sviluppato tenendo conto dei seguenti requisiti.\n",
        "    Si consiglia di utilizzare queste versioni o quelle più recenti.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.0\n",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "13528739",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\" title=\"Nota\">\n",
        "  Le funzioni Qiskit sono una funzione sperimentale disponibile solo per gli utenti di IBM Quantum® Premium Plan, Flex Plan e On-Prem (tramite IBM Quantum Platform API) Plan. Sono in stato di anteprima e sono soggetti a modifiche.\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"overview\" />\n",
        "\n",
        "## Panoramica\n",
        "\n",
        "Sebbene le unità di elaborazione quantistica siano notevolmente migliorate negli ultimi anni, gli errori dovuti al rumore e alle imperfezioni dell'hardware esistente rimangono una sfida centrale per gli sviluppatori di algoritmi quantistici. Man mano che il settore si avvicina a calcoli quantistici su scala industriale che non possono essere verificati in modo classico, le soluzioni per eliminare il rumore con una precisione garantita stanno diventando sempre più importanti. Per superare questa sfida, Qedma ha sviluppato Quantum Error Mitigation (QESEM), perfettamente integrato su IBM Quantum Platform come [funzione](/docs/guides/functions) Qiskit.\n",
        "\n",
        "Con QESEM, gli utenti possono eseguire i propri circuiti quantistici su QPU soggette a rumore per ottenere risultati altamente accurati e privi di errori, con tempi di elaborazione della QPU estremamente efficienti, vicini ai limiti fondamentali. A tal fine, QESEM si avvale di una suite di metodi proprietari sviluppati da Qedma per la caratterizzazione e la riduzione degli errori. Le tecniche di riduzione degli errori comprendono l'ottimizzazione dei gate, la transpilazione sensibile al rumore, la soppressione degli errori (ES) e la mitigazione imparziale degli errori (EM). Grazie alla combinazione di questi metodi basati sulla caratterizzazione, gli utenti possono ottenere risultati affidabili e privi di errori per circuiti quantistici generici di grandi dimensioni, aprendo la strada ad applicazioni che altrimenti non sarebbero realizzabili.\n",
        "\n",
        "Per una descrizione completa dei componenti sottostanti, nonché una dimostrazione su scala industriale, consultare il documento [Reliable high-accuracy error mitigation for utility-scale quantum circuits](https://arxiv.org/abs/2508.10997) (Mitigazione affidabile e altamente accurata degli errori per circuiti quantistici su scala industriale).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5f761442",
      "metadata": {},
      "source": [
        "<span id=\"description\" />\n",
        "\n",
        "## Descrizione\n",
        "\n",
        "È possibile utilizzare la funzione QESEM di Qedma per stimare ed eseguire facilmente i circuiti con la soppressione e la mitigazione degli errori, ottenendo volumi di circuiti più grandi e precisioni più elevate. Per utilizzare il QESEM, si fornisce un circuito quantistico, una serie di osservabili da misurare, un obiettivo di precisione statistica per ogni osservabile e una QPU scelta. Prima di eseguire il circuito con la precisione desiderata, è possibile stimare il tempo richiesto dalla QPU in base a un calcolo analitico che non richiede l'esecuzione del circuito. Una volta soddisfatti della stima dei tempi di QPU, è possibile eseguire il circuito con QESEM.\n",
        "\n",
        "Quando si esegue un circuito, QESEM esegue un protocollo di caratterizzazione del dispositivo su misura per il circuito, fornendo un modello di rumore affidabile per gli errori che si verificano nel circuito. Sulla base della caratterizzazione, QESEM implementa innanzitutto una transpilazione sensibile al rumore per mappare il circuito di input su un insieme di qubit e gate fisici, riducendo al minimo il rumore che influenza l'osservabile target. Questi includono i gate disponibili in modo nativo (CX/CZ sui dispositivi IBM® ), nonché gate aggiuntivi ottimizzati da QESEM, che formano il set di gate esteso di QESEM. QESEM esegue quindi una serie di circuiti ES ed EM basati sulla caratterizzazione sulla QPU e raccoglie i risultati delle misurazioni. Questi vengono poi sottoposti a post-elaborazione classica per fornire un valore atteso non distorto e una barra di errore per ciascun osservabile, in corrispondenza con l'accuratezza richiesta.\n",
        "\n",
        "![Panoramica di Qedma QESEM](https://quantum.cloud.ibm.com/docs/images/guides/qedma-qesem/overview.svg)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "74823696",
      "metadata": {},
      "source": [
        "È stato dimostrato che il QESEM è in grado di fornire risultati di alta precisione per una varietà di applicazioni quantistiche e sui più grandi volumi di circuiti oggi realizzabili. QESEM offre le seguenti funzionalità rivolte all'utente, dimostrate nella sezione dei benchmark che segue:\n",
        "\n",
        "* **Accuratezza garantita:** QESEM fornisce stime imparziali dei valori attesi delle grandezze osservabili. Il suo metodo EM è dotato di garanzie teoriche che, insieme alla caratterizzazione all'avanguardia di Qedma, assicurano che la mitigazione converga verso l'uscita del circuito privo di rumore fino alla precisione specificata dall'utente. A differenza di molti metodi EM euristici che sono soggetti a errori sistematici o distorsioni, l'accuratezza garantita di QESEM è essenziale per assicurare risultati affidabili nei circuiti quantistici generici e negli osservabili.\n",
        "* **Scalabilità a QPU di grandi dimensioni:** il tempo QPU di QESEM dipende dai volumi dei circuiti, ma è altrimenti indipendente dal numero di qubit. Qedma ha dimostrato QESEM sui più grandi dispositivi quantistici oggi disponibili, tra cui i dispositivi Eagle da 127 qubit e Heron da 133 qubit dell' IBM Quantum.\n",
        "* **Indipendente dalle applicazioni:** Il QESEM è stato dimostrato in diverse applicazioni, tra cui la simulazione hamiltoniana, VQE, QAOA e la stima dell'ampiezza. Gli utenti possono inserire qualsiasi circuito quantistico e osservabile da misurare e ottenere risultati precisi e privi di errori. Le uniche limitazioni sono dettate dalle specifiche hardware e dal tempo assegnato alla QPU, che determinano i volumi di circuito accessibili e le precisioni di uscita. Al contrario, molte soluzioni per la riduzione degli errori sono specifiche per l'applicazione o coinvolgono euristiche non controllate, rendendole inapplicabili a circuiti e applicazioni quantistiche generiche.\n",
        "* **Set di gate esteso:** QESEM supporta gate ad angolo frazionario e fornisce gate QEDMA ottimizzati ad angolo frazionario $Rzz(\\theta)$ sui dispositivi IBM Quantum Heron e Eagle. Questo set di gate esteso consente una compilazione più efficiente e sblocca volumi di circuiti fino a 2 volte superiori rispetto alla compilazione CX/CZ predefinita.\n",
        "* **Osservabili multibase:** QESEM supporta osservabili in ingresso composte da molte stringhe di Pauli non comunicanti, come gli hamiltoniani generici. La scelta delle basi di misura e l'ottimizzazione dell'allocazione delle risorse della QPU (scatti e circuiti) viene quindi eseguita automaticamente da QESEM per ridurre al minimo il tempo richiesto dalla QPU per la precisione richiesta. Questa ottimizzazione, che tiene conto delle fedeltà hardware e delle velocità di esecuzione, consente di eseguire circuiti più profondi e di ottenere precisioni più elevate.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "57b41ab0",
      "metadata": {},
      "source": [
        "<span id=\"benchmarks\" />\n",
        "\n",
        "## Benchmark\n",
        "\n",
        "QESEM è stato testato su un'ampia gamma di casi d'uso e applicazioni. I seguenti esempi possono aiutare a valutare quali tipi di carichi di lavoro è possibile eseguire con QESEM.\n",
        "\n",
        "Una cifra di merito fondamentale per quantificare la durezza della mitigazione degli errori e della simulazione classica per un determinato circuito e osservabile è il **volume attivo** : il numero di porte CNOT che influenzano l'osservabile nel circuito. Il volume attivo dipende dalla profondità e dalla larghezza del circuito, dal peso dell'osservabile e dalla struttura del circuito, che determina il cono di luce dell'osservabile. Per ulteriori dettagli, si veda l'intervento del [2024 IBM Quantum Summit](https://www.youtube.com/watch?v=Hd-IGvuARfE\\&t=1730s). Il QESEM fornisce un valore particolarmente elevato nel regime ad alto volume, fornendo risultati affidabili per circuiti e osservabili generici.\n",
        "\n",
        "![Volume attivo](https://quantum.cloud.ibm.com/docs/images/guides/qedma-qesem/active_volume.svg)\n",
        "\n",
        "| Applicazione                           | Numero di qubit | Periferica    | Descrizione del circuito                                    | Accuratezza | Tempo totale | Utilizzo del tempo di esecuzione |\n",
        "| -------------------------------------- | --------------- | ------------- | ----------------------------------------------------------- | ----------- | ------------ | -------------------------------- |\n",
        "| Circuito VQE                           | 8               | Aquila ( r3 ) | 21 strati totali, 9 basi di misura, 1D catena               | 98%         | 35 min       | 14 min                           |\n",
        "| Calciomercato Ising                    | 28              | Aquila ( r3 ) | 3 strati unici x 3 passi, 2D topologia heavy-hex            | 97%         | 22 min       | 4 min                            |\n",
        "| Calciomercato Ising                    | 28              | Aquila ( r3 ) | 3 strati unici x 8 passi, 2D topologia heavy-hex            | 97%         | 116 min      | 23 min                           |\n",
        "| Simulazione hamiltoniana trotterizzata | 40              | Aquila ( r3 ) | 2 strati unici x 10 passi di Trotter, 1D catena             | 97%         | 3 ore        | 25 min                           |\n",
        "| Simulazione hamiltoniana trotterizzata | 119             | Aquila ( r3 ) | 3 strati unici x 9 passi di Trotter, 2D topologia heavy-hex | 95%         | 6.5 ore      | 45 min                           |\n",
        "| Calciomercato Ising                    | 136             | Airone ( r2 ) | 3 strati unici x 15 passi, 2D topologia heavy-hex           | 99%         | 52 min       | 9 min                            |\n",
        "\n",
        "La precisione viene misurata rispetto al valore ideale dell'osservabile: $\\frac{\\langle O \\rangle_{ideal} - \\epsilon}{\\langle O \\rangle_{ideal}}$, dove ' $\\epsilon$ ' è la precisione assoluta dell'attenuazione (impostata dall'input dell'utente) e $\\langle O \\rangle_{ideal}$ è l'osservabile al circuito senza rumore.\n",
        "'Runtime usage' misura l'uso del benchmark in modalità batch (somma dell'uso dei singoli lavori), mentre 'total time' misura l'uso in modalità sessione (experiment wall time), che include tempi classici e di comunicazione aggiuntivi. QESEM è disponibile per l'esecuzione in entrambe le modalità, in modo che gli utenti possano sfruttare al meglio le risorse disponibili.\n",
        "\n",
        "I circuiti Ising a 28 qubit simulano il Quasicristallo a tempo discreto studiato da Shinjo et al. (cfr [arXiv 2403.16718](https://arxiv.org/abs/2403.16718) e [Q2B24 Tokyo](https://www.youtube.com/watch?v=tQW6FdLc6zo) ) su tre anelli connessi di ibm\\_kawasaki. I parametri del circuito presi in considerazione sono $(\\theta_x, \\theta_z) = (0.9 \\pi, 0)$, con uno stato iniziale ferromagnetico $| \\psi_0 \\rangle = | 0 \\rangle ^{\\otimes n}$. L'osservabile misurato è il valore assoluto della magnetizzazione $M = |\\frac{1}{28} \\sum_{i=0}^{27} \\langle Z_i \\rangle|$. L'esperimento di Kicked Ising su scala utility è stato eseguito sui 136 migliori qubit di ibm\\_fez; questo particolare benchmark è stato eseguito all'angolo di Clifford $(\\theta_x, \\theta_z) = (\\pi, 0)$, al quale il volume attivo cresce lentamente con la profondità del circuito, il che, insieme all'elevata fedeltà del dispositivo, consente di ottenere un'elevata precisione con un breve tempo di esecuzione.\n",
        "\n",
        "I circuiti di simulazione hamiltoniana trotterizzata sono per un modello Ising a campo trasverso con angoli frazionari: $(\\theta_{zz}, \\theta_x) = (\\pi / 4, \\pi /8)$ e $(\\theta_{zz}, \\theta_x) = (\\pi / 6, \\pi / 8)$ corrispondenti (vedi [Q2B24 Tokyo](https://www.youtube.com/watch?v=tQW6FdLc6zo) ). Il circuito utility-scale è stato eseguito sui 119 migliori qubit di ibm\\_brisbane, mentre l'esperimento a 40 qubit è stato eseguito sulla migliore catena disponibile. L'accuratezza è riportata per la magnetizzazione; risultati di alta precisione sono stati ottenuti anche per osservabili di peso superiore.\n",
        "\n",
        "Il circuito VQE è stato sviluppato insieme ai ricercatori del Center for Quantum Technology and Applications del Deutsches Elektronen-Synchrotron (DESY). L'osservabile target in questo caso era un'hamiltoniana costituita da un gran numero di stringhe di Pauli non comunicanti, sottolineando le prestazioni ottimizzate di QESEM per le osservabili multi-base. La mitigazione è stata applicata a un'ipotesi di ottimizzazione classica; sebbene questi risultati siano ancora inediti, si otterranno risultati della stessa qualità per circuiti diversi con proprietà strutturali simili.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d6fb65de",
      "metadata": {},
      "source": [
        "<span id=\"get-started\" />\n",
        "\n",
        "## Introduzione\n",
        "\n",
        "Autenticati utilizzando la tua [chiave API IBM Quantum Platform](http://quantum.cloud.ibm.com/) e seleziona la funzione QESEM Qiskit come segue. (Questo frammento di codice presuppone che tu abbia già [salvato il tuo account](/docs/guides/functions-get-started#install-qiskit-functions-catalog-client) nell'ambiente locale.)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "95a715d2",
      "metadata": {},
      "outputs": [],
      "source": [
        "import qiskit\n",
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "catalog = QiskitFunctionsCatalog(channel=\"ibm_quantum_platform\")\n",
        "\n",
        "# verify that you have access to the function\n",
        "catalog.list()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "2d78b033",
      "metadata": {},
      "outputs": [],
      "source": [
        "# load the function\n",
        "qesem_function = catalog.load(\"qedma/qesem\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5f0120d8",
      "metadata": {},
      "source": [
        "<span id=\"examples\" />\n",
        "\n",
        "## Esempi\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7d102971",
      "metadata": {},
      "source": [
        "<span id=\"time-estimation-job-example\" />\n",
        "\n",
        "### Esempio di lavoro di stima dei tempi\n",
        "\n",
        "Il processo di stima del tempo è utile per stimare il tempo di elaborazione richiesto dalla QPU per un dato `pub` e `backend_name`. `backend_name` può anche essere impostato su qualsiasi backend del simulatore; ad esempio, `fake_fez`.\n",
        "\n",
        "QESEM utilizza un metodo EM quasi-probabilistico basato sulla caratterizzazione. Questo metodo comporta un sovraccarico di tempo della QPU che varia approssimativamente secondo la seguente relazione:\n",
        "\n",
        "$T_{QPU} = a \\frac{e^{\\alpha IF\\cdot V_a}}{\\epsilon^2} + b$\n",
        "\n",
        "Dove $V_a$ è il volume attivo del circuito, $\\epsilon$ è la precisione desiderata e $IF$ è l’infedeltà dei gate nativi.\n",
        "\n",
        "Si noti che `\"estimate_time_only\": \"empirical\"` impiega alcuni minuti di tempo QPU per stimare il tempo necessario per l'esecuzione del processo (se il backend è un dispositivo reale; se invece si tratta di un simulatore, non viene utilizzato alcun tempo QPU). Di solito ci vogliono circa 5 minuti, ma non più di 10 minuti. Se l'infedeltà varia drasticamente tra l'operazione di stima empirica dei tempi e quella di mitigazione, anche il tempo di elaborazione della QPU subirà una variazione drastica.\n",
        "\n",
        "Per iniziare, provate questo esempio di base per stimare il tempo necessario alla QPU per eseguire QESEM per un dato `pub`:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "d56e1440",
      "metadata": {},
      "outputs": [],
      "source": [
        "backend_name = \"fake_fez\"\n",
        "\n",
        "circ = qiskit.QuantumCircuit(5)\n",
        "circ.cx(0, 1)\n",
        "circ.cx(2, 3)\n",
        "circ.cx(1, 2)\n",
        "circ.cx(3, 4)\n",
        "\n",
        "avg_magnetization = qiskit.quantum_info.SparsePauliOp.from_sparse_list(\n",
        "    [(\"Z\", [q], 1 / 5) for q in range(5)], num_qubits=5\n",
        ")\n",
        "other_observable = qiskit.quantum_info.SparsePauliOp.from_sparse_list(\n",
        "    [(\"ZZ\", [0, 1], 1.0), (\"XZ\", [1, 4], 0.5)], num_qubits=5\n",
        ")\n",
        "\n",
        "time_estimation_job = qesem_function.run(\n",
        "    pubs=[(circ, [avg_magnetization, other_observable])],\n",
        "    options={\n",
        "        \"estimate_time_only\": \"empirical\",\n",
        "    },\n",
        "    backend_name=backend_name,  # example: \"fake_fez\", \"ibm_fez\"\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "a6eb4bda04796ac5",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2026-05-03T12:04:42.901739Z",
          "start_time": "2026-05-03T12:02:20.288020Z"
        }
      },
      "outputs": [],
      "source": [
        "time_estimate_result = (\n",
        "    time_estimation_job.result()\n",
        ")  # a list of results per pub (circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5ec8053b",
      "metadata": {},
      "source": [
        "Il seguente frammento di codice illustra come recuperare diverse metriche di esecuzione dal processo di stima dei tempi (`estimate_time_only` è impostato):\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 106,
      "id": "77a9dca8efb1a37b",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2026-05-12T11:22:06.848571Z",
          "start_time": "2026-05-12T11:22:06.838844Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The estimated QPU time for mitigation for this PUB is: 300\n",
            "The QPU time that this time estimation job took is (here it is 0 because we used fake_fez): 0\n",
            "Gates fidelity measured during the experiment: {'CZ': 0.9951354916722668, 'ID1Q': 0.9991246627329172}\n",
            "Total shots: 220000\n",
            "Resource usage breakdown: {'RUNNING: MAPPING': {'CPU_TIME': 33.6066133165732, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: OPTIMIZING_FOR_HARDWARE': {'CPU_TIME': 184.53575124032795, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: WAITING_FOR_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: EXECUTING_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: POST_PROCESSING': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}}\n"
          ]
        }
      ],
      "source": [
        "pub_result = time_estimate_result[0]\n",
        "\n",
        "print(\n",
        "    f\"The estimated QPU time for mitigation for this PUB is: {pub_result.metadata['time_estimation_sec']}\"\n",
        ")\n",
        "print(\n",
        "    f\"The QPU time that this time estimation job took is (here it is 0 because we used fake_fez): {pub_result.metadata['total_qpu_time']}\"\n",
        ")\n",
        "print(\n",
        "    f\"Gates fidelity measured during the experiment: {pub_result.metadata['gate_fidelities']}\"\n",
        ")\n",
        "print(f\"Total shots: {pub_result.metadata['total_shots']}\")\n",
        "print(f\"Resource usage breakdown: {pub_result.metadata['resource_usage']}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5f68f983189f00a1",
      "metadata": {},
      "source": [
        "Quando è abilitata la stima empirica dei tempi, QESEM esegue un numero limitato di circuiti per fornire una stima più accurata dei tempi della QPU. I risultati relativi alla mitigazione ottenuti da questi circuiti sono disponibili nel `empirical_estimation_mitigation_results` campo del lavoro.\n",
        "\n",
        "Poiché questi risultati derivano da un campione limitato di circuiti, sono notevolmente meno accurati rispetto ai risultati finali ottenuti dall'analisi completa di mitigazione QESEM. Tuttavia, quando il circuito è di piccole dimensioni o la precisione richiesta è bassa, la mitigazione effettuata durante la stima empirica dei tempi potrebbe essere sufficiente per raggiungere la precisione desiderata, e potrebbe non essere necessario eseguire l'intero processo di mitigazione.\n",
        "\n",
        "Il `empirical_estimation_mitigation_results` campo è un elenco di `PrimitiveResult` oggetti per ciascun parametro di input. Se il circuito non è parametrizzato, la lista avrà lunghezza 1.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "7acca648911dacd5",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2026-05-05T13:41:38.131003Z",
          "start_time": "2026-05-05T13:41:38.127666Z"
        }
      },
      "outputs": [],
      "source": [
        "empirical_estimation_mitigation_results = time_estimate_result[0].metadata[\n",
        "    \"empirical_estimation_mitigation_results\"\n",
        "][0]  # a list per parameter"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "60b482803339ce27",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2026-05-05T15:23:58.817671Z",
          "start_time": "2026-05-05T15:23:58.811680Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Partial results for the observables:\n",
            "    Mitigated expectation values: [1.00347302 1.00693905]\n",
            "    Mitigated error bars: [0.00304061 0.00714276]\n",
            "    Number of shots used for mitigation: 180000\n",
            "    Qubit mapping: [[[0, 136], [1, 143], [2, 142], [3, 141], [4, 140]]]\n",
            "    Number of measurement bases: 2\n",
            "\n",
            "Results for each observable:\n",
            "Observable 1: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "    QESEM mitigated value: 1.003473015776871 ± 0.0030406128032204015\n",
            "Observable 2: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "    QESEM mitigated value: 1.0069390542613554 ± 0.0071427606736885925\n"
          ]
        }
      ],
      "source": [
        "print(\"Partial results for the observables:\")\n",
        "\n",
        "print(\n",
        "    f\"    Mitigated expectation values: {empirical_estimation_mitigation_results.data.evs}\"\n",
        ")\n",
        "print(\n",
        "    f\"    Mitigated error bars: {empirical_estimation_mitigation_results.data.stds}\"\n",
        ")\n",
        "print(\n",
        "    f\"    Number of shots used for mitigation: {empirical_estimation_mitigation_results.metadata['mitigation_shots']}\"\n",
        ")\n",
        "transpiled_circ = empirical_estimation_mitigation_results.metadata[\n",
        "    \"transpiled_circ\"\n",
        "]\n",
        "print(f\"    Qubit mapping: {transpiled_circ['qubit_maps']}\")\n",
        "print(\n",
        "    f\"    Number of measurement bases: {transpiled_circ['num_measurement_bases']}\\n\"\n",
        ")\n",
        "\n",
        "# results per obs\n",
        "emp_obs_results = empirical_estimation_mitigation_results.metadata[\"results\"][\n",
        "    0\n",
        "]\n",
        "# print(f\"Results for each observable: {results}\")\n",
        "print(\"Results for each observable:\")\n",
        "\n",
        "for i, (obs_array, result_dict) in enumerate(emp_obs_results):\n",
        "    # obs_array, result_dict = results\n",
        "    print(f\"Observable {i+1}: {obs_array}\")\n",
        "    print(\n",
        "        f\"    QESEM mitigated value: {result_dict['qesem']['value']} \\u00b1 {result_dict['qesem']['error_bar']}\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ae10a4c8",
      "metadata": {},
      "source": [
        "<span id=\"qesem-mitigation-job-example\" />\n",
        "\n",
        "### Esempio di attività di mitigazione QESEM\n",
        "\n",
        "L'esempio seguente esegue un lavoro QESEM:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "e7351d6b",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2026-05-05T13:42:11.391952Z",
          "start_time": "2026-05-05T13:42:01.266109Z"
        }
      },
      "outputs": [],
      "source": [
        "sample_job = qesem_function.run(\n",
        "    pubs=[(circ, [avg_magnetization, other_observable])],\n",
        "    backend_name=backend_name,  # example: \"ibm_fez\"\n",
        "    # options = {\n",
        "    #     \"estimate_time_only\": \"empirical\",\n",
        "    #     \"default_precision\": 0.2,  # Default precision is applied to all pubs that don't have a precision specified, see API reference for more details\n",
        "    #     \"max_execution_time\": 3600,  # You can specify a maximum QPU time in seconds, see API reference for more details\n",
        "    #     \"transpilation_level\": \"standard\",  # \"minimal_with_layout_opt\" for minimal transpilation, see API reference for more details\n",
        "    #     \"parallel_execution\": True,  # True for parallel execution, see API reference for more details\n",
        "    # },\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f7f7fe68",
      "metadata": {},
      "source": [
        "Per una descrizione dettagliata di ciascun campo di immissione e di ciascuna opzione, consultare la [guida di riferimento dell'API QESEM](/docs/api/functions/qedma-qesem).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dfe99043",
      "metadata": {},
      "source": [
        "È possibile utilizzare le API Qiskit Serverless già note per controllare lo stato del carico di lavoro di Qiskit Function o per restituire i risultati:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "id": "856fe992",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "3ac6b2df-15b0-4dc0-8f48-cf14bd20a1c8\n",
            "DONE\n"
          ]
        }
      ],
      "source": [
        "# Print the ID so you can use it later, if necessary\n",
        "print(sample_job.job_id)\n",
        "print(sample_job.status())\n",
        "sample_result = sample_job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a9e51542",
      "metadata": {},
      "source": [
        "Il seguente frammento di codice mostra come recuperare i risultati delle misure di mitigazione e le metriche di esecuzione. Questi contengono dati essenziali che consentono di comprendere più a fondo in che modo i diversi parametri influenzano l'esecuzione del QESEM. Potrebbe inoltre rivelarsi utile quando si redige un articolo basato sulla propria ricerca.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 50,
      "id": "117c2e4aa624ed51",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2026-05-12T11:23:45.739919Z",
          "start_time": "2026-05-12T11:23:45.737884Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "PUB 0:\n",
            "  The QPU time that this job took is (here it is 0 because we used fake_fez): 0.0\n",
            "  Gates fidelity measured during the experiment: {'CZ': 0.9953704216147041, 'ID1Q': 0.9991834123567518}\n",
            "  Total shots: 446000\n",
            "  Number of shots used for mitigation: 194000\n",
            "  Resource usage breakdown: {'RUNNING: MAPPING': {'CPU_TIME': 32.52745003718883, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: OPTIMIZING_FOR_HARDWARE': {'CPU_TIME': 257.850521848537, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: WAITING_FOR_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: EXECUTING_QPU': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}, 'RUNNING: POST_PROCESSING': {'CPU_TIME': 0.0, 'GPU_TIME': 0.0, 'QPU_TIME': 0.0}}\n"
          ]
        }
      ],
      "source": [
        "for pub_idx, pub_result in enumerate(\n",
        "    sample_result\n",
        "):  # each element in the list is a result for a different pub, here we sent only one pub\n",
        "    print(f\"\\nPUB {pub_idx}:\")\n",
        "    print(\n",
        "        f\"  The QPU time that this job took is (here it is 0 because we used fake_fez): {pub_result.metadata['total_qpu_time']}\"\n",
        "    )\n",
        "    print(\n",
        "        f\"  Gates fidelity measured during the experiment: {pub_result.metadata['gate_fidelities']}\"\n",
        "    )\n",
        "    print(f\"  Total shots: {pub_result.metadata['total_shots']}\")\n",
        "    print(\n",
        "        f\"  Number of shots used for mitigation: {pub_result.metadata['mitigation_shots']}\"\n",
        "    )\n",
        "    print(\n",
        "        f\"  Resource usage breakdown: {pub_result.metadata['resource_usage']}\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3f71cc3a",
      "metadata": {},
      "source": [
        "In `metadata[\"results\"]`, i risultati vengono raggruppati prima per istanza di circuito e poi per grandezza osservabile.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 99,
      "id": "a5899795",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Full QESEM mitigation results:\n",
            "\n",
            "PUB 0:\n",
            "  Mitigated expectation values: [1.00648343 1.00636289]\n",
            "  Mitigated error bars: [0.00253812 0.00693586]\n",
            "  Unmitigated expectation values: [0.98031429 0.96357143]\n",
            "  Unmitigated error bars: [0.00124128 0.00578812]\n",
            "  Transpiled circuits:\n",
            "    Circuit 0:\n",
            "      Qubit mapping: [[[0, 140], [1, 141], [2, 142], [3, 143], [4, 136]]]\n",
            "      Measurement bases: 2\n",
            "  Results for each observable:\n",
            "    Circuit 0:\n",
            "      Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "        QESEM mitigated value: 1.0064834305181962 ± 0.002538119914534849\n",
            "        Unmitigated value: 0.9803142857142859 ± 0.0012412835813609938\n",
            "      Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "        QESEM mitigated value: 1.0063628870614818 ± 0.006935859820870656\n",
            "        Unmitigated value: 0.9635714285714285 ± 0.005788121870526659\n"
          ]
        }
      ],
      "source": [
        "print(\"Full QESEM mitigation results:\")\n",
        "\n",
        "for pub_idx, pub_result in enumerate(sample_result):\n",
        "    print(f\"\\nPUB {pub_idx}:\")\n",
        "\n",
        "    print(f\"  Mitigated expectation values: {pub_result.data.evs}\")\n",
        "    print(f\"  Mitigated error bars: {pub_result.data.stds}\")\n",
        "    noisy_results = pub_result.metadata.get(\"noisy_results\")\n",
        "    print(f\"  Unmitigated expectation values: {noisy_results.evs}\")\n",
        "    print(f\"  Unmitigated error bars: {noisy_results.stds}\")\n",
        "\n",
        "    print(\"  Transpiled circuits:\")\n",
        "    for circ_idx, transpiled_circ in enumerate(\n",
        "        pub_result.metadata[\"transpiled_circs\"]\n",
        "    ):\n",
        "        print(f\"    Circuit {circ_idx}:\")\n",
        "        # print(f\"      Circuit: \\n {transpiled_circ['circuit']}\") # not printing it because it's long but you can see the transpiled circuit itself\n",
        "        print(f\"      Qubit mapping: {transpiled_circ['qubit_maps']}\")\n",
        "        print(\n",
        "            f\"      Measurement bases: {transpiled_circ['num_measurement_bases']}\"\n",
        "        )\n",
        "\n",
        "    print(\"  Results for each observable:\")\n",
        "    for circ_idx, circ_results in enumerate(pub_result.metadata[\"results\"]):\n",
        "        print(f\"    Circuit {circ_idx}:\")\n",
        "        for obs_idx, (obs_array, result_dict) in enumerate(circ_results):\n",
        "            print(f\"      Observable {obs_idx}: {obs_array}\")\n",
        "            print(\n",
        "                f\"        QESEM mitigated value: {result_dict['qesem']['value']} ± {result_dict['qesem']['error_bar']}\"\n",
        "            )\n",
        "            print(\n",
        "                f\"        Unmitigated value: {result_dict['unmitigated']['value']} ± {result_dict['unmitigated']['error_bar']}\"\n",
        "            )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "345524a3",
      "metadata": {},
      "source": [
        "**Ripartizione dei risultati principali:**\n",
        "\n",
        "* `mitigated`: il valore atteso del QESEM completamente mitigato.\n",
        "* `unmitigated`: il risultato grezzo relativo al rumore fisico senza mitigazione degli errori.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "65a2e503",
      "metadata": {},
      "source": [
        "<span id=\"qesem-heuristic-extrapolation-results\" />\n",
        "\n",
        "#### Risultati dell'estrapolazione euristica QESEM\n",
        "\n",
        "In un'esecuzione standard del QESEM con un singolo `precision` galleggiante, i risultati includono anche punti di scalatura del rumore disponibili automaticamente, utilizzati per l'euristica del QESEM. Questi punti vengono calcolati senza ricorrere a risorse QPU aggiuntive.\n",
        "\n",
        "La scala `1.0` rappresenta il livello di rumore del dispositivo fisico con mitigazione della lettura (REM), mentre la scala `2.0` corrisponde al punto complementare con amplificazione del rumore, anch’esso con REM. Questi punti vengono utilizzati per ottenere il `qesem_heuristic` risultato.\n",
        "\n",
        "* `qesem_heuristic`: una stima in stile ZNE calcolata sulla base dei dati disponibili, corretti in funzione del rumore. Attualmente, questo metodo utilizza l'estrapolazione esponenziale.\n",
        "* `noise_scaling.results_with_REM`: valori attesi a diverse scale di rumore, tutti con mitigazione della lettura (REM).\n",
        "\n",
        "Un dettaglio sottile ma importante è che il risultato della scala `1.0` non coincide con il `unmitigated` risultato. Entrambi corrispondono al livello di rumore del dispositivo fisico, ma il punto di scala `1.0` tiene conto della mitigazione del rumore di lettura, mentre `unmitigated` no.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 101,
      "id": "21afd3d2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QESEM heuristic results:\n",
            "\n",
            "PUB 0:\n",
            "  Circuit 0:\n",
            "    Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "      QESEM heuristic:\n",
            "        Value: 1.0008161638888535 ± 0.0038859458884403964\n",
            "        Extrapolation: exponential\n",
            "        Scale factors: [1.0, 2.0]\n",
            "      Noise scaling results:\n",
            "        Scaling method: QESEM\n",
            "        Results with Readout mitigation (REM):\n",
            "          Scale factor 1.0: 0.9918395459270772 ± 0.0012565417579355634\n",
            "          Scale factor 2.0: 0.982943441922748 ± 0.0028919278067695018\n",
            "    Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "      QESEM heuristic:\n",
            "        Value: 0.9960853148925298 ± 0.013811635038961175\n",
            "        Extrapolation: exponential\n",
            "        Scale factors: [1.0, 2.0]\n",
            "      Noise scaling results:\n",
            "        Scaling method: QESEM\n",
            "        Results with Readout mitigation (REM):\n",
            "          Scale factor 1.0: 0.9902860583785115 ± 0.005921236914723409\n",
            "          Scale factor 2.0: 0.984520565414274 ± 0.006909522262347639\n"
          ]
        }
      ],
      "source": [
        "print(\"QESEM heuristic results:\")\n",
        "\n",
        "for pub_idx, pub_result in enumerate(sample_result):\n",
        "    print(f\"\\nPUB {pub_idx}:\")\n",
        "    for circ_idx, circ_results in enumerate(pub_result.metadata[\"results\"]):\n",
        "        print(f\"  Circuit {circ_idx}:\")\n",
        "        for obs_idx, (obs_array, result_dict) in enumerate(circ_results):\n",
        "            print(f\"    Observable {obs_idx}: {obs_array}\")\n",
        "            qesem_heuristic = result_dict[\"qesem_heuristic\"][0]\n",
        "            print(\"      QESEM heuristic:\")\n",
        "            print(\n",
        "                f\"        Value: {qesem_heuristic['value']} ± {qesem_heuristic['error_bar']}\"\n",
        "            )\n",
        "            print(\n",
        "                f\"        Extrapolation: {qesem_heuristic['extrapolation']}\"\n",
        "            )\n",
        "            print(\n",
        "                f\"        Scale factors: {qesem_heuristic['scale_factors']}\"\n",
        "            )\n",
        "            noise_scaling = result_dict[\"noise_scaling\"]\n",
        "            print(\"      Noise scaling results:\")\n",
        "            print(\n",
        "                f\"        Scaling method: {noise_scaling['scaling_method']}\"\n",
        "            )\n",
        "            print(\"        Results with Readout mitigation (REM):\")\n",
        "            for rem_result in sorted(\n",
        "                (\n",
        "                    item\n",
        "                    for item in noise_scaling[\"results_with_REM\"]\n",
        "                    if item[\"scale\"] != 0.0\n",
        "                ),\n",
        "                key=lambda item: item[\"scale\"],\n",
        "            ):\n",
        "                print(\n",
        "                    f\"          Scale factor {rem_result['scale']}: {rem_result['value']} ± {rem_result['error_bar']}\"\n",
        "                )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "899d229a",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\">\n",
        "  Gli esempi che seguono si concentrano su input e risultati specifici per ciascuna funzionalità, pertanto non riportano ogni volta tutte le metriche di esecuzione. I metadati di primo livello mostrati in precedenza, quali <code>tempo\\_totale\\_qpu</code>, <code>gate\\_fidelities</code>, <code>numero\\_totale\\_di\\_tiri</code>, <code>misure di mitigazione</code> e <code>utilizzo\\_delle\\_risorse</code>, sono disponibili anche per questi lavori.\n",
        "\n",
        "  Per motivi di concisione, alcune variabili degli esempi precedenti, tra cui il backend, gli osservabili e i parametri del circuito di base, vengono riutilizzate di seguito.\n",
        "</Admonition>\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Tutti gli esempi riportati di seguito possono essere eseguiti anche con una stima empirica del tempo. Per abilitarla, passare `<code>\"estimate_time_only\": \"empirico\"</code>` nelle opzioni della funzione.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "079cb5be",
      "metadata": {},
      "source": [
        "<span id=\"parameterized-circuit-example\" />\n",
        "\n",
        "### Esempio di circuito parametrizzato\n",
        "\n",
        "Molti algoritmi valutano lo stesso circuito con diversi valori dei parametri. L'invio del circuito parametrizzato come unico processo QESEM consente a QESEM di condividere la caratterizzazione e la calibrazione tra le diverse istanze del circuito, il che può ridurre il sovraccarico in termini di tempo di elaborazione della QPU rispetto all'esecuzione di processi separati.\n",
        "\n",
        "Per inviare un circuito parametrizzato è necessario utilizzare il `\"minimal_with_layout_opt\"` livello di transpilazione.\n",
        "I circuiti inviati a questo livello dovrebbero già essere espressi utilizzando i gate di base del backend, a seconda del backend stesso. A questo livello, QESEM mantiene la struttura inviata il più vicina possibile al circuito di input, rispetta le barriere durante la stratificazione (raggruppando le operazioni in strati di porte parallele a due qubit) e gestisce comunque automaticamente la mappatura hardware su qubit ad alta fedeltà e la connettività dei dispositivi.\n",
        "\n",
        "In pratica, ciò significa che prima dell'invio è necessario trasporre i circuiti nelle porte di base del backend di destinazione. Di seguito è riportato un semplice esempio di trasposizione di un gate di base.\n",
        "\n",
        "Attualmente QESEM supporta un solo osservabile per ogni set di parametri. Le due righe di parametri riportate di seguito sono associate ai due osservabili: la prima riga viene misurata con `avg_magnetization`, mentre la seconda riga viene misurata con `other_observable`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "704f8aa5",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Transpile to the backend basis gates only. With minimal_with_layout_opt, QESEM handles hardware mapping/connectivity and observable layout internally.\n",
        "from qiskit_ibm_runtime.fake_provider import FakeFez\n",
        "\n",
        "backend = FakeFez()\n",
        "basis = backend.operation_names\n",
        "print(basis)\n",
        "\n",
        "param0 = qiskit.circuit.Parameter(\"param0\")\n",
        "param1 = qiskit.circuit.Parameter(\"param1\")\n",
        "parametrized_circ = qiskit.QuantumCircuit(5)\n",
        "parametrized_circ.rx(param0, 0)\n",
        "parametrized_circ.rx(param1, 1)\n",
        "parametrized_circ.cx(0, 1)\n",
        "parametrized_circ.cx(2, 3)\n",
        "parametrized_circ.cx(1, 2)\n",
        "parametrized_circ.cx(3, 4)\n",
        "\n",
        "parametrized_circ = qiskit.transpile(\n",
        "    parametrized_circ, basis_gates=basis, optimization_level=1\n",
        ")\n",
        "parametrized_parameter_values = [[0.5, 0.1], [0.0, 0.6]]\n",
        "parametrized_observables = [avg_magnetization, other_observable]\n",
        "\n",
        "parametrized_job = qesem_function.run(\n",
        "    pubs=[\n",
        "        (\n",
        "            parametrized_circ,\n",
        "            parametrized_observables,\n",
        "            parametrized_parameter_values,\n",
        "            0.1,\n",
        "        )\n",
        "    ],\n",
        "    backend_name=backend_name,\n",
        "    options={\n",
        "        \"max_execution_time\": 300,\n",
        "        \"transpilation_level\": \"minimal_with_layout_opt\",\n",
        "    },\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 72,
      "id": "85a452fc",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "d1b0e29b-196c-4896-aec6-44a268ebd874\n",
            "DONE\n"
          ]
        }
      ],
      "source": [
        "print(parametrized_job.job_id)\n",
        "print(parametrized_job.status())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 73,
      "id": "244cd3b2",
      "metadata": {},
      "outputs": [],
      "source": [
        "parametrized_result = parametrized_job.result()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 77,
      "id": "03399db5",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Parameterized circuit QESEM results:\n",
            "\n",
            "PUB 0:\n",
            "  Mitigated expectation values: [0.92392021 0.82517653]\n",
            "  Mitigated error bars: [0.00565281 0.00616016]\n",
            "  Unmitigated expectation values: [0.9028     0.78771429]\n",
            "  Unmitigated error bars: [0.00335142 0.00925413]\n",
            "  Results for each parameter value:\n",
            "    Parameter set 0: [0.5, 0.1]\n",
            "      Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "        QESEM mitigated value: 0.923920210615709 ± 0.005652811570890183\n",
            "        Unmitigated value: 0.9028 ± 0.0033514176105045447\n",
            "    Parameter set 1: [0.0, 0.6]\n",
            "      Observable 0: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "        QESEM mitigated value: 0.8251765289285893 ± 0.006160161743353999\n",
            "        Unmitigated value: 0.7877142857142858 ± 0.009254130564027902\n"
          ]
        }
      ],
      "source": [
        "print(\"Parameterized circuit QESEM results:\")\n",
        "\n",
        "for pub_idx, pub_result in enumerate(parametrized_result):\n",
        "    print(f\"\\nPUB {pub_idx}:\")\n",
        "    print(f\"  Mitigated expectation values: {pub_result.data.evs}\")\n",
        "    print(f\"  Mitigated error bars: {pub_result.data.stds}\")\n",
        "    noisy_results = pub_result.metadata[\"noisy_results\"]\n",
        "    print(f\"  Unmitigated expectation values: {noisy_results.evs}\")\n",
        "    print(f\"  Unmitigated error bars: {noisy_results.stds}\")\n",
        "    print(\"  Results for each parameter value:\")\n",
        "    for param_idx, param_results in enumerate(pub_result.metadata[\"results\"]):\n",
        "        print(\n",
        "            f\"    Parameter set {param_idx}: {parametrized_parameter_values[param_idx]}\"\n",
        "        )\n",
        "        for obs_idx, (obs_array, result_dict) in enumerate(param_results):\n",
        "            print(f\"      Observable {obs_idx}: {obs_array}\")\n",
        "            print(\n",
        "                f\"        QESEM mitigated value: {result_dict['qesem']['value']} ± {result_dict['qesem']['error_bar']}\"\n",
        "            )\n",
        "            print(\n",
        "                f\"        Unmitigated value: {result_dict['unmitigated']['value']} ± {result_dict['unmitigated']['error_bar']}\"\n",
        "            )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d6d1b6c2",
      "metadata": {},
      "source": [
        "<span id=\"multi-pub-example\" />\n",
        "\n",
        "### Esempio con più pub\n",
        "\n",
        "L'esecuzione multi-pub è utile quando si desidera eseguire diversi circuiti correlati in un unico processo QESEM. Come nel caso dell'esecuzione parametrizzata, ciò può ridurre il sovraccarico, poiché QESEM è in grado di condividere la caratterizzazione e la calibrazione tra le diverse istanze del circuito, anziché ripeterle in processi separati.\n",
        "\n",
        "Ciò risulta particolarmente utile per i circuiti con una struttura a livelli condivisi, come i carichi di lavoro **di tipo Trotter**, in cui circuiti diversi riutilizzano gli stessi livelli univoci. In tal caso, eseguirle contemporaneamente può ridurre i costi di caratterizzazione rispetto a sessioni QESEM indipendenti.\n",
        "\n",
        "I lavori che prevedono la pubblicazione su più testate richiedono `\"transpilation_level\": \"minimal_with_layout_opt\"`. Come nell'esempio parametrizzato, prima dell'invio i circuiti devono essere transpilati nei gate di base del backend di destinazione. QESEM gestisce quindi internamente la connettività dei dispositivi, il layout e la mappatura ai qubit ad alta fedeltà.\n",
        "\n",
        "Ogni PUB riportato di seguito contiene un circuito e gli stessi due osservabili utilizzati in precedenza nel notebook, quindi il risultato restituito `PrimitiveResult` contiene un `PubResult` per ogni circuito di input.\n",
        "\n",
        "L'esempio riportato di seguito utilizza due semplici circuiti di Trotter con lo stesso schema di strati: `circ_a` presenta uno strato di Trotter, mentre `circ_b` ripete lo stesso schema di strati due volte. In questo modo la struttura condivisa risulta esplicita.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "8cc663fc",
      "metadata": {},
      "outputs": [],
      "source": [
        "def make_trotter_circuit(num_qubits, num_layers, zz_angle=0.2, x_angle=0.1):\n",
        "    trotter_circ = qiskit.QuantumCircuit(num_qubits)\n",
        "    for _ in range(num_layers):\n",
        "        for q in range(num_qubits):\n",
        "            trotter_circ.rx(x_angle, q)\n",
        "        trotter_circ.barrier()\n",
        "        for q in range(0, num_qubits - 1, 2):\n",
        "            trotter_circ.rzz(zz_angle, q, q + 1)\n",
        "        trotter_circ.barrier()\n",
        "        for q in range(1, num_qubits - 1, 2):\n",
        "            trotter_circ.rzz(zz_angle, q, q + 1)\n",
        "        trotter_circ.barrier()\n",
        "    return trotter_circ\n",
        "\n",
        "\n",
        "circ_a = make_trotter_circuit(num_qubits=5, num_layers=1)\n",
        "circ_b = make_trotter_circuit(num_qubits=5, num_layers=2)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "371c4893",
      "metadata": {},
      "outputs": [],
      "source": [
        "multi_pubs = [\n",
        "    (\n",
        "        qiskit.transpile(qci, basis_gates=basis, optimization_level=1),\n",
        "        [avg_magnetization, other_observable],\n",
        "    )\n",
        "    for qci in [circ_a, circ_b]\n",
        "]\n",
        "\n",
        "multi_circ_job = qesem_function.run(\n",
        "    pubs=multi_pubs,\n",
        "    backend_name=backend_name,\n",
        "    options={\n",
        "        \"max_execution_time\": 300,\n",
        "        \"transpilation_level\": \"minimal_with_layout_opt\",\n",
        "        \"default_precision\": 0.1,\n",
        "    },\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 91,
      "id": "92e45737",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "e34565b8-7262-4133-a120-de42ce624a99\n",
            "DONE\n"
          ]
        }
      ],
      "source": [
        "print(multi_circ_job.job_id)\n",
        "print(multi_circ_job.status())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 92,
      "id": "23c61008",
      "metadata": {},
      "outputs": [],
      "source": [
        "multi_circ_result = multi_circ_job.result()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 105,
      "id": "1ae6f8c3",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Multi-pub QESEM results:\n",
            "\n",
            "PUB 0:\n",
            "  Mitigated expectation values: [0.99502406 1.02209332]\n",
            "  Mitigated error bars: [0.00483819 0.00707488]\n",
            "  Unmitigated expectation values: [0.96934286 0.97271429]\n",
            "  Unmitigated error bars: [0.00124855 0.00617294]\n",
            "  Results for each observable:\n",
            "    Circuit 0:\n",
            "      Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "        QESEM mitigated value: 0.9950240647925642 ± 0.004838188086259301\n",
            "        Unmitigated value: 0.9693428571428573 ± 0.0012485470362492692\n",
            "      Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "        QESEM mitigated value: 1.0220933230604674 ± 0.007074884384355636\n",
            "        Unmitigated value: 0.9727142857142859 ± 0.006172939375512439\n",
            "\n",
            "PUB 1:\n",
            "  Mitigated expectation values: [0.98850017 1.02555188]\n",
            "  Mitigated error bars: [0.0077912  0.01672652]\n",
            "  Unmitigated expectation values: [0.93682857 0.95371429]\n",
            "  Unmitigated error bars: [0.00156245 0.00665735]\n",
            "  Results for each observable:\n",
            "    Circuit 0:\n",
            "      Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "        QESEM mitigated value: 0.988500171577252 ± 0.007791203181151346\n",
            "        Unmitigated value: 0.9368285714285716 ± 0.001562451883089579\n",
            "      Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "        QESEM mitigated value: 1.02555188098689 ± 0.016726524388086233\n",
            "        Unmitigated value: 0.9537142857142858 ± 0.006657345655544263\n"
          ]
        }
      ],
      "source": [
        "print(\"Multi-pub QESEM results:\")\n",
        "\n",
        "for pub_idx, pub_result in enumerate(multi_circ_result):\n",
        "    print(f\"\\nPUB {pub_idx}:\")\n",
        "    print(f\"  Mitigated expectation values: {pub_result.data.evs}\")\n",
        "    print(f\"  Mitigated error bars: {pub_result.data.stds}\")\n",
        "    noisy_results = pub_result.metadata[\"noisy_results\"]\n",
        "    print(f\"  Unmitigated expectation values: {noisy_results.evs}\")\n",
        "    print(f\"  Unmitigated error bars: {noisy_results.stds}\")\n",
        "    print(\"  Results for each observable:\")\n",
        "    for circ_idx, circ_results in enumerate(pub_result.metadata[\"results\"]):\n",
        "        print(f\"    Circuit {circ_idx}:\")\n",
        "        for obs_idx, (obs_array, result_dict) in enumerate(circ_results):\n",
        "            print(f\"      Observable {obs_idx}: {obs_array}\")\n",
        "            print(\n",
        "                f\"        QESEM mitigated value: {result_dict['qesem']['value']} ± {result_dict['qesem']['error_bar']}\"\n",
        "            )\n",
        "            print(\n",
        "                f\"        Unmitigated value: {result_dict['unmitigated']['value']} ± {result_dict['unmitigated']['error_bar']}\"\n",
        "            )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8f28d826",
      "metadata": {},
      "source": [
        "<span id=\"quasi-probabilistic-error-tuning-qet-example\" />\n",
        "\n",
        "### Esempio di regolazione dell'errore quasi-probabilistica (QET)\n",
        "\n",
        "Il Quasi-probabilistic Error Tuning (QET) richiede i valori attesi a determinati fattori di scala del rumore. Ciò risulta utile per studi personalizzati sul ridimensionamento del rumore e per i flussi di lavoro di estrapolazione a rumore zero. La scala `1.0` indica il livello fisico di rumore; i valori compresi tra `0.0` e `1.0` riducono parzialmente il rumore, mentre i valori superiori `1.0` a lo amplificano.\n",
        "\n",
        "Per utilizzare QET con la funzione Qiskit, passare un dizionario come parametro \" PUB \" (precisione). Il dizionario associa a ciascuna scala di rumore richiesta la relativa precisione target. I risultati relativi al fattore di scala restituiti vengono memorizzati in `noise_scaling.results_with_REM` e includono la mitigazione della lettura. Il punto di scala `1.0` non è quindi identico al valore non corretto, poiché `1.0` il primo tiene conto della correzione di lettura mentre `unmitigated` il secondo no.\n",
        "\n",
        "Quando viene richiesta una scala, QESEM restituisce anche la scala complementare intorno a `1.0` senza un utilizzo aggiuntivo della QPU. `0.7``1.5`Ad esempio, la richiesta di `0.5` può restituire anche, e la richiesta di `1.3` può restituire anche. La precisione della scala complementare non è garantita.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 88,
      "id": "723cdf95",
      "metadata": {},
      "outputs": [],
      "source": [
        "noise_scale_precision = {0.5: 0.15, 1.3: 0.2}\n",
        "\n",
        "qet_job = qesem_function.run(\n",
        "    pubs=[\n",
        "        (\n",
        "            circ,\n",
        "            [avg_magnetization, other_observable],\n",
        "            None,\n",
        "            noise_scale_precision,\n",
        "        )\n",
        "    ],\n",
        "    backend_name=backend_name,\n",
        "    options={\"max_execution_time\": 300},\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 95,
      "id": "d68a015c",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "8195fa58-f037-4651-8715-36ce1cdc5521\n",
            "DONE\n"
          ]
        }
      ],
      "source": [
        "print(qet_job.job_id)\n",
        "print(qet_job.status())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 96,
      "id": "927d8543",
      "metadata": {},
      "outputs": [],
      "source": [
        "qet_result = qet_job.result()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 104,
      "id": "1c9ba079",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "QET noise-scaling results:\n",
            "\n",
            "PUB 0:\n",
            "  Unmitigated expectation values: [0.97822857 0.96171429]\n",
            "  Unmitigated error bars: [0.00123812 0.00672958]\n",
            "  Results for each observable:\n",
            "    Circuit 0:\n",
            "      Observable 0: ObservablesArray({'IIIIZ': 0.2, 'IIIZI': 0.2, 'IIZII': 0.2, 'IZIII': 0.2, 'ZIIII': 0.2}, shape=())\n",
            "        Scaling method: QESEM\n",
            "        Results with Readout mitigation (REM):\n",
            "          Scale factor 0.5: 0.9938730340199383 ± 0.0032116907357568275\n",
            "          Scale factor 0.7: 0.9963976191853445 ± 0.00036300258869586616\n",
            "          Scale factor 1.0: 0.9898115079506586 ± 0.0012525947426560995\n",
            "          Scale factor 1.3: 0.9864667065580341 ± 0.002633221613518526\n",
            "          Scale factor 1.5: 0.9838755527197551 ± 0.002948417797996015\n",
            "      Observable 1: ObservablesArray({'IIIZZ': 1.0, 'ZIIXI': 0.5}, shape=())\n",
            "        Scaling method: QESEM\n",
            "        Results with Readout mitigation (REM):\n",
            "          Scale factor 0.5: 1.0006538544450332 ± 0.002121742014777343\n",
            "          Scale factor 0.7: 1.0004159801523036 ± 0.0021671375357823794\n",
            "          Scale factor 1.0: 0.9898058846339917 ± 0.00690183710903159\n",
            "          Scale factor 1.3: 0.9948946719997267 ± 0.002146532859610311\n",
            "          Scale factor 1.5: 0.9927220368192772 ± 0.0020875057190323882\n"
          ]
        }
      ],
      "source": [
        "print(\"QET noise-scaling results:\")\n",
        "\n",
        "for pub_idx, pub_result in enumerate(qet_result):\n",
        "    print(f\"\\nPUB {pub_idx}:\")\n",
        "    noisy_results = pub_result.metadata[\"noisy_results\"]\n",
        "    print(f\"  Unmitigated expectation values: {noisy_results.evs}\")\n",
        "    print(f\"  Unmitigated error bars: {noisy_results.stds}\")\n",
        "    print(\"  Results for each observable:\")\n",
        "    for circ_idx, circ_results in enumerate(pub_result.metadata[\"results\"]):\n",
        "        print(f\"    Circuit {circ_idx}:\")\n",
        "        for obs_idx, (obs_array, result_dict) in enumerate(circ_results):\n",
        "            print(f\"      Observable {obs_idx}: {obs_array}\")\n",
        "            noise_scaling = result_dict[\"noise_scaling\"]\n",
        "            print(\n",
        "                f\"        Scaling method: {noise_scaling['scaling_method']}\"\n",
        "            )\n",
        "            print(\"        Results with Readout mitigation (REM):\")\n",
        "            for rem_result in sorted(\n",
        "                (\n",
        "                    item\n",
        "                    for item in noise_scaling[\"results_with_REM\"]\n",
        "                    if item[\"scale\"] != 0.0\n",
        "                ),\n",
        "                key=lambda item: item[\"scale\"],\n",
        "            ):\n",
        "                print(\n",
        "                    f\"          Scale factor {rem_result['scale']}: {rem_result['value']} ± {rem_result['error_bar']}\"\n",
        "                )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "35aed54a",
      "metadata": {},
      "source": [
        "<span id=\"fetch-error-messages\" />\n",
        "\n",
        "## Recupera i messaggi di errore\n",
        "\n",
        "Se lo stato del carico di lavoro è ERROR, utilizzare `job.result()` per recuperare il messaggio di errore come segue:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "d95a3f30",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(2,), dtype=float64>), stds=np.ndarray(<shape=(2,), dtype=float64>), shape=(2,)), metadata={'gate_fidelities': {'CZ': 0.9979444718552628, 'ID1Q': 0.9991994239814883}, 'total_shots': 498600, 'mitigation_shots': 223400, 'transpiled_circs': [{'circuit': 'OPENQASM 3.0;\\ninclude \"stdgates.inc\";\\nbit[76] c0;\\nqubit[76] q0;\\nrx(0) q0[54];\\nrx(0) q0[59];\\nrx(0) q0[75];\\nrz(pi/2) q0[54];\\nrz(pi/2) q0[59];\\nrz(pi/2) q0[75];\\nrx(pi/2) q0[54];\\nr... (truncated 3771 characters)\n"
          ]
        }
      ],
      "source": [
        "# Get the result and truncate for readability\n",
        "result = sample_job.result()\n",
        "result_str = str(result)\n",
        "max_length = 500  # Adjust this value as necessary\n",
        "\n",
        "if len(result_str) > max_length:\n",
        "    truncated = (\n",
        "        result_str[:max_length]\n",
        "        + f\"... (truncated {len(result_str) - max_length} characters)\"\n",
        "    )\n",
        "else:\n",
        "    truncated = result_str\n",
        "\n",
        "print(truncated)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e9ec2e67",
      "metadata": {},
      "source": [
        "<span id=\"get-support\" />\n",
        "\n",
        "## Ottenere supporto\n",
        "\n",
        "Il team di supporto Qedma è qui per aiutarvi! Se riscontrate problemi o avete domande sull'utilizzo della funzione Qiskit di QESEM, non esitate a contattarci. Il nostro personale di assistenza, competente e cordiale, è pronto ad assistervi in caso di dubbi tecnici o richieste di informazioni.\n",
        "\n",
        "Potete inviarci un'e-mail all'indirizzo [support@qedma.com](mailto:support@qedma.com) per ricevere assistenza. Si prega di includere quanti più dettagli possibili sul problema riscontrato per aiutarci a fornire una risposta rapida e accurata. Potete anche contattare il vostro rappresentante Qedma POC dedicato via e-mail o telefono.\n",
        "\n",
        "Per aiutarci ad assistervi in modo più efficiente, vi preghiamo di fornire le seguenti informazioni quando ci contattate:\n",
        "\n",
        "* Una descrizione dettagliata del problema\n",
        "* L'ID lavoro\n",
        "* Eventuali messaggi o codici di errore rilevanti\n",
        "\n",
        "Ci impegniamo a fornirvi un'assistenza rapida ed efficace per assicurarvi la migliore esperienza possibile con la nostra funzione Qiskit.\n",
        "\n",
        "Siamo sempre alla ricerca di modi per migliorare il nostro prodotto e accogliamo con piacere i vostri suggerimenti! Se avete idee su come migliorare i nostri servizi o funzionalità che vorreste vedere implementate, inviateci i vostri suggerimenti all'indirizzo [support@qedma.com](mailto:support@qedma.com).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5a6a25c8",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Suggerimenti\">\n",
        "  * [Richiedi l'accesso a Qedma QESEM](/functions?id=qedma-qesem).\n",
        "  * Consulta la documentazione [di riferimento dell'API](/docs/api/functions/qedma-qesem) relativa a questa funzione di Qiskit.\n",
        "  * Prova il tutorial [\"Simulazione di un sistema di Ising a campo inclinato con effetto di 2D \" utilizzando la funzione QESEM](/docs/tutorials/qedma-2d-ising-with-qesem).\n",
        "  * Recensione [Aharonov, D., et al. (2025). Mitigazione degli errori affidabile e altamente accurata per circuiti quantistici su scala industriale. arXiv preprint arXiv:2508.10997](https://arxiv.org/pdf/2508.10997).\n",
        "  * Recensione [Aharonov, D., et al. (2025). Mitigazione degli errori logici basata sulla consapevolezza della sindrome. arXiv preprint arXiv:2508.10997](https://arxiv.org/pdf/2508.10997).\n",
        "  * Recensione [Aharonov, D., et al. (2025). Sull'importanza della mitigazione degli errori nel calcolo quantistico. arXiv preprint arXiv:2512.23810](https://arxiv.org/abs/2512.23810).\n",
        "  * Recensione [Bauman, N. P., et al. (2025). Teoria del downfolding dei cluster accoppiati nelle simulazioni di sistemi chimici su hardware quantistico. arXiv preprint arXiv:2507.01199](https://arxiv.org/pdf/2507.01199).\n",
        "  * Recensione [Goldack, M., et al. (2026). Calcolo delle proprietà statistiche dei campi di velocità sull'attuale hardware quantistico. arXiv preprint arXiv:2601.10166](https://arxiv.org/pdf/2601.10166).\n",
        "  * Recensione [Sakuma, R., et al. (2026). Analisi della simmetria dei gruppi puntiformi delle funzioni d’onda a molti elettroni su un computer quantistico arXiv preprint arXiv:2605.24824](https://arxiv.org/abs/2605.24824).\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
}