{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "828c3465-62a7-4c42-b376-e3ec32f67595",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Aiuto per l'apprendimento del rumore\"\n",
        "description: \"Inizia a utilizzare il programma di supporto all'apprendimento del rumore per salvare i modelli di rumore creati durante l'esecuzione dei carichi di lavoro in qiskit-ibm-runtime\"\n",
        "---\n",
        "\n",
        "<span id=\"noise-learning-helper\" />\n",
        "\n",
        "# Aiuto per l'apprendimento del rumore\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "40a246f5-4efd-4fb0-861b-c4e013c1572a",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "{/*\n",
        "  DO NOT EDIT THIS CELL!!!\n",
        "  This cell's content is generated automatically by a script. Anything you add\n",
        "  here will be removed next time the notebook is run. To add new content, create\n",
        "  a new cell before or after this one.\n",
        "  */}\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Versioni del pacchetto\">\n",
        "    Il codice di questa pagina è stato sviluppato in base ai seguenti requisiti.\n",
        "    Si consiglia di utilizzare queste versioni o versioni più recenti.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.4.1\n",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    samplomatic~=0.18.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cce93074-df51-4760-9fce-5a520c3bc59a",
      "metadata": {},
      "source": [
        "Le tecniche di mitigazione degli errori [PEA](/docs/guides/error-mitigation-and-suppression-techniques#pea) e [PEC](/docs/guides/error-mitigation-and-suppression-techniques#pec) utilizzano entrambe una componente di apprendimento del rumore basata su un [modello di rumore di Pauli-Lindblad](https://arxiv.org/abs/2201.09866), che viene tipicamente gestita durante l'esecuzione dopo l'invio di uno o più lavori tramite `qiskit-ibm-runtime` senza alcun accesso locale al modello di rumore adattato. Tuttavia, a partire dalla versione `qiskit-ibm-runtime`v0.27.1, sono state create una classe [`NoiseLearner`](/docs/api/qiskit-ibm-runtime/noise-learner) e una classe [`NoiseLearnerOptions`](/docs/api/qiskit-ibm-runtime/options-noise-learner-options) associata per ottenere i risultati di questi esperimenti di apprendimento del rumore. Questi risultati possono quindi essere salvati localmente come e utilizzati come dati `NoiseLearnerResult` di input in esperimenti successivi. Questa pagina offre una panoramica sul suo utilizzo e sulle opzioni disponibili.\n",
        "\n",
        "Inoltre, a partire dalla versione `qiskit-ibm-runtime`v0.47.0, è disponibile una nuova `NoiseLearnerV3` classe compatibile con la primitiva Executor. Questa nuova versione, che rientra anch'essa nel [modello di esecuzione guidata](/docs/guides/directed-execution-model), consente di specificare in modo esplicito i livelli che si desidera addestrare.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  `NoiseLearner` funziona solo con EstimatorV2 e e `NoiseLearnerV3` funziona solo con Executor.\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"noiselearner\" />\n",
        "\n",
        "## `NoiseLearner`\n",
        "\n",
        "<span id=\"overview\" />\n",
        "\n",
        "### Panoramica\n",
        "\n",
        "Il `NoiseLearner` corso prevede esperimenti volti a caratterizzare i processi di rumore sulla base di un modello di rumore di Pauli-Lindblad applicato a uno (o più) circuiti. Dispone di un `run()` metodo che esegue gli esperimenti di apprendimento e accetta come input un elenco di circuiti o un oggetto [PUB](/docs/guides/primitive-input-output), restituendo un oggetto `NoiseLearnerResult` contenente i canali di rumore appresi e i metadati relativi ai lavori inviati. Di seguito è riportato un frammento di codice che illustra come utilizzare il programma di supporto.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "d9a5320d-8ec6-483a-9ecf-931b0f5f5d13",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit.transpiler import CouplingMap\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2\n",
        "from qiskit_ibm_runtime.noise_learner import NoiseLearner\n",
        "from qiskit_ibm_runtime.options import (\n",
        "    NoiseLearnerOptions,\n",
        "    ResilienceOptionsV2,\n",
        "    EstimatorOptions,\n",
        ")\n",
        "\n",
        "# Build a circuit with two entangling layers\n",
        "num_qubits = 27\n",
        "edges = list(CouplingMap.from_line(num_qubits, bidirectional=False))\n",
        "even_edges = edges[::2]\n",
        "odd_edges = edges[1::2]\n",
        "\n",
        "circuit = QuantumCircuit(num_qubits)\n",
        "for pair in even_edges:\n",
        "    circuit.cx(pair[0], pair[1])\n",
        "for pair in odd_edges:\n",
        "    circuit.cx(pair[0], pair[1])\n",
        "\n",
        "# Choose a backend to run on\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy()\n",
        "\n",
        "# Transpile the circuit for execution\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
        "circuit_to_learn = pm.run(circuit)\n",
        "\n",
        "# Instantiate a NoiseLearner object and execute the noise learning program\n",
        "learner = NoiseLearner(mode=backend)\n",
        "job = learner.run([circuit_to_learn])\n",
        "noise_model = job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ef141d65-d14d-4e2b-9813-b8766e29fdb9",
      "metadata": {},
      "source": [
        "Il risultato `NoiseLearnerResult.data` è un elenco di oggetti [`LayerError`](/docs/api/qiskit-ibm-runtime/results-layer-error) contenenti il [modello di rumore](https://arxiv.org/abs/2201.09866) per ogni singolo strato di entanglement appartenente ai circuiti di destinazione. Ciascuno di essi memorizza `LayerError` le informazioni relative al livello, sotto forma di un circuito e di un insieme di etichette di qubit, insieme al modello di [`PauliLindbladError`](/docs/api/qiskit-ibm-runtime/results-pauli-lindblad-error) rumore che è stato appreso per quel determinato livello.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a9be8ff1-7494-407c-853c-50d471a2f55f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Noise learner result contains 2 entries and has the following type:\n",
            " <class 'qiskit_ibm_runtime.utils.noise_learner_result.NoiseLearnerResult'>\n",
            "\n",
            "Each element of `NoiseLearnerResult` then contains an object of type:\n",
            " <class 'qiskit_ibm_runtime.utils.noise_learner_result.LayerError'>\n",
            "\n",
            "And each of these `LayerError` objects possess data on the generators for the error channel: \n",
            "['IIIIIIIIIIIIIIIIIIIIIIIIIIX', 'IIIIIIIIIIIIIIIIIIIIIIIIIIY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIXI',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIXX', 'IIIIIIIIIIIIIIIIIIIIIIIIIXY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIXZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIYI',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIYX', 'IIIIIIIIIIIIIIIIIIIIIIIIIYY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIYZ', 'IIIIIIIIIIIIIIIIIIIIIIIIIZI',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIZX', 'IIIIIIIIIIIIIIIIIIIIIIIIIZY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIZZ', 'IIIIIIIIIIIIIIIIIIIIIIIIXII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIXIX', 'IIIIIIIIIIIIIIIIIIIIIIIIXIY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIXIZ', 'IIIIIIIIIIIIIIIIIIIIIIIIYII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIYIX', 'IIIIIIIIIIIIIIIIIIIIIIIIYIY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIYIZ', 'IIIIIIIIIIIIIIIIIIIIIIIIZII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIZIX', 'IIIIIIIIIIIIIIIIIIIIIIIIZIY',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIZIZ', 'IIIIIIIIIIIIIIIIIIIIIIIXIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIYIII', 'IIIIIIIIIIIIIIIIIIIIIIIZIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIXIIII', 'IIIIIIIIIIIIIIIIIIIIIIXXIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIXYIII', 'IIIIIIIIIIIIIIIIIIIIIIXZIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIYIIII', 'IIIIIIIIIIIIIIIIIIIIIIYXIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIYYIII', 'IIIIIIIIIIIIIIIIIIIIIIYZIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIZIIII', 'IIIIIIIIIIIIIIIIIIIIIIZXIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIZYIII', 'IIIIIIIIIIIIIIIIIIIIIIZZIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIXIIIII', 'IIIIIIIIIIIIIIIIIIIIIXXIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIXYIIII', 'IIIIIIIIIIIIIIIIIIIIIXZIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIYIIIII', 'IIIIIIIIIIIIIIIIIIIIIYXIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIYYIIII', 'IIIIIIIIIIIIIIIIIIIIIYZIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIZIIIII', 'IIIIIIIIIIIIIIIIIIIIIZXIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIZYIIII', 'IIIIIIIIIIIIIIIIIIIIIZZIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIXIIIIII', 'IIIIIIIIIIIIIIIIIIIIXXIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIXYIIIII', 'IIIIIIIIIIIIIIIIIIIIXZIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIYIIIIII', 'IIIIIIIIIIIIIIIIIIIIYXIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIYYIIIII', 'IIIIIIIIIIIIIIIIIIIIYZIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIZIIIIII', 'IIIIIIIIIIIIIIIIIIIIZXIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIIZYIIIII', 'IIIIIIIIIIIIIIIIIIIIZZIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIXIIIIIII', 'IIIIIIIIIIIIIIIIIIIXXIIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIXYIIIIII', 'IIIIIIIIIIIIIIIIIIIXZIIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIYIIIIIII', 'IIIIIIIIIIIIIIIIIIIYXIIIIII',\n",
            " 'IIIIIIIIIIIIIIIIIIIYYIIIIII', 'IIIIIIIIIIIIIIIIIIIYZIIIIII', ...]\n",
            "\n",
            "Along with the error rates: \n",
            "[5.9e-04 5.3e-04 5.7e-04 ... 0.0e+00 1.0e-05 0.0e+00]\n",
            "\n"
          ]
        }
      ],
      "source": [
        "import numpy\n",
        "\n",
        "print(\n",
        "    f\"Noise learner result contains {len(noise_model.data)} entries\"\n",
        "    f\" and has the following type:\\n {type(noise_model)}\\n\"\n",
        ")\n",
        "print(\n",
        "    f\"Each element of `NoiseLearnerResult` then contains\"\n",
        "    f\" an object of type:\\n {type(noise_model.data[0])}\\n\"\n",
        ")\n",
        "# Results are truncated\n",
        "with numpy.printoptions(threshold=200):\n",
        "    print(\n",
        "        f\"And each of these `LayerError` objects possess\"\n",
        "        f\" data on the generators for the error channel: \\n\"\n",
        "        f\"{noise_model.data[0].error.generators}\\n\"\n",
        "    )\n",
        "# Results are truncated\n",
        "with numpy.printoptions(threshold=200):\n",
        "    print(\n",
        "        f\"Along with the error rates: \\n{noise_model.data[0].error.rates}\\n\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "faa3892e-30a5-48f7-87dd-39ab1b0846d9",
      "metadata": {},
      "source": [
        "L'attributo `LayerError.error` del risultato dell'apprendimento del rumore contiene i generatori e i tassi di errore del modello Pauli Lindblad adattato, che ha la forma\n",
        "\n",
        "$\\Lambda(\\rho) = \\exp{\\sum_j r_j \\left(P_j \\rho P_j^\\dagger - \\rho\\right)},$\n",
        "\n",
        "dove $r_j$ sono gli operatori `LayerError.rates` e $P_j$ sono gli operatori di Pauli specificati in `LayerError.generators`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fc0000e6-e77a-4b87-a9ee-262f904953fc",
      "metadata": {},
      "source": [
        "<span id=\"noise-learning-options\" />\n",
        "\n",
        "### Opzioni di apprendimento del rumore\n",
        "\n",
        "Quando si crea un'istanza di `NoiseLearner` un oggetto, è possibile scegliere tra diverse opzioni. Queste opzioni sono racchiuse nella `qiskit_ibm_runtime.options.NoiseLearnerOptions` classe e consentono, tra l'altro, di specificare il numero massimo di livelli da addestrare, il numero di randomizzazioni e la strategia di rotazione. Per ulteriori informazioni, consultare la [`NoiseLearnerOptions`](/docs/api/qiskit-ibm-runtime/options-noise-learner-options) documentazione dell'API.\n",
        "\n",
        "Di seguito è riportato un semplice esempio che illustra come utilizzare il `NoiseLearnerOptions` in un `NoiseLearner` esperimento:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "fcd1bd93-405d-4cfb-a5d1-bb646404aa58",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Build a GHZ circuit\n",
        "circuit = QuantumCircuit(10)\n",
        "circuit.h(0)\n",
        "circuit.cx(range(0, 9), range(1, 10))\n",
        "# Choose a backend to run on\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy()\n",
        "\n",
        "# Transpile the circuit for execution\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
        "circuit_to_run = pm.run(circuit_to_learn)\n",
        "\n",
        "# Instantiate a NoiseLearnerOptions object\n",
        "learner_options = NoiseLearnerOptions(\n",
        "    max_layers_to_learn=3, num_randomizations=32, twirling_strategy=\"all\"\n",
        ")\n",
        "\n",
        "# Instantiate a NoiseLearner object and execute the noise learning program\n",
        "learner = NoiseLearner(mode=backend, options=learner_options)\n",
        "job = learner.run([circuit_to_run])\n",
        "noise_model = job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d952d0cc-497b-45ae-a55e-2b611ebbe4a3",
      "metadata": {},
      "source": [
        "<span id=\"input-noise-model-to-a-primitive\" />\n",
        "\n",
        "### Modello di rumore in ingresso a una primitiva\n",
        "\n",
        "Il modello di rumore appreso sul circuito può essere utilizzato anche come input per la primitiva `EstimatorV2` \" IBM Quantum \". Questo può essere passato alla primitiva in diversi modi. I tre esempi seguenti mostrano come sia possibile passare il modello di rumore direttamente all'attributo `estimator.options` , utilizzando un oggetto `ResilienceOptionsV2` prima di istanziare una primitiva Estimator e passando un dizionario formattato in modo appropriato.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "9826013a-f9fd-4d72-baa7-dc5395b81007",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Pass the noise model to the `estimator.options` attribute directly\n",
        "estimator = EstimatorV2(mode=backend)\n",
        "estimator.options.resilience.layer_noise_model = noise_model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "7ab10595-5c20-4954-9001-70b8879926b4",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Specify options through a ResilienceOptionsV2 object\n",
        "resilience_options = ResilienceOptionsV2(layer_noise_model=noise_model)\n",
        "estimator_options = EstimatorOptions(resilience=resilience_options)\n",
        "estimator = EstimatorV2(mode=backend, options=estimator_options)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "17b1f8de-fe14-4998-898b-ecd409a5efd3",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Specify options by using a dictionary\n",
        "options_dict = {\n",
        "    \"resilience_level\": 2,\n",
        "    \"resilience\": {\"layer_noise_model\": noise_model},\n",
        "}\n",
        "\n",
        "estimator = EstimatorV2(mode=backend, options=options_dict)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8c167b65-2e9a-41b9-b593-edfe80a2fde4",
      "metadata": {},
      "source": [
        "Una volta che il modello di rumore è stato passato all'oggetto `EstimatorV2` , è possibile utilizzarlo per eseguire i carichi di lavoro e applicare le misure di mitigazione degli errori come di consueto.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dad71939-7fe2-42f0-90fe-6974fe0854e7",
      "metadata": {},
      "source": [
        "<span id=\"NoiseLearnerV3\" />\n",
        "\n",
        "<span id=\"noiselearnerv3\" />\n",
        "\n",
        "## NoiseLearnerV3\n",
        "\n",
        "<span id=\"overview\" />\n",
        "\n",
        "### Panoramica\n",
        "\n",
        "Analogamente a `NoiseLearner`, la `NoiseLearnerV3` classe esegue esperimenti volti a caratterizzare i processi di rumore sulla base di un modello di rumore di Pauli-Lindblad per uno o più circuiti. Il suo `run()` metodo accetta un elenco di istruzioni, ciascuna delle quali deve essere un oggetto annotato con Twirl [`BoxOp`](/docs/api/qiskit/qiskit.circuit.BoxOp) contenente operazioni [ISA](/docs/guides/transpile#instruction-set-architecture).\n",
        "\n",
        "Il risultato di un'operazione `NoiseLearnerV3` contiene un elenco di [`NoiseLearnerV3Result`](/docs/api/qiskit-ibm-runtime/results-noise-learner-v3-result) oggetti, uno per ogni istruzione di input.\n",
        "Il codice seguente mostra come utilizzare il programma di supporto.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "0bbd2c21-6045-4954-aee9-339e6b060805",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Found 3 unique layers\n",
            "Each instruction is of type <class 'qiskit.circuit.controlflow.box.BoxOp'>\n",
            "And has annotations: [Twirl(group='pauli', dressing='left', decomposition='rzsx'), InjectNoise(ref='r789B', modifier_ref='', site='before')]\n"
          ]
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit.transpiler import CouplingMap\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService, Executor\n",
        "from qiskit_ibm_runtime.noise_learner_v3 import NoiseLearnerV3\n",
        "from samplomatic.transpiler import generate_boxing_pass_manager\n",
        "from samplomatic.utils import find_unique_box_instructions\n",
        "\n",
        "\n",
        "# Build a circuit with two entangling layers\n",
        "num_qubits = 27\n",
        "edges = list(CouplingMap.from_line(num_qubits, bidirectional=False))\n",
        "even_edges = edges[::2]\n",
        "odd_edges = edges[1::2]\n",
        "\n",
        "circuit = QuantumCircuit(num_qubits)\n",
        "for pair in even_edges:\n",
        "    circuit.cx(pair[0], pair[1])\n",
        "for pair in odd_edges:\n",
        "    circuit.cx(pair[0], pair[1])\n",
        "\n",
        "# Choose a backend to run on\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy()\n",
        "\n",
        "# Transpile the circuit for execution\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
        "isa_circuit = pm.run(circuit)\n",
        "\n",
        "# Run the boxing pass manager to group instructions into annotated boxes\n",
        "boxing_pm = generate_boxing_pass_manager(\n",
        "    enable_gates=True,\n",
        "    enable_measures=False,\n",
        "    inject_noise_targets=\"gates\",  # no measurement mitigation\n",
        "    inject_noise_strategy=\"uniform_modification\",\n",
        ")\n",
        "boxed_circuit = boxing_pm.run(isa_circuit)\n",
        "\n",
        "# Find unique boxed instructions\n",
        "unique_box_instructions = find_unique_box_instructions(boxed_circuit.data)\n",
        "print(f\"Found {len(unique_box_instructions)} unique layers\")\n",
        "print(\n",
        "    f\"Each instruction is of type {type(unique_box_instructions[0].operation)}\"\n",
        ")\n",
        "print(\n",
        "    f\"And has annotations: {unique_box_instructions[0].operation.annotations}\"\n",
        ")\n",
        "\n",
        "# Instantiate a NoiseLearnerV3 object and execute the noise learning program\n",
        "learner = NoiseLearnerV3(backend)\n",
        "learner.options.shots_per_randomization = 128\n",
        "learner.options.num_randomizations = 32\n",
        "learner_job = learner.run(unique_box_instructions)\n",
        "learner_result = learner_job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "937986c1-b08d-4218-ae5d-c9dbfbf4a0cf",
      "metadata": {},
      "source": [
        "Il risultato dell'operazione è un elenco di `NoiseLearnerV3Result` oggetti, uno per ogni insieme di istruzioni contenuto in una casella di input. `NoiseLearnerV3Result` dispone di un `to_pauli_lindblad_map()` metodo che restituisce un [`PauliLindbladMap`](/docs/api/qiskit/qiskit.quantum_info.PauliLindbladMap) oggetto, il quale dispone di metodi per estrarre i generatori, i tassi di errore e altro ancora.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "4a9b686b-cf8d-4986-8fff-83eedda1f2c1",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The Noise learner V3 result contains 3 entries and each has the following type:\n",
            " <class 'qiskit_ibm_runtime.results.noise_learner_v3.NoiseLearnerV3Result'>\n",
            "\n",
            "After converting to PauliLindbladMap, you can extract data  on the generators for the error channel (truncated to 3): \n",
            "<QubitSparsePauliList with 3 elements on 27 qubits: [X_0, Y_0, Z_0]>\n",
            "\n",
            "Along with the error rates (truncated to 3): \n",
            "[0.00026 0.00032 0.00023]\n",
            "\n"
          ]
        }
      ],
      "source": [
        "print(\n",
        "    f\"The Noise learner V3 result contains {len(learner_result)} entries\"\n",
        "    f\" and each has the following type:\\n {type(learner_result[0])}\\n\"\n",
        ")\n",
        "noise_map = learner_result[0].to_pauli_lindblad_map()\n",
        "print(\n",
        "    f\"After converting to PauliLindbladMap, you can extract data \"\n",
        "    f\" on the generators for the error channel \"\n",
        "    f\"(truncated to 3): \\n{noise_map.generators()[:3]}\\n\"\n",
        ")\n",
        "with numpy.printoptions(threshold=20):\n",
        "    print(\n",
        "        f\"Along with the error rates \"\n",
        "        f\"(truncated to 3): \\n{noise_map.rates[:3]}\\n\"\n",
        "    )"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "baa61d6a-7efc-498b-bccd-260871e174df",
      "metadata": {},
      "source": [
        "<span id=\"noise-learning-options\" />\n",
        "\n",
        "### Opzioni di apprendimento del rumore\n",
        "\n",
        "`NoiseLearnerV3` supporta diverse opzioni, tra cui il numero di randomizzazioni e la profondità delle coppie di livelli, per citarne alcune. Come per le primitive, è possibile specificare le opzioni durante o dopo l'istanziazione dell'oggetto `NoiseLearnerV3` . L'esempio di codice precedente mostrava come impostare le `shots_per_randomization` opzioni e `num_randomizations` . Per ulteriori informazioni, consultare la [`NoiseLearnerV3Options`](/docs/api/qiskit-ibm-runtime/options-models-noise-learner-v3-options) documentazione dell'API.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e76e997d-506f-4607-a89a-e4723c640a44",
      "metadata": {},
      "source": [
        "<span id=\"input-a-noise-model-to-executor\" />\n",
        "\n",
        "### Inserire un modello di rumore in Executor\n",
        "\n",
        "Executor segue le intenzioni di progettazione specificate nelle annotazioni del circuito (sotto forma di samplex) e nelle opzioni. `InjectNoise` è l'annotazione che serve a specificare dove inserire il rumore, mentre l'argomento `pauli_lindblad_maps` `samplex` indica quale mappa di rumore utilizzare.\n",
        "\n",
        "Il circuito dell'esempio precedente passa attraverso il gestore dei passaggi di boxing, che raggruppa le istruzioni in caselle annotate. Il codice in questione è riportato qui di seguito per facilitare la comprensione.\n",
        "\n",
        "* `inject_noise_targets=”gates”` specifica di aggiungere le `InjectNoise` annotazioni alle caselle che contengono elementi di intreccio.\n",
        "* `inject_noise_strategy=\"uniform_modification\"` specifica di assegnare lo stesso `ref` valore `modifier_ref` a tutte le caselle equivalenti con `InjectNoise` annotazioni.\n",
        "  * `InjectNoise.ref` è un identificatore univoco utilizzato per assegnare un modello di rumore a quella casella.\n",
        "  * `InjectNoise.modifier_ref` consente di ridimensionare il modello di rumore assegnato a una casella mediante fattori moltiplicativi.\n",
        "\n",
        "```python\n",
        "boxing_pm = generate_boxing_pass_manager(\n",
        "    enable_gates=True,\n",
        "    enable_measures=False,\n",
        "    inject_noise_targets=\"gates\",  # no measurement mitigation\n",
        "    inject_noise_strategy=\"uniform_modification\",\n",
        ")\n",
        "```\n",
        "\n",
        "Il circuito dell'esempio precedente contiene tre caselle, due delle quali contengono `InjectNoise` annotazioni con attributi diversi `ref` (poiché non sono equivalenti).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "3b86853b-6766-4cf6-9a6b-2ea1008aea42",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Annotations of box #0: [Twirl(group='pauli', dressing='left', decomposition='rzsx'), InjectNoise(ref='r789B', modifier_ref='r789B', site='before')]\n",
            "\n",
            "Annotations of box #1: [Twirl(group='pauli', dressing='left', decomposition='rzsx'), InjectNoise(ref='r054B', modifier_ref='r054B', site='before')]\n",
            "\n",
            "Annotations of box #2: [Twirl(group='pauli', dressing='right', decomposition='rzsx')]\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# box_circuit comes from the example above\n",
        "for idx, instruction in enumerate(boxed_circuit):\n",
        "    # The `InjectNoise` annotation defines which boxes to inject noise.\n",
        "    print(f\"Annotations of box #{idx}: {instruction.operation.annotations}\\n\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3ab1e503-b36a-46bd-b5d1-2735c3d0a82d",
      "metadata": {},
      "source": [
        "Il risultato dell'operazione `NoiseLearnerV3` deve essere convertito in un dizionario prima di essere passato a Executor. Le chiavi di questo dizionario sono gli `InjectNoise.ref` attributi, mentre i valori sono le mappe di rumore corrispondenti. Questa mappatura indica a Executor quali modelli di rumore inserire e in quali punti.\n",
        "\n",
        "Il codice seguente mostra come prendere il circuito e il `NoiseLearnerV3` risultato dell'esempio precedente e passarli a Executor, che genererà le varianti del circuito con i modelli di rumore inseriti e le eseguirà sull'hardware.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "96d59082-7adc-482a-b57f-0f7a5c3eb217",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.quantum_program import QuantumProgram\n",
        "from samplomatic import build\n",
        "\n",
        "# Generate a quantum program\n",
        "program = QuantumProgram(shots=1000)\n",
        "\n",
        "# Build the template circuit and samplex pair\n",
        "template_circuit, samplex = build(boxed_circuit)\n",
        "\n",
        "# Convert the NoiseLearnerV3 result to a dictionary\n",
        "noise_maps = learner_result.to_dict(\n",
        "    instructions=unique_box_instructions, require_refs=False\n",
        ")\n",
        "\n",
        "# Append the samplex item and execute\n",
        "program.append_samplex_item(\n",
        "    template_circuit,\n",
        "    samplex=samplex,\n",
        "    samplex_arguments={\n",
        "        \"pauli_lindblad_maps\": noise_maps,\n",
        "    },\n",
        ")\n",
        "\n",
        "executor = Executor(backend)\n",
        "executor_job = executor.run(program)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "936c08fb-7838-4d61-9060-092b479e7909",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Suggerimenti\">\n",
        "  * Consultare il [riferimento API EstimatorOptions](/docs/api/qiskit-ibm-runtime/options-estimator-options) e [il riferimento API ResilienceOptionsV2](/docs/api/qiskit-ibm-runtime/options-resilience-options-v2).\n",
        "  * Scopri di più sulle [tecniche](error-mitigation-and-suppression-techniques) disponibili per la mitigazione e la soppressione degli errori.\n",
        "  * Scopri come implementare [la gestione del rumore in Estimator](/docs/guides/estimator-noise-management).\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
}