{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "3a5616bf-6edb-4539-872a-03217649edcb",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Creare un gestore di passaggi per il disaccoppiamento dinamico\"\n",
        "description: \"Come creare un gestore di passaggi per il disaccoppiamento dinamico in Qiskit.\"\n",
        "---\n",
        "\n",
        "<span id=\"create-a-pass-manager-for-dynamical-decoupling\" />\n",
        "\n",
        "# Creare un gestore di passaggi per il disaccoppiamento dinamico\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a5662d8c-46f8-40a8-92b5-af63c32d303f",
      "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.5.1\n",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1ed6dc8d-b6f2-43dc-bb40-ceec0f311764",
      "metadata": {},
      "source": [
        "In questa pagina viene illustrato come utilizzare il [`PadDynamicalDecoupling`](/docs/api/qiskit/qiskit.transpiler.passes.PadDynamicalDecoupling) per aggiungere al circuito una tecnica di soppressione degli errori chiamata *disaccoppiamento dinamico*.\n",
        "\n",
        "Il disaccoppiamento dinamico funziona aggiungendo sequenze di impulsi (note come *sequenze di disaccoppiamento dinamico* ) ai qubit inattivi per farli girare intorno alla sfera di Bloch, annullando l'effetto dei canali di rumore e sopprimendo così la decoerenza. Queste sequenze di impulsi sono simili agli impulsi di rifocalizzazione utilizzati nella risonanza magnetica nucleare. Per una descrizione completa, si veda [A Quantum Engineer's Guide to Superconducting Qubits](https://arxiv.org/abs/1904.06560).\n",
        "\n",
        "Poiché il passaggio `PadDynamicalDecoupling` opera solo su circuiti programmati e coinvolge porte che non sono necessariamente porte di base del nostro obiettivo, sono necessari i parametri [`ALAPScheduleAnalysis`](/docs/api/qiskit/qiskit.transpiler.passes.ALAPScheduleAnalysis) e [`BasisTranslator`](/docs/api/qiskit/qiskit.transpiler.passes.BasisTranslator) anche i passaggi.\n",
        "\n",
        "Recupera le `target` informazioni dal `backend` e salva i nomi delle operazioni come, `basis_gates` poiché il `target` dovrà essere modificato per aggiungere le informazioni temporali relative ai gate utilizzati nel disaccoppiamento dinamico.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  In questi esempi viene utilizzato il backend `FakeSherbrooke``qiskit_ibm_runtime` fittizio di, ma è possibile provarlo su qualsiasi backend reale o fittizio compatibile con Qiskit.  I tuoi risultati potrebbero essere diversi.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "c55c6e3b-4016-4866-b2ec-19793e89d215",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.fake_provider import FakeSherbrooke\n",
        "\n",
        "backend = FakeSherbrooke()\n",
        "\n",
        "target = backend.target\n",
        "basis_gates = list(target.operation_names)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b8dfccd9-30c9-48dc-88bc-50af3256f187",
      "metadata": {},
      "source": [
        "Creare un circuito `efficient_su2` come esempio. Per prima cosa, si traspila il circuito nel backend, perché gli impulsi di disaccoppiamento dinamico devono essere aggiunti dopo che il circuito è stato transpilato e programmato. Il disaccoppiamento dinamico funziona spesso al meglio quando i circuiti quantistici hanno molto tempo di inattività, cioè ci sono qubit che non vengono utilizzati mentre altri sono attivi. Questo è il caso di questo circuito, perché le porte a due qubit `ecr` sono applicate in sequenza in questo ansatz.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "9479a60c-d5d0-45c7-a93e-a2a488ba8985",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/dynamical-decoupling-pass-manager/extracted-outputs/9479a60c-d5d0-45c7-a93e-a2a488ba8985-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "from qiskit.circuit.library import efficient_su2\n",
        "\n",
        "qc = efficient_su2(12, entanglement=\"circular\", reps=1)\n",
        "pm = generate_preset_pass_manager(1, target=target, seed_transpiler=12345)\n",
        "qc_t = pm.run(qc)\n",
        "qc_t.draw(\"mpl\", fold=-1, idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d3ab848d-2782-431c-b028-69a46cf94360",
      "metadata": {},
      "source": [
        "Una sequenza di disaccoppiamento dinamico è una serie di porte che si compongono all'identità e sono distanziate regolarmente nel tempo. Ad esempio, iniziamo a creare una semplice sequenza chiamata XY4 composta da quattro porte.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "368df772-aee7-4b59-b096-a47e5bc94577",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.circuit.library import XGate, YGate\n",
        "\n",
        "X = XGate()\n",
        "Y = YGate()\n",
        "\n",
        "dd_sequence = [X, Y, X, Y]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d5eafd85-6fea-42ac-8bcb-0abf15635456",
      "metadata": {},
      "source": [
        "A causa della regolarità delle sequenze di disaccoppiamento dinamico, le informazioni relative al `YGate` devono essere aggiunte al `target` poiché *non* si tratta di un gate di base, mentre il `XGate` lo è. Sappiamo *a priori* che ha `YGate` la stessa durata ed errore di `XGate`, quindi possiamo semplicemente recuperare tali proprietà da `target` e aggiungerle nuovamente agli `YGate` oggetti. Questo è anche il motivo per cui i `basis_gates` sono stati salvati separatamente, poiché stiamo aggiungendo `YGate` l'istruzione al `target` anche se non è un vero e proprio gate di base di `ibm_fez`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "cabac6ca-c845-4c05-8c7d-2940717b3120",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler import InstructionProperties\n",
        "\n",
        "y_gate_properties = {}\n",
        "for qubit in range(target.num_qubits):\n",
        "    y_gate_properties.update(\n",
        "        {\n",
        "            (qubit,): InstructionProperties(\n",
        "                duration=target[\"x\"][(qubit,)].duration,\n",
        "                error=target[\"x\"][(qubit,)].error,\n",
        "            )\n",
        "        }\n",
        "    )\n",
        "\n",
        "target.add_instruction(YGate(), y_gate_properties)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d33f64d6-c4e3-4881-a924-f30dfce35106",
      "metadata": {},
      "source": [
        "I circuiti Ansatz come `efficient_su2` sono parametrizzati, quindi devono avere un valore vincolato prima di essere inviati al backend. Qui si assegnano parametri casuali.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "788839cc-9378-4c9d-95fd-df0ec6bc2d64",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "\n",
        "rng = np.random.default_rng(1234)\n",
        "qc_t.assign_parameters(\n",
        "    rng.uniform(-np.pi, np.pi, qc_t.num_parameters), inplace=True\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "36d54ded-1786-41c0-9c8a-75f339dbd160",
      "metadata": {},
      "source": [
        "Quindi, eseguire i passaggi personalizzati. Istanziare `PassManager` con `ALAPScheduleAnalysis` e `PadDynamicalDecoupling`.  Eseguire prima `ALAPScheduleAnalysis` per aggiungere informazioni sulla tempistica del circuito quantistico prima di poter aggiungere le sequenze di disaccoppiamento dinamico a distanza regolare. Questi passaggi vengono eseguiti sul circuito con `.run()`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "334796e7-fb37-42fa-be54-4135b485246b",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler import PassManager\n",
        "from qiskit.transpiler.passes.scheduling import (\n",
        "    ALAPScheduleAnalysis,\n",
        "    PadDynamicalDecoupling,\n",
        ")\n",
        "\n",
        "dd_pm = PassManager(\n",
        "    [\n",
        "        ALAPScheduleAnalysis(target=target),\n",
        "        PadDynamicalDecoupling(target=target, dd_sequence=dd_sequence),\n",
        "    ]\n",
        ")\n",
        "qc_dd = dd_pm.run(qc_t)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b0f68880-066c-4586-a27c-5d0f90d674f7",
      "metadata": {},
      "source": [
        "Utilizzare lo strumento di visualizzazione [`timeline_drawer`](/docs/api/qiskit/qiskit.visualization.timeline_drawer) per vedere la temporizzazione del circuito e confermare che nel circuito compaia una sequenza regolarmente distanziata di `XGate` oggetti e `YGate` oggetti.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "7a552621-a96f-4bb8-ae9b-4ab5a65bbb64",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/dynamical-decoupling-pass-manager/extracted-outputs/7a552621-a96f-4bb8-ae9b-4ab5a65bbb64-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import timeline_drawer\n",
        "\n",
        "timeline_drawer(qc_dd, idle_wires=False, target=target)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "836a4094-0e55-4028-9e2e-cdf561d27049",
      "metadata": {},
      "source": [
        "Infine, poiché `YGate` non è un vero e proprio gate di base del nostro backend, applicare manualmente il passaggio `BasisTranslator` (è un passaggio predefinito, ma viene eseguito prima della programmazione, quindi deve essere applicato di nuovo). La libreria delle equivalenze di sessione è una libreria di equivalenze circuitali che consente al transpiler di decomporre i circuiti in porte di base, come specificato anche come argomento.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "f0f4b29d-1c95-47d2-a7ad-8e130eaff74a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/dynamical-decoupling-pass-manager/extracted-outputs/f0f4b29d-1c95-47d2-a7ad-8e130eaff74a-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.circuit.equivalence_library import (\n",
        "    SessionEquivalenceLibrary as sel,\n",
        ")\n",
        "from qiskit.transpiler.passes import BasisTranslator\n",
        "\n",
        "qc_dd = BasisTranslator(sel, basis_gates)(qc_dd)\n",
        "qc_dd.draw(\"mpl\", fold=-1, idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fafca471-0042-41f8-964c-606b4ee0d5cd",
      "metadata": {},
      "source": [
        "Ora, `YGate` gli oggetti sono assenti dal nostro circuito e ci sono informazioni esplicite sulla temporizzazione sotto forma di `Delay` porte. Questo circuito trasposto con disaccoppiamento dinamico è ora pronto per essere inviato al backend.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "95fee5f9-9e7d-47db-83c2-309ca03d357a",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Suggerimenti\">\n",
        "  * Per imparare a usare la funzione `generate_preset_passmanager` invece di scrivere i propri passaggi, iniziare con l'argomento [Impostazioni predefinite e opzioni di configurazione di Transpilation](defaults-and-configuration-options).\n",
        "  * Prova la guida [Confronta le impostazioni del transpiler](/docs/guides/circuit-transpilation-settings#compare-transpiler-settings).\n",
        "  * Consulta [la documentazione dell'API Transpile](https://docs.quantum-computing.ibm.com/api/qiskit/transpiler).\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
}