{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "552b1077",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Esegui il tuo primo circuito sull'hardware\"\n",
        "description: \"Inizia a utilizzare Qiskit con l'hardware dell' IBM Quantum e in questo esempio Hello World\"\n",
        "---\n",
        "\n",
        "<span id=\"run-your-first-circuit-on-hardware\" />\n",
        "\n",
        "# Esegui il tuo primo circuito sull'hardware\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7cc19a86-a234-4220-bb4f-d66d3834e0c3",
      "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 utilizzando i seguenti requisiti.\n",
        "    Si consiglia di utilizzare queste versioni o versioni più recenti.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.1\n",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1a3c196d-545d-417f-b34e-fa422aa9a394",
      "metadata": {},
      "source": [
        "Questo esempio è composto da due parti. Per prima cosa creerai un semplice programma quantistico \"Hello world\" e lo eseguirai su un'unità di elaborazione quantistica (QPU).  Poiché la ricerca quantistica effettiva richiede programmi molto più robusti, nella seconda sezione ( [Scalabilità a un numero elevato di qubit](#scale-to-large-numbers-of-qubits) ) si procederà a scalare il programma semplice fino al livello di utilità.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7b65f7e0",
      "metadata": {},
      "source": [
        "<span id=\"install-and-authenticate\" />\n",
        "\n",
        "## Installa e autentica\n",
        "\n",
        "1. Se non hai ancora installato Qiskit, consulta le istruzioni nella guida [Quickstart](/docs/guides/quick-start).\n",
        "\n",
        "   * Installa il client Compute di IBM Quantum per eseguire i lavori sull'hardware quantistico:\n",
        "\n",
        "     ```bash\n",
        "     pip install qiskit-ibm-runtime\n",
        "     ```\n",
        "\n",
        "   * Configurare un ambiente per eseguire i notebook Jupyter in locale:\n",
        "\n",
        "     ```bash\n",
        "     pip install jupyter\n",
        "     ```\n",
        "\n",
        "2. Configura la tua autenticazione per accedere all'hardware quantistico tramite il [piano Open](/docs/guides/plans-overview#open-plan) gratuito.\n",
        "\n",
        "   (Se hai ricevuto un invito via e-mail per partecipare a un account, segui invece la [procedura per gli utenti invitati](/docs/guides/cloud-setup-invited).)\n",
        "\n",
        "   * Vai su [IBM Quantum Platform](/) per accedere o creare un account.\n",
        "     <Admonition type=\"note\" title=\"Importante\">\n",
        "       Se ti connetti tramite un server proxy, devi utilizzare v0.44.0`qiskit-ibm-runtime` o una versione successiva.\n",
        "     </Admonition>\n",
        "\n",
        "   * Genera la tua chiave API (chiamata anche *token* API) sulla [dashboard](/), quindi copiala in un luogo sicuro.\n",
        "\n",
        "   * Vai alla pagina [Istanze](/instances) e trova l'istanza che desideri utilizzare. Passa con il mouse sul suo CRN e clicca per copiarlo.\n",
        "\n",
        "   * Salva le tue credenziali localmente con questo codice:\n",
        "\n",
        "     ```python\n",
        "     from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "     QiskitRuntimeService.save_account(\n",
        "         # For `token`, use the 44-character API_KEY you created\n",
        "         # and saved from the IBM Quantum Platform Home dashboard\n",
        "         token=\"<your-api-key>\",\n",
        "         instance=\"<CRN>\", # Optional\n",
        "     )\n",
        "     ```\n",
        "\n",
        "3. Ora puoi utilizzare questo codice Python ogni volta che desideri effettuare l'autenticazione al servizio IBM Quantum Compute:\n",
        "   ```python\n",
        "   from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "   # Run every time you need the service\n",
        "   service = QiskitRuntimeService()\n",
        "   ```\n",
        "\n",
        "<Admonition type=\"info\" title=\"Non utilizzi un ambiente Python affidabile?\">\n",
        "  Se stai utilizzando un computer pubblico o un altro ambiente non protetto, segui invece le [istruzioni per l'autenticazione manuale](/docs/guides/cloud-setup-untrusted) per mantenere al sicuro le tue credenziali di autenticazione.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "80471a0a",
      "metadata": {},
      "source": [
        "<span id=\"create-and-run-a-simple-quantum-program\" />\n",
        "\n",
        "## Creare ed eseguire un semplice programma quantistico\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "85fe979e",
      "metadata": {
        "raw_mimetype": "text/restructuredtext"
      },
      "source": [
        "I quattro passaggi per scrivere un programma quantistico utilizzando i modelli Qiskit sono:\n",
        "\n",
        "1. Mappare il problema in un formato nativo quantistico.\n",
        "\n",
        "2. Ottimizzare i circuiti e gli operatori.\n",
        "\n",
        "3. Eseguire utilizzando una funzione primitiva quantistica.\n",
        "\n",
        "4. Analizza i risultati.\n",
        "\n",
        "<span id=\"step-1-map-the-problem-to-a-quantum-native-format\" />\n",
        "\n",
        "### Passo 1. Mappare il problema in un formato nativo quantistico\n",
        "\n",
        "In un programma quantistico, *i circuiti quantistici* sono il formato nativo in cui rappresentare le istruzioni quantistiche, mentre *gli operatori* rappresentano gli osservabili da misurare. Quando si crea un circuito, di solito si crea un nuovo [`QuantumCircuit`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#quantumcircuit-class) oggetto, quindi si aggiungono le istruzioni in sequenza.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "21f7a26c",
      "metadata": {},
      "source": [
        "La seguente cella di codice crea un circuito che produce uno *stato di Bell,* ovvero uno stato in cui due qubit sono completamente intrecciati tra loro.\n",
        "\n",
        "<Admonition type=\"note\" title=\"Nota: ordine dei bit\">\n",
        "  Il Qiskit SDK utilizza la numerazione LSb 0 bit in cui la $n^{th}$ cifra ha valore $1 \\ll n$ o $2^n$. Per ulteriori dettagli, consultare [l'](/docs/guides/bit-ordering) argomento Ordinamento dei bit in Qiskit SDK.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "930ca3b6",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/hello-world/extracted-outputs/930ca3b6-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "from qiskit_ibm_runtime import EstimatorOptions\n",
        "from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
        "from matplotlib import pyplot as plt\n",
        "# Uncomment the next line if you want to use a simulator:\n",
        "# from qiskit_ibm_runtime.fake_provider import FakeBelemV2\n",
        "\n",
        "\n",
        "# Create a new circuit with two qubits\n",
        "qc = QuantumCircuit(2)\n",
        "\n",
        "# Add a Hadamard gate to qubit 0\n",
        "qc.h(0)\n",
        "\n",
        "# Perform a controlled-X gate on qubit 1, controlled by qubit 0\n",
        "qc.cx(0, 1)\n",
        "\n",
        "# Return a drawing of the circuit using MatPlotLib (\"mpl\").\n",
        "# These guides are written by using Jupyter notebooks, which\n",
        "# display the output of the last line of each cell.\n",
        "# If you're running this in a script, use `print(qc.draw())` to\n",
        "# print a text drawing.\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0c957de9",
      "metadata": {
        "raw_mimetype": "text/restructuredtext"
      },
      "source": [
        "Vedi [`QuantumCircuit`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#quantumcircuit-class) nella documentazione tutte le operazioni disponibili.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f3ef4248-7938-44c1-85f1-edc997f0edcd",
      "metadata": {},
      "source": [
        "Quando si creano circuiti quantistici, è necessario considerare anche quale tipo di dati si desidera ottenere al termine dell'esecuzione. Qiskit offre due modi per ottenere i dati: è possibile ottenere un output campionario per un insieme di qubit che si sceglie di misurare, oppure è possibile ottenere il valore atteso di un osservabile. Prepara il tuo carico di lavoro per misurare il circuito in uno di questi due modi utilizzando le primitive (spiegate in dettaglio nel [Passo 3](#step-3-execute-using-the-quantum-primitives) ).\n",
        "\n",
        "Questo esempio misura i valori attesi utilizzando il `qiskit.quantum_info` sottomodulo, specificato tramite operatori (oggetti matematici utilizzati per rappresentare un'azione o un processo che modifica uno stato quantistico). La seguente cella di codice crea sei operatori di Pauli a due qubit: `IZ`, `IX`, `ZI`, `XI` `ZZ`, e `XX`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "c57b261c-b757-4432-beab-61b526c98a41",
      "metadata": {
        "tags": []
      },
      "outputs": [],
      "source": [
        "# Set up six different observables.\n",
        "\n",
        "observables_labels = [\"IZ\", \"IX\", \"ZI\", \"XI\", \"ZZ\", \"XX\"]\n",
        "observables = [SparsePauliOp(label) for label in observables_labels]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "47150779",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\" title=\"Notazione dell'operatore\">\n",
        "  Qui, qualcosa come `ZZ` l'operatore è una scorciatoia per il prodotto $Z\\otimes Z$ tensoriale, che significa misurare Z sul qubit 1 e Z sul qubit 0 insieme, e ottenere informazioni sulla correlazione tra il qubit 1 e il qubit 0. Valori attesi come questo sono solitamente scritti anche come $\\langle Z_1 Z_0 \\rangle$.\n",
        "\n",
        "  Se lo stato è intrecciato, allora la misurazione di $\\langle Z_1 Z_0 \\rangle$ dovrebbe essere diversa dalla misurazione di $\\langle I_1 \\otimes Z_0 \\rangle \\langle Z_1 \\otimes I_0 \\rangle$. Per lo stato intrecciato specifico creato dal nostro circuito descritto sopra, la misurazione di $\\langle Z_1 Z_0 \\rangle$ dovrebbe essere 1 e la misurazione di $\\langle I_1 \\otimes Z_0 \\rangle \\langle Z_1 \\otimes I_0 \\rangle$ dovrebbe essere zero.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "83bf9151-3bc9-40d2-8615-31570238b08e",
      "metadata": {},
      "source": [
        "<span id=\"optimize\" />\n",
        "\n",
        "<span id=\"step-2-optimize-the-circuits-and-operators\" />\n",
        "\n",
        "### Passo 2. Ottimizzare i circuiti e gli operatori\n",
        "\n",
        "Quando si eseguono circuiti su un dispositivo, è importante ottimizzare l'insieme di istruzioni contenute nel circuito e ridurre al minimo la profondità complessiva (approssimativamente il numero di istruzioni) del circuito. Ciò garantisce i migliori risultati possibili riducendo gli effetti di errori e rumori. Inoltre, le istruzioni del circuito devono essere conformi [all'architettura del set di istruzioni (ISA)](/docs/guides/transpile#instruction-set-architecture) del dispositivo backend e devono tenere conto dei gate di base e della connettività dei qubit del dispositivo.\n",
        "\n",
        "Il codice seguente istanzia un dispositivo reale a cui inviare un lavoro e trasforma il circuito e gli osservabili in modo che corrispondano all'ISA di quel backend. È necessario che tu abbia già [salvato le tue credenziali.](/docs/guides/cloud-setup)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "9a901271",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/hello-world/extracted-outputs/9a901271-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "service = QiskitRuntimeService()\n",
        "\n",
        "backend = service.least_busy(simulator=False, operational=True)\n",
        "\n",
        "# Convert to an ISA circuit and layout-mapped observables.\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "isa_circuit = pm.run(qc)\n",
        "\n",
        "isa_circuit.draw(\"mpl\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9acac1d4",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-the-quantum-primitives\" />\n",
        "\n",
        "### Passaggio 3. Eseguire utilizzando le primitive quantistiche\n",
        "\n",
        "I computer quantistici possono produrre risultati casuali, quindi solitamente si raccoglie un campione dei risultati eseguendo il circuito più volte. È possibile stimare il valore dell'osservabile utilizzando la `Estimator` classe. `Estimator` è una delle due [primitive](/docs/guides/get-started-with-estimator); l'altra è `Sampler`, che può essere utilizzata per ottenere dati da un computer quantistico.  Questi oggetti dispongono di un `run()` metodo che esegue la selezione di circuiti, grandezze osservabili e parametri (se applicabile), utilizzando un [blocco unificato primitivo ( PUB )](/docs/guides/get-started-with-sampler).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "62c4ca44",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> Job ID: d9mqa588csec73fagtu0\n"
          ]
        }
      ],
      "source": [
        "# Construct the Estimator instance.\n",
        "\n",
        "estimator = Estimator(mode=backend)\n",
        "estimator.options.resilience_level = 1\n",
        "estimator.options.default_shots = 5000\n",
        "\n",
        "mapped_observables = [\n",
        "    observable.apply_layout(isa_circuit.layout) for observable in observables\n",
        "]\n",
        "\n",
        "# One pub, with one circuit to run against five different observables.\n",
        "job = estimator.run([(isa_circuit, mapped_observables)])\n",
        "\n",
        "# Use the job ID to retrieve your job data later\n",
        "print(f\">>> Job ID: {job.job_id()}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "47479e76",
      "metadata": {},
      "source": [
        "Dopo aver inviato un lavoro, puoi attendere che venga completato nell'istanza Python corrente oppure utilizzare `job_id` per recuperare i dati in un secondo momento.  (Per ulteriori dettagli, consultare la [sezione relativa al recupero dei lavori](/docs/guides/monitor-job#retrieve-job-results-at-a-later-time) )\n",
        "\n",
        "Al termine dell'operazione, esaminare il risultato tramite l'attributo `result()` dell'operazione.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "792d2f01",
      "metadata": {},
      "outputs": [],
      "source": [
        "# This is the result of the entire submission.  You submitted one Pub,\n",
        "# so this contains one inner result (and some metadata of its own).\n",
        "job_result = job.result()\n",
        "\n",
        "# This is the result from our single pub, which had six observables,\n",
        "# so contains information on all six.\n",
        "pub_result = job.result()[0]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "48317a25",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\" title=\"Alternativa: eseguire l'esempio utilizzando un simulatore\">\n",
        "  Quando si esegue un programma quantistico su un dispositivo reale, il carico di lavoro deve attendere in coda prima di essere eseguito. Per risparmiare tempo, puoi invece utilizzare il codice seguente per eseguire questo piccolo carico di lavoro in modalità di [`fake_provider`](/docs/api/qiskit-ibm-runtime/fake-provider) test locale `qiskit-ibm-runtime` . Si noti che ciò è possibile solo per un circuito di piccole dimensioni. Quando passerai alla sezione successiva, dovrai utilizzare un dispositivo reale.\n",
        "\n",
        "  ```python\n",
        "\n",
        "  # Use the following code instead if you want to run on a simulator:\n",
        "\n",
        "  from qiskit_ibm_runtime.fake_provider import FakeBelemV2\n",
        "  backend = FakeBelemV2()\n",
        "  estimator = Estimator(backend)\n",
        "\n",
        "  # Convert to an ISA circuit and layout-mapped observables.\n",
        "\n",
        "  pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "  isa_circuit = pm.run(qc)\n",
        "  mapped_observables = [\n",
        "      observable.apply_layout(isa_circuit.layout) for observable in observables\n",
        "  ]\n",
        "\n",
        "  job = estimator.run([(isa_circuit, mapped_observables)])\n",
        "  result = job.result()\n",
        "\n",
        "  # This is the result of the entire submission. You submitted one Pub,\n",
        "  # so this contains one inner result (and some metadata of its own).\n",
        "\n",
        "  job_result = job.result()\n",
        "\n",
        "  # This is the result from our single pub, which had five observables,\n",
        "  # so contains information on all five.\n",
        "\n",
        "  pub_result = job.result()[0]\n",
        "  ```\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d200d1f8",
      "metadata": {},
      "source": [
        "<span id=\"step-4-analyze-the-results\" />\n",
        "\n",
        "### Passaggio 4. Analizza i risultati\n",
        "\n",
        "La fase di analisi è in genere quella in cui è possibile elaborare i risultati utilizzando, ad esempio, la mitigazione dell'errore di misurazione o l'estrapolazione del rumore zero (ZNE). È possibile inserire questi risultati in un altro flusso di lavoro per ulteriori analisi o preparare un grafico dei valori e dei dati chiave. In generale, questo passaggio è specifico per il tuo problema.  Per questo esempio, traccia ciascuno dei valori attesi misurati per il nostro circuito.\n",
        "\n",
        "I valori attesi e le deviazioni standard relativi alle grandezze osservabili specificate in Estimator sono accessibili tramite gli attributi e `PubResult.data.stds` del `PubResult.data.evs` risultato del processo. Per ottenere i risultati da Sampler, utilizzare la `PubResult.data.meas.get_counts()` funzione, che restituirà un `dict` di misurazioni sotto forma di stringhe di bit come chiavi e conteggi come valori corrispondenti. Per ulteriori informazioni, consulta la guida [introduttiva a Sampler](/docs/guides/get-started-with-sampler).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "87143fcc",
      "metadata": {
        "tags": []
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/hello-world/extracted-outputs/87143fcc-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Plot the result\n",
        "\n",
        "values = pub_result.data.evs\n",
        "\n",
        "errors = pub_result.data.stds\n",
        "\n",
        "# plotting graph\n",
        "plt.plot(observables_labels, values, \"-o\")\n",
        "plt.xlabel(\"Observables\")\n",
        "plt.ylabel(\"Values\")\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e6a9ba84",
      "metadata": {},
      "source": [
        "Si noti che per i qubit 0 e 1, i valori attesi indipendenti sia di X che di Z sono 0, mentre le correlazioni (`XX` e `ZZ`) sono 1. Questo è un tratto distintivo dell'entanglement quantistico.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0bc582d8",
      "metadata": {},
      "source": [
        "<span id=\"scale-to-large-numbers-of-qubits\" />\n",
        "\n",
        "## Scalabilità a un numero elevato di qubit\n",
        "\n",
        "Nel campo dell'informatica quantistica, il lavoro su scala industriale è fondamentale per compiere progressi in questo settore. Questo tipo di lavoro richiede calcoli su scala molto più ampia, con circuiti che possono utilizzare oltre 100 qubit e oltre 1000 gate. Questo esempio mostra come è possibile eseguire operazioni su scala industriale su IBM® QPU creando e analizzando uno stato GHZ a 100 qubit.  Utilizza il flusso di lavoro dei modelli Qiskit e termina misurando il valore atteso $\\langle Z_0 Z_i \\rangle $ per ciascun qubit.\n",
        "\n",
        "<span id=\"step-1-map-the-problem\" />\n",
        "\n",
        "### Passo 1. Mappare il problema\n",
        "\n",
        "Scrivi una funzione che restituisca un `QuantumCircuit` che prepara uno $n$ stato GHZ a -qubit (essenzialmente uno stato di Bell esteso), quindi utilizza tale funzione per preparare uno stato GHZ a 100-qubit e raccogliere gli osservabili da misurare.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "2ac02692",
      "metadata": {},
      "outputs": [],
      "source": [
        "def get_qc_for_n_qubit_GHZ_state(n: int) -> QuantumCircuit:\n",
        "    \"\"\"This function will create a qiskit.QuantumCircuit (qc)\n",
        "        for an n-qubit GHZ state.\n",
        "\n",
        "    Args:\n",
        "        n (int): Number of qubits in the n-qubit GHZ state\n",
        "\n",
        "    Returns:\n",
        "        QuantumCircuit: Quantum circuit that generate the n-qubit GHZ state,\n",
        "            assuming all qubits start in the 0 state\n",
        "    \"\"\"\n",
        "    if isinstance(n, int) and n >= 2:\n",
        "        qc = QuantumCircuit(n)\n",
        "        qc.h(0)\n",
        "        for i in range(n - 1):\n",
        "            qc.cx(i, i + 1)\n",
        "    else:\n",
        "        raise Exception(\"n is not a valid input\")\n",
        "    return qc\n",
        "\n",
        "\n",
        "# Create a new circuit with 100 qubits in the GHZ state\n",
        "n = 100\n",
        "qc = get_qc_for_n_qubit_GHZ_state(n)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5b3d0d74",
      "metadata": {},
      "source": [
        "Successivamente, mappare gli operatori di interesse. Questo esempio utilizza gli `ZZ` operatori tra i qubit per esaminare il comportamento man mano che si allontanano.  Valori di aspettativa sempre più imprecisi (corrotti) tra qubit distanti rivelerebbero il livello di rumore presente.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "863a4ec9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# ZZII...II, ZIZI...II, ... , ZIII...IZ\n",
        "operator_strings = [\n",
        "    \"Z\" + \"I\" * i + \"Z\" + \"I\" * (n - 2 - i) for i in range(n - 1)\n",
        "]\n",
        "\n",
        "operators = [SparsePauliOp(operator) for operator in operator_strings]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a0b462ce",
      "metadata": {},
      "source": [
        "<span id=\"step-2-optimize-the-problem-for-execution-on-quantum-hardware\" />\n",
        "\n",
        "### Passo 2. Ottimizzare il problema per l'esecuzione su hardware quantistico\n",
        "\n",
        "Il codice seguente trasforma il circuito e gli osservabili per adattarli all'ISA del backend. È necessario che tu abbia già [salvato le tue credenziali.](/docs/guides/cloud-setup)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "428f05e7",
      "metadata": {},
      "outputs": [],
      "source": [
        "service = QiskitRuntimeService()\n",
        "\n",
        "backend = service.least_busy(\n",
        "    simulator=False, operational=True, min_num_qubits=100\n",
        ")\n",
        "pm = generate_preset_pass_manager(optimization_level=1, backend=backend)\n",
        "\n",
        "isa_circuit = pm.run(qc)\n",
        "isa_operators_list = [op.apply_layout(isa_circuit.layout) for op in operators]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2d2b5065",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-on-hardware\" />\n",
        "\n",
        "### Passaggio 3. Eseguire su hardware\n",
        "\n",
        "Invia il lavoro e attiva la soppressione degli errori utilizzando una tecnica volta a ridurre gli errori denominata “[disaccoppiamento dinamico](/docs/api/qiskit-ibm-runtime/options-dynamical-decoupling-options) ”. Il livello di resilienza indica il grado di resilienza da implementare per far fronte agli errori. Livelli più elevati producono risultati più accurati, a scapito di tempi di elaborazione più lunghi.  Per ulteriori spiegazioni sulle opzioni impostate nel codice riportato di seguito, consultare la sezione “[Tecniche di mitigazione e soppressione degli errori](/docs/guides/error-mitigation-and-suppression-techniques) ”.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "3aaa5025",
      "metadata": {},
      "outputs": [],
      "source": [
        "options = EstimatorOptions()\n",
        "options.resilience_level = 1\n",
        "options.dynamical_decoupling.enable = True\n",
        "options.dynamical_decoupling.sequence_type = \"XY4\"\n",
        "\n",
        "# Create an Estimator object\n",
        "estimator = Estimator(backend, options=options)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "b4c3d3e7-0a0f-4023-8948-1082e225f46c",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "d9mqnjmh4e6s738vioqg\n"
          ]
        }
      ],
      "source": [
        "# Submit the circuit to Estimator\n",
        "job = estimator.run([(isa_circuit, isa_operators_list)])\n",
        "job_id = job.job_id()\n",
        "print(job_id)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0bc64091",
      "metadata": {},
      "source": [
        "<span id=\"step-4-post-process-results\" />\n",
        "\n",
        "### Passaggio 4. Risultati della post-elaborazione\n",
        "\n",
        "Una volta completato il lavoro, traccia i risultati e nota che $\\langle Z_0 Z_i \\rangle$ diminuisce all'aumentare di $i$, anche se in una simulazione ideale tutti i $\\langle Z_0 Z_i \\rangle$ dovrebbero essere pari a 1.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "de91ebd0",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/hello-world/extracted-outputs/de91ebd0-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# data\n",
        "data = list(range(1, len(operators) + 1))  # Distance between the Z operators\n",
        "result = job.result()[0]\n",
        "values = result.data.evs  # Expectation value at each Z operator.\n",
        "values = [\n",
        "    v / values[0] for v in values\n",
        "]  # Normalize the expectation values to evaluate how they decay with distance.\n",
        "\n",
        "# plotting graph\n",
        "plt.plot(data, values, marker=\"o\", label=\"100-qubit GHZ state\")\n",
        "plt.xlabel(\"Distance between qubits $i$\")\n",
        "plt.ylabel(r\"$\\langle Z_i Z_0 \\rangle / \\langle Z_1 Z_0 \\rangle $\")\n",
        "plt.legend()\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0afc307c",
      "metadata": {},
      "source": [
        "Il grafico precedente mostra che all'aumentare della distanza tra i qubit, il segnale decade a causa della presenza di rumore.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e7c24c81",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Suggerimenti\">\n",
        "  * Prova uno di questi tutorial:\n",
        "    * [Stima dell'energia dello stato fondamentale della catena di Heisenberg con VQE](/docs/tutorials/spin-chain-vqe)\n",
        "    * Risolvi i problemi di ottimizzazione utilizzando [QAOA](/docs/tutorials/quantum-approximate-optimization-algorithm)\n",
        "    * Addestrare modelli [di kernel quantistici](/docs/tutorials/quantum-kernel-training) per attività di apprendimento automatico\n",
        "  * Trova le istruzioni dettagliate per l'installazione nella guida [Install Qiskit](/docs/guides/install-qiskit).\n",
        "  * Se preferisci non installare Qiskit localmente, leggi le opzioni disponibili per utilizzare Qiskit in un [ambiente di sviluppo online](/docs/guides/online-lab-environments).\n",
        "  * Per salvare più credenziali di accesso o specificare altre opzioni dell'account, consulta le istruzioni dettagliate nella guida [Salva le tue credenziali di accesso](/docs/guides/save-credentials#save-your-access-credentials).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "celltoolbar": "Raw Cell Format",
    "hours": 0.5,
    "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"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "state": {},
        "version_major": 2,
        "version_minor": 0
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}