{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "3a5616bf-6edb-4539-872a-03217649edcb",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Crear un gestor de pases para el desacoplamiento dinámico\"\n",
        "description: \"Cómo crear un gestor de pases para el desacoplamiento dinámico en Qiskit.\"\n",
        "---\n",
        "\n",
        "<span id=\"create-a-pass-manager-for-dynamical-decoupling\" />\n",
        "\n",
        "# Crear un gestor de pases para el desacoplamiento dinámico\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=\"Versiones del paquete\">\n",
        "    El código de esta página se ha desarrollado teniendo en cuenta los siguientes requisitos.\n",
        "    Recomendamos utilizar estas versiones o versiones más recientes.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.0\n",
        "    qiskit-ibm-runtime~=0.47.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1ed6dc8d-b6f2-43dc-bb40-ceec0f311764",
      "metadata": {},
      "source": [
        "Esta página muestra cómo utilizar el [`PadDynamicalDecoupling`](/docs/api/qiskit/qiskit.transpiler.passes.PadDynamicalDecoupling) pass para añadir al circuito una técnica de supresión de errores llamada *desacoplamiento dinámico*.\n",
        "\n",
        "El desacoplamiento dinámico funciona añadiendo secuencias de pulsos (conocidas como *secuencias de desacoplamiento dinámico* ) a los qubits inactivos para voltearlos alrededor de la esfera de Bloch, lo que anula el efecto de los canales de ruido, suprimiendo así la decoherencia. Estas secuencias de impulsos son similares a los impulsos de reenfoque utilizados en resonancia magnética nuclear. Para una descripción completa, véase [A Quantum Engineer's Guide to Superconducting Qubits](https://arxiv.org/abs/1904.06560).\n",
        "\n",
        "Debido a que el pase `PadDynamicalDecoupling` sólo opera en circuitos programados e involucra compuertas que no son necesariamente compuertas de base de nuestro objetivo, necesitará los parámetros [`ALAPScheduleAnalysis`](/docs/api/qiskit/qiskit.transpiler.passes.ALAPScheduleAnalysis) y [`BasisTranslator`](/docs/api/qiskit/qiskit.transpiler.passes.BasisTranslator) también.\n",
        "\n",
        "Obtén la `target` información del `backend` y guarda los nombres de las operaciones como, ya `basis_gates` que `target` habrá que modificar el para añadir información de temporización de las puertas utilizadas en el desacoplamiento dinámico.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  En estos ejemplos se utiliza el backend `FakeSherbrooke``qiskit_ibm_runtime` simulado de, pero puedes probarlo con cualquier backend real o simulado compatible con Qiskit.  Tus resultados pueden ser diferentes.\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": [
        "Cree un circuito `efficient_su2` a modo de ejemplo. En primer lugar, transpile el circuito al backend, ya que es necesario añadir pulsos de desacoplamiento dinámico después de transpilar y programar el circuito. El desacoplamiento dinámico suele funcionar mejor cuando hay mucho tiempo de inactividad en los circuitos cuánticos, es decir, cuando hay qubits que no se utilizan mientras otros están activos. Este es el caso en este circuito porque las puertas `ecr` de dos qubits se aplican secuencialmente en este 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 secuencia de desacoplamiento dinámico es una serie de puertas que componen a la identidad y están espaciadas regularmente en el tiempo. Por ejemplo, comience creando una secuencia simple llamada XY4 que conste de cuatro puertas.\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": [
        "Debido a la periodicidad de las secuencias de desacoplamiento dinámico, la información sobre el `YGate` debe añadirse al, `target` ya que *no* es una puerta básica, mientras que el `XGate` sí lo es. Sabemos *a priori* que el `YGate` tiene la misma duración y error que el `XGate`, sin embargo, podemos recuperar esas propiedades del `target` y añadirlas de nuevo a los `YGate` objetos. Esta es también la razón por la que `basis_gates` se guardaron por separado, ya que estamos añadiendo la `YGate` instrucción a, `target` aunque no sea una puerta básica real de `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": [
        "Los circuitos Ansatz como `efficient_su2` están parametrizados, por lo que deben tener un valor vinculado a ellos antes de ser enviados al backend. Aquí, asigna parámetros aleatorios.\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": [
        "A continuación, ejecute los pases personalizados. Instancie `PassManager` con `ALAPScheduleAnalysis` y `PadDynamicalDecoupling`.  Ejecute `ALAPScheduleAnalysis` primero para añadir información de temporización sobre el circuito cuántico antes de que se puedan añadir las secuencias de desacoplamiento dinámico regularmente espaciadas. Estas pasadas se realizan en el 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": [
        "Utilice la herramienta de [`timeline_drawer`](/docs/api/qiskit/qiskit.visualization.timeline_drawer) visualización para ver la sincronización del circuito y confirmar que aparece una secuencia espaciada regularmente de `XGate` objetos y `YGate` objetos en el circuito.\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": [
        "Por último, dado que `YGate` no es una puerta base real de nuestro backend, aplique manualmente el pase `BasisTranslator` (es un pase predeterminado, pero se ejecuta antes de la programación, por lo que es necesario aplicarlo de nuevo). La biblioteca de equivalencias de sesión es una biblioteca de equivalencias de circuitos que permite al transpilador descomponer circuitos en puertas base, como también se especifica como argumento.\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": [
        "Ahora, `YGate` los objetos están ausentes de nuestro circuito, y hay información de sincronización explícita en forma de `Delay` puertas. Este circuito transpilado con desacoplamiento dinámico ya está listo para enviarse al backend.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "95fee5f9-9e7d-47db-83c2-309ca03d357a",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximos pasos\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendaciones\">\n",
        "  * Para aprender a utilizar la función `generate_preset_passmanager` en lugar de escribir sus propios pases, empiece por el tema [Ajustes por defecto y opciones de configuración de la transpilación](defaults-and-configuration-options).\n",
        "  * Prueba la guía [de configuración del transpilador Compare](/docs/guides/circuit-transpilation-settings#compare-transpiler-settings).\n",
        "  * Consulte la [documentación de la API de 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
}