{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "d0e7f54f-e951-44d4-8cd8-5b539cf5c91c",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Esempi di esecutori testamentari\"\n",
        "description: \"Esempi pratici di utilizzo della primitiva Executor in qiskit-ibm-runtime.\"\n",
        "---\n",
        "\n",
        "<span id=\"executor-examples\" />\n",
        "\n",
        "# Esempi di esecutori testamentari\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a53ccd93-5bca-4dfb-a8a0-fcf4ed046fa7",
      "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 sulla base dei seguenti requisiti.\n",
        "    Si consiglia di utilizzare queste versioni o quelle più recenti.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.4.0\n",
        "    qiskit-ibm-runtime~=0.46.1\n",
        "    samplomatic~=0.18.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fed832ee-87a7-4261-874d-84002f3863b5",
      "metadata": {},
      "source": [
        "Gli esempi riportati in questa sezione illustrano alcuni modi comuni di utilizzare la primitiva Executor. Prima di eseguire questi esempi, segui le istruzioni riportate [nella guida rapida](/docs/guides/directed-execution-model) \"[Installazione di Qiskit](/docs/guides/install-qiskit) ed Executor\".\n",
        "\n",
        "<span id=\"before-you-begin\" />\n",
        "\n",
        "## Prima di iniziare\n",
        "\n",
        "Alcuni degli esempi di codice presenti in questa pagina utilizzano `samplex`, che fa parte del pacchetto Samplomatic.  Pertanto, prima di eseguire quei blocchi di codice, è necessario installare Samplomatic, come illustrato nel blocco di codice seguente.  Per ulteriori informazioni, consultare la [documentazione di Samplomatic](https://qiskit.github.io/samplomatic).\n",
        "\n",
        "```python\n",
        "pip install samplomatic\n",
        "\n",
        "# For visualization support, include the visualization dependencies.\n",
        "# pip install samplomatic[vis]\n",
        "```\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "19549d62-4095-458d-a691-00b9bc456ed5",
      "metadata": {},
      "source": [
        "<span id=\"example-parameterized-circuit\" />\n",
        "\n",
        "## Esempio: circuito parametrizzato\n",
        "\n",
        "Questo esempio illustra come aggiungere elementi di circuito con parametri, nonché come aggiungere elementi Samplex. Si articola nelle seguenti fasi:\n",
        "\n",
        "1. Configurare il circuito: generare e transpilare il circuito di destinazione.\n",
        "2. Preparare un samplex: raggruppare i gate e le misurazioni in riquadri annotati e generare il modello del circuito e la coppia samplex.\n",
        "3. Esegui: aggiungi un elemento di circuito e un elemento Samplex a un `QuantumProgram` ed esegui entrambi in un unico processo.\n",
        "\n",
        "<span id=\"set-up-the-circuit\" />\n",
        "\n",
        "### Configurare il circuito\n",
        "\n",
        "Preparare uno stato GHZ a tre qubit, ruotare i qubit attorno all'asse di Pauli-Z e misurare i qubit nella base computazionale.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "caf43d3e-ed55-4805-8d19-6c0980eeb1dc",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.circuit import Parameter, QuantumCircuit\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService, Executor\n",
        "from qiskit_ibm_runtime.quantum_program import QuantumProgram\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "import numpy as np\n",
        "from samplomatic import build\n",
        "from samplomatic.transpiler import generate_boxing_pass_manager\n",
        "\n",
        "# Generate the circuit\n",
        "circuit = QuantumCircuit(3)\n",
        "circuit.h(0)\n",
        "circuit.h(1)\n",
        "circuit.cz(0, 1)\n",
        "circuit.h(1)\n",
        "circuit.h(2)\n",
        "circuit.cz(1, 2)\n",
        "circuit.h(2)\n",
        "circuit.rz(Parameter(\"theta\"), 0)\n",
        "circuit.rz(Parameter(\"phi\"), 1)\n",
        "circuit.rz(Parameter(\"lam\"), 2)\n",
        "circuit.measure_all()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f95bc53d-ed01-4b94-988b-1e497916d0fa",
      "metadata": {},
      "source": [
        "Specificare il backend e trasporre il circuito in modo che utilizzi solo istruzioni supportate dalla QPU (circuito denominato \"architecture del set di istruzioni\" o ISA).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "bf633f01-372f-4519-b89d-ab4075255bd9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Initialize the service and choose a backend\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "# Transpile the circuit to ISA\n",
        "preset_pass_manager = generate_preset_pass_manager(\n",
        "    backend=backend, optimization_level=3\n",
        ")\n",
        "isa_circuit = preset_pass_manager.run(circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fbecf32d-d1b9-4e12-ab56-0a1ede7ebf04",
      "metadata": {},
      "source": [
        "<span id=\"prepare-the-samplex\" />\n",
        "\n",
        "### Preparare il campione\n",
        "\n",
        "Utilizza la `generate_boxing_pass_manager` funzione di comodità e i relativi parametri di rotazione per raggruppare porte a due qubit e misurazioni in riquadri e applicare annotazioni di rotazione.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "8d6d64ad-12ee-4c0c-a683-d1178600d3c7",
      "metadata": {},
      "outputs": [],
      "source": [
        "boxing_pm = generate_boxing_pass_manager(\n",
        "    # Add gate twirling\n",
        "    enable_gates=True,\n",
        "    # Add measurement twirling\n",
        "    enable_measures=True,\n",
        ")\n",
        "\n",
        "boxed_circuit = boxing_pm.run(isa_circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2e8fb1f9-4b15-4161-9f8f-1c24d64b0045",
      "metadata": {},
      "source": [
        "Utilizza il `build` metodo per generare il circuito modello e il samplex.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "90e21ca1-7f39-4636-b65e-28685b610a3c",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Build the template circuit and the samplex\n",
        "template_circuit, samplex = build(boxed_circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "521a7263-8d2f-46fd-a261-c23ae56aa5b5",
      "metadata": {},
      "source": [
        "<span id=\"execute-the-circuits\" />\n",
        "\n",
        "### Esegui i circuiti\n",
        "\n",
        "Executor esegue `QuantumProgram` gli oggetti. Ciascuno `QuantumProgram` può contenere diversi elementi. Questo esempio aggiunge un elemento di circuito e un elemento Samplex da eseguire. Per ulteriori dettagli, consultare [la sezione \"Input e output di Executor\"](/docs/guides/executor-input-output).\n",
        "\n",
        "Il primo passo consiste nell'inizializzare un programma vuoto, richiedendo `1024` delle immagini per ogni configurazione di ciascun elemento.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "85d7d9ef-a74c-42e4-a758-0f490e29275d",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Generate a quantum program\n",
        "program = QuantumProgram(shots=1024)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8869d18d-cc0e-4556-a195-cd6b590bcef7",
      "metadata": {},
      "source": [
        "`QuantumProgram`Aggiungi l'elemento del circuito al. Questo elemento del circuito è composto da due parti: il circuito ISA e 10 set di valori dei suoi parametri.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "19963674-3e72-473c-b24a-228316946dc5",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Append the circuit and the parameter values to the program\n",
        "program.append_circuit_item(\n",
        "    isa_circuit,\n",
        "    circuit_arguments=np.random.rand(10, 3),  # 10 sets of parameter values\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "41505f83-a7a6-4ea8-a7fc-a3fb45a2992a",
      "metadata": {},
      "source": [
        "`QuantumProgram` Aggiungi l'elemento samplex a con questi argomenti:\n",
        "\n",
        "* Il circuito modello e il samplex generato dalla `build` funzione\n",
        "* Dieci serie di valori dei parametri per il circuito originale\n",
        "* Il numero di randomizzazioni da eseguire\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "d6b07700-5834-4baa-a08a-434516f5bc07",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Append the template circuit and samplex as a samplex item\n",
        "program.append_samplex_item(\n",
        "    template_circuit,\n",
        "    samplex=samplex,\n",
        "    samplex_arguments={\n",
        "        \"parameter_values\": np.random.rand(\n",
        "            10, 3\n",
        "        ),  # 10 sets of parameter values\n",
        "    },\n",
        "    shape=(2, 14, 10),\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f39e3e78-5953-4801-b521-dd48ae487acf",
      "metadata": {},
      "source": [
        "<span id=\"run-the-executor-job\" />\n",
        "\n",
        "### Esegui il processo Executor\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "149addb2-e76f-427c-bac4-54b6a83ddb0a",
      "metadata": {},
      "outputs": [],
      "source": [
        "# initialize an Executor with default options\n",
        "executor = Executor(mode=backend)\n",
        "\n",
        "# Submit the job\n",
        "job = executor.run(program)\n",
        "\n",
        "# Retrieve the result\n",
        "result = job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "93698fec-cff7-4153-8cbb-f7e39c972d9a",
      "metadata": {},
      "source": [
        "Recupera il risultato per ogni attività.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "77235bf8-bcac-43fb-89b0-9ba74b976053",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Access the results of the classical register of task #0, the CircuitItem\n",
        "result_0 = result[0][\"meas\"]\n",
        "\n",
        "# Access the results of the classical register of task #1, the SamplexItem\n",
        "result_1 = result[1][\"meas\"]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "64063941-87b5-4c5d-bbf9-8920c24a216f",
      "metadata": {},
      "source": [
        "<span id=\"example-perform-pec\" />\n",
        "\n",
        "## Esempio: Eseguire il PEC\n",
        "\n",
        "Questo esempio illustra come utilizzare un elemento Samplex per eseguire la cancellazione probabilistica degli errori ( [PEC](/docs/guides/error-mitigation-and-suppression-techniques#pec) ) al fine di ridurre gli errori.\n",
        "\n",
        "Si consideri una versione speculare di un circuito composto da dieci qubit e due livelli distinti di porte CX. Questi sono i compiti principali:\n",
        "\n",
        "* Esegui il circuito con dei giri.\n",
        "* Eseguire il circuito con mitigazione PEC, come descritto nell'articolo [\"Probabilistic error cancellation with sparse Pauli-Lindblad models on noisy quantum processors\"](https://arxiv.org/abs/2201.09866).\n",
        "\n",
        "Il processo si articola nelle seguenti fasi:\n",
        "\n",
        "1. Configurazione: generare il circuito di destinazione e raggrupparne le operazioni in riquadri.\n",
        "2. Identificare: identificare il rumore delle istruzioni che si desidera attenuare con il PEC.\n",
        "3. Esegui: esegui il circuito su un backend.\n",
        "4. Analisi: elaborare e analizzare i risultati.\n",
        "\n",
        "A titolo di confronto, eseguiremo questo circuito speculare due volte. Una volta con l'applicazione del solo effetto Pauli, e una volta con l'applicazione della correzione PEC.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  L'esecuzione di questo esempio richiede circa 10 minuti su un processore Heron r2.\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"set-up-the-circuit\" />\n",
        "\n",
        "### Configurare il circuito\n",
        "\n",
        "Scegli un backend e prepara un circuito a 10 qubit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "f9e93b2c-154a-4d09-872d-f770bcc669c4",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/executor-examples/extracted-outputs/f9e93b2c-154a-4d09-872d-f770bcc669c4-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit_ibm_runtime import QiskitRuntimeService, Executor\n",
        "from qiskit_ibm_runtime.quantum_program import QuantumProgram\n",
        "from qiskit.circuit import QuantumCircuit, Parameter\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from samplomatic.transpiler import generate_boxing_pass_manager\n",
        "from samplomatic import build\n",
        "\n",
        "# Initialize the service and choose a backend\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "# Prepare a circuit\n",
        "\n",
        "num_qubits = 10\n",
        "num_layers = 10\n",
        "\n",
        "qubits = list(range(num_qubits))\n",
        "circuit = QuantumCircuit(num_qubits)\n",
        "\n",
        "for layer_idx in range(num_layers):\n",
        "    circuit.rx(Parameter(f\"theta_{layer_idx}\"), qubits)\n",
        "    for i in range(num_qubits // 2):\n",
        "        circuit.cz(qubits[2 * i], qubits[2 * i + 1])\n",
        "\n",
        "    circuit.rx(Parameter(f\"phi_{layer_idx}\"), qubits)\n",
        "    for i in range(num_qubits // 2 - 1):\n",
        "        circuit.cz(qubits[2 * i] + 1, qubits[2 * i + 1] + 1)\n",
        "\n",
        "circuit.draw(\"mpl\", scale=0.35, fold=100)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2d76f4f5-48b7-4123-8b6b-32eeaa06527d",
      "metadata": {},
      "source": [
        "Combina il circuito con il suo inverso per creare un circuito speculare.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "f8ac3f75-88ca-40f9-8382-6a427303bb8e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/executor-examples/extracted-outputs/f8ac3f75-88ca-40f9-8382-6a427303bb8e-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "mirror_circuit = circuit.compose(circuit.inverse())\n",
        "mirror_circuit.measure_all()\n",
        "\n",
        "mirror_circuit.draw(\"mpl\", scale=0.35, fold=100)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2bb0692c-3d4f-4a74-807e-6b93ef4ea8d2",
      "metadata": {},
      "source": [
        "Imposta alcuni valori dei parametri:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "c1974bff-c738-43a8-8e27-b85059e2428a",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "\n",
        "parameter_values = np.random.rand(mirror_circuit.num_parameters)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0ca9f203-008b-4190-9e86-affefb303938",
      "metadata": {},
      "source": [
        "Utilizza il gestore di passaggi per trasporre il circuito in un circuito ISA.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "224e0d6d-9238-4fae-aad8-f051c7e34938",
      "metadata": {},
      "outputs": [],
      "source": [
        "preset_pass_manager = generate_preset_pass_manager(\n",
        "    backend=backend,\n",
        "    optimization_level=3,\n",
        ")\n",
        "\n",
        "isa_circuit = preset_pass_manager.run(mirror_circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9dd71644-df3d-4cf3-9e4b-9c7624b54961",
      "metadata": {},
      "source": [
        "Successivamente, raggruppa i gate e le misurazioni in riquadri annotati. Puoi farlo manualmente oppure, per comodità, utilizzare la `generate_boxing_pass_manager` funzione di Samplomatic. `Twirl` Al primo circuito verrà applicata solo la rotazione e pertanto richiede solo l'annotazione. Il secondo circuito verrà eseguito con la mitigazione PEC completa e richiede sia `Twirl` le annotazioni che `InjectNoise` .\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "4afb22f1-b41f-40ed-87f7-c2d0b0f6730c",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Pass manager used to create twirled-annotated boxes.\n",
        "boxing_pm = generate_boxing_pass_manager(\n",
        "    enable_gates=True,\n",
        "    enable_measures=True,\n",
        ")\n",
        "\n",
        "mirror_circuit_twirl = boxing_pm.run(isa_circuit)\n",
        "\n",
        "# Pass manager used to create a new boxed circuit with\n",
        "# both Twirl and InjectNoise annotations.\n",
        "boxing_pm = generate_boxing_pass_manager(\n",
        "    enable_gates=True,\n",
        "    enable_measures=True,\n",
        "    inject_noise_targets=\"gates\",  # no measurement mitigation\n",
        "    inject_noise_strategy=\"uniform_modification\",\n",
        ")\n",
        "\n",
        "mirror_circuit_pec = boxing_pm.run(isa_circuit)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bd0c7cc5-48ba-47ab-84bc-41f832af3d8d",
      "metadata": {},
      "source": [
        "<span id=\"learn-the-noise\" />\n",
        "\n",
        "### Impara a riconoscere il rumore\n",
        "\n",
        "Per ridurre al minimo il numero di esperimenti di apprendimento del rumore, individuare le istruzioni uniche presenti nel secondo circuito (quello con i riquadri contrassegnati con `InjectNoise`). Ai fini della definizione di unicità, due istruzioni \"box\" sono uguali se si verificano entrambe le seguenti condizioni:\n",
        "\n",
        "* Il loro contenuto è identico, fino ai gate a singolo qubit.\n",
        "* La loro `Twirl` annotazione è identica (tutte le altre annotazioni vengono ignorate).\n",
        "\n",
        "Ciò porta a tre istruzioni distinte, ovvero le caselle dei gate pari e dispari e la casella della misurazione finale.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "2f8b325a-ffa4-447a-bf32-8b26b7404b0a",
      "metadata": {},
      "outputs": [],
      "source": [
        "from samplomatic.utils import find_unique_box_instructions\n",
        "\n",
        "unique_box_instructions = find_unique_box_instructions(\n",
        "    mirror_circuit_pec.data\n",
        ")\n",
        "assert len(unique_box_instructions) == 3"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7d496c90-fb07-49e6-a233-451ad4306102",
      "metadata": {},
      "source": [
        "Inizializzare un `NoiseLearnerV3`, scegliere i parametri di apprendimento impostando le relative opzioni ed eseguire un processo di apprendimento del rumore.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "d69204bb-4beb-4b31-b9dd-e8923889685e",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.noise_learner_v3 import NoiseLearnerV3\n",
        "\n",
        "learner = NoiseLearnerV3(backend)\n",
        "\n",
        "learner.options.shots_per_randomization = 128\n",
        "learner.options.num_randomizations = 32\n",
        "learner.options.layer_pair_depths = [0, 1, 2, 4, 16, 32]\n",
        "\n",
        "learner_job = learner.run(unique_box_instructions)\n",
        "\n",
        "learner_job.job_id()\n",
        "learner_result = learner_job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "efe80acb-f12d-4051-84ed-d61a5a93ca23",
      "metadata": {},
      "source": [
        "Converti `result` l'oggetto nel formato richiesto dal samplex utilizzando il `result.to_dict` metodo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "fd63ad99-01ad-492b-9232-91f2377f97f6",
      "metadata": {},
      "outputs": [],
      "source": [
        "noise_maps = learner_result.to_dict(\n",
        "    instructions=unique_box_instructions, require_refs=False\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "89dd2022-db07-46f6-8737-644aa070dcdb",
      "metadata": {},
      "source": [
        "<span id=\"execute-the-circuits\" />\n",
        "\n",
        "### Esegui i circuiti\n",
        "\n",
        "`Executor` esegue `QuantumProgram` gli oggetti. Ciascuno `QuantumProgram` può contenere diversi *elementi*, che vengono aggiunti al programma. Ogni voce rappresenta un'operazione che il programma deve eseguire.\n",
        "\n",
        "Avvia un programma vuoto, richiedendo `1000` immagini per ogni configurazione di ciascun elemento.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "id": "b48b038e-6e7d-4a6a-8f9a-df1389b644fa",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.quantum_program import QuantumProgram\n",
        "\n",
        "# Initialize an empty QuantumProgram\n",
        "program = QuantumProgram(shots=1000)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "845a9fdb-6837-4bda-925c-8795613bb708",
      "metadata": {},
      "source": [
        "Successivamente, crea il circuito modello e il codice di esempio per `mirror_circuit_twirl` e aggiungili al programma. Richiedi `900` anche randomizzazioni dal samplex. Ciò significa che il samplex genererà `900` insiemi di parametri e che ciascun insieme verrà eseguito `1000` un numero di volte pari al numero di shot nella QPU.\n",
        "\n",
        "Questo è il primo compito del programma (risultato 0).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "id": "38942fab-f68d-44ed-b613-362b38a1ca02",
      "metadata": {},
      "outputs": [],
      "source": [
        "template_twirl, samplex_twirl = build(mirror_circuit_twirl)\n",
        "\n",
        "program.append_samplex_item(\n",
        "    template_twirl,\n",
        "    samplex=samplex_twirl,\n",
        "    samplex_arguments={\"parameter_values\": parameter_values},\n",
        "    shape=(900,),\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a30d1536-5339-4f19-b351-1c26891a4817",
      "metadata": {},
      "source": [
        "Allo stesso modo, aggiungi il circuito modello e il samplex creati per `mirror_circuit_pec`, richiedendo `900` delle randomizzazioni.  Questo è il secondo compito del programma (risultato 1).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "id": "16bbb410-b0b7-4011-b4d0-62ffbad30f41",
      "metadata": {},
      "outputs": [],
      "source": [
        "template_pec, samplex_pec = build(mirror_circuit_pec)\n",
        "\n",
        "program.append_samplex_item(\n",
        "    template_pec,\n",
        "    samplex=samplex_pec,\n",
        "    samplex_arguments={\n",
        "        \"parameter_values\": parameter_values,\n",
        "        \"pauli_lindblad_maps\": noise_maps,\n",
        "        \"noise_scales\": {\n",
        "            ref: -1.0 for ref in noise_maps\n",
        "        },  # Set the scales to -1 for PEC\n",
        "    },\n",
        "    shape=(900,),\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "abf9d679-0262-4447-b889-9b06ad3cd77d",
      "metadata": {},
      "source": [
        "Importa `Executor` e invia un lavoro.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "id": "6231e441-87f4-480a-886a-5fdd83631e60",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Twirl result keys:\n",
            " ['meas', 'measurement_flips.meas']\n",
            "\n",
            "Shape of results: (900, 1000, 10)\n",
            "PEC result keys:\n",
            " ['meas', 'measurement_flips.meas', 'pauli_signs']\n",
            "\n",
            "Shape of results: (900, 1000, 10)\n"
          ]
        }
      ],
      "source": [
        "from qiskit_ibm_runtime.executor import Executor\n",
        "\n",
        "executor = Executor(backend)\n",
        "executor_job = executor.run(program)\n",
        "\n",
        "executor_job.job_id()\n",
        "\n",
        "executor_results = executor_job.result()\n",
        "executor_results\n",
        "\n",
        "twirl_result = executor_results[0]\n",
        "\n",
        "print(f\"Twirl result keys:\\n {list(twirl_result.keys())}\\n\")\n",
        "print(f\"Shape of results: {twirl_result['meas'].shape}\")\n",
        "\n",
        "pec_result = executor_results[1]\n",
        "\n",
        "print(f\"PEC result keys:\\n {list(pec_result.keys())}\\n\")\n",
        "print(f\"Shape of results: {pec_result['meas'].shape}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "021b944c-5119-4554-b4e9-2af1cfc906d8",
      "metadata": {},
      "source": [
        "<span id=\"analyze-results\" />\n",
        "\n",
        "### Analizzare i risultati\n",
        "\n",
        "Infine, si procede alla post-elaborazione dei risultati per stimare i valori attesi degli operatori di Pauli-Z su un singolo qubit che agiscono su ciascuno dei dieci qubit attivi (valore atteso: `1.0`).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "a24c1dd9-7f29-40b0-87ad-25c2a03e0431",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Qubit 0 -> 0.77\n",
            "Qubit 1 -> 0.76\n",
            "Qubit 2 -> 0.66\n",
            "Qubit 3 -> 0.71\n",
            "Qubit 4 -> 0.69\n",
            "Qubit 5 -> 0.67\n",
            "Qubit 6 -> 0.62\n",
            "Qubit 7 -> 0.59\n",
            "Qubit 8 -> 0.62\n",
            "Qubit 9 -> 0.68\n"
          ]
        }
      ],
      "source": [
        "# Undo measurement twirling\n",
        "twirl_result_unflipped = (\n",
        "    twirl_result[\"meas\"] ^ twirl_result[\"measurement_flips.meas\"]\n",
        ")\n",
        "\n",
        "# Calculate the expectation values of single-qubit Z operators\n",
        "exp_vals = 1 - 2 * twirl_result_unflipped.mean(axis=1).mean(axis=0)\n",
        "\n",
        "for qubit, val in enumerate(exp_vals):\n",
        "    print(f\"Qubit {qubit} -> {np.round(val, 2)}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "id": "8aa25d47-c4fd-4b20-a36f-fa69d7bd0971",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Qubit 0 -> 0.98\n",
            "Qubit 1 -> 0.99\n",
            "Qubit 2 -> 0.96\n",
            "Qubit 3 -> 0.98\n",
            "Qubit 4 -> 0.98\n",
            "Qubit 5 -> 0.98\n",
            "Qubit 6 -> 0.98\n",
            "Qubit 7 -> 0.95\n",
            "Qubit 8 -> 0.95\n",
            "Qubit 9 -> 0.94\n"
          ]
        }
      ],
      "source": [
        "# Undo measurement twirling\n",
        "pec_result_unflipped = (\n",
        "    pec_result[\"meas\"] ^ pec_result[\"measurement_flips.meas\"]\n",
        ")\n",
        "\n",
        "# Calculate the signs for PEC mitigation\n",
        "signs = np.prod((-1) ** pec_result[\"pauli_signs\"], axis=-1)\n",
        "signs = signs.reshape((signs.shape[0], 1))\n",
        "\n",
        "# Calculate the expectation values of single-qubit Z operators as required by\n",
        "# PEC mitigation\n",
        "exp_vals = 1 - (2 * pec_result_unflipped.mean(axis=1) * signs).mean(axis=0)\n",
        "\n",
        "for qubit, val in enumerate(exp_vals):\n",
        "    print(f\"Qubit {qubit} -> {np.round(val, 2)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cf25d17a-5e90-4e24-a3bf-c86f5bc3444b",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Suggerimenti\">\n",
        "  * Consulta la panoramica [sulle trasmissioni](/docs/guides/primitive-input-output#broadcasting).\n",
        "  * Scopri come utilizzare [le opzioni di Executor](/docs/guides/executor-options).\n",
        "  * Comprendere il [modello di esecuzione diretta](/docs/guides/directed-execution-model).\n",
        "  * Consulta la [documentazione di Samplomatic](https://qiskit.github.io/samplomatic/).\n",
        "  * Scopri come combinare diverse tecniche di mitigazione degli errori quando si utilizza il modello di esecuzione diretta nel tutorial \" [Probabilistic error cancellation with shaded lightcones](https://qiskit.github.io/qiskit-addon-slc/tutorials/01_getting_started.html) \".\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}