{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "797fe94d-93a3-4a7b-8d60-0706d5ab21d5",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Comparar la configuración del transpilador\"\n",
        "description: \"Explora el proceso de transpilación a lo largo de todas las etapas de creación, transpilación y envío de circuitos.\"\n",
        "---\n",
        "\n",
        "<span id=\"compare-transpiler-settings\" />\n",
        "\n",
        "# Comparar la configuración del transpilador\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d403684a-9dc5-433b-a788-789881878d6c",
      "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 posteriores.\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": "a6affcc2-72f4-4f06-8c4c-fc52715b0285",
      "metadata": {},
      "source": [
        "Los distintos ajustes del transpilador ofrecen diferentes tipos de optimización del circuito, a menudo a costa de un mayor tiempo de procesamiento clásico. Esta guía describe paso a paso todo el proceso de creación, transpilación y envío de circuitos para demostrar cómo evaluar el rendimiento de diferentes configuraciones.\n",
        "\n",
        "Ten en cuenta que el mismo ajuste podría mejorar los resultados de un circuito y, al mismo tiempo, perjudicar a otro. Asegúrate de revisar los circuitos transpilados resultantes antes de ejecutarlos en hardware real.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "39f9c961-c52d-46fc-a2aa-464462474b56",
      "metadata": {},
      "source": [
        "<span id=\"set-up-and-create-sample-circuit\" />\n",
        "\n",
        "## Configurar y crear un circuito de prueba\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "790b4934-ae24-4e69-be9f-d82ae639a5e6",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Create circuit to test transpiler on\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "from qiskit.circuit.library import grover_operator, DiagonalGate\n",
        "\n",
        "# Use Statevector object to calculate the ideal output\n",
        "from qiskit.quantum_info import Statevector\n",
        "from qiskit.visualization import plot_histogram\n",
        "from qiskit.transpiler import PassManager\n",
        "\n",
        "from qiskit.circuit.library import XGate\n",
        "from qiskit.quantum_info import hellinger_fidelity"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fe0a4958-b406-4fe4-9415-38a772ad152c",
      "metadata": {},
      "source": [
        "Crea un pequeño circuito para que el transpilador intente optimizarlo. Este ejemplo crea un circuito que ejecuta el algoritmo de Grover con un oráculo que marca el estado `111`. A continuación, simule la distribución ideal (lo que esperaría medir si ejecutara esto en un ordenador cuántico perfecto un número infinito de veces) para compararlo más adelante.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "4ac958d4-b9b5-4939-a359-a9edca7ddb6a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/circuit-transpilation-settings/extracted-outputs/4ac958d4-b9b5-4939-a359-a9edca7ddb6a-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "oracle = DiagonalGate([1] * 7 + [-1])\n",
        "qc = QuantumCircuit(3)\n",
        "qc.h([0, 1, 2])\n",
        "qc = qc.compose(grover_operator(oracle))\n",
        "\n",
        "qc.draw(output=\"mpl\", style=\"iqp\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "6313186e-bc40-432e-9ada-8594d6a26d55",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/circuit-transpilation-settings/extracted-outputs/6313186e-bc40-432e-9ada-8594d6a26d55-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ideal_distribution = Statevector.from_instruction(qc).probabilities_dict()\n",
        "\n",
        "plot_histogram(ideal_distribution)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "964ca1e0-d1c9-40ed-bcf1-babc50f847ed",
      "metadata": {},
      "source": [
        "<span id=\"transpile\" />\n",
        "\n",
        "## Transpilar\n",
        "\n",
        "A continuación, transpile los circuitos para la QPU. Compararás el rendimiento del transpilador con `optimization_level` establecido en `0` (el más bajo) frente a `3` (el más alto). El nivel de optimización más bajo hace lo mínimo necesario para que el circuito funcione en el dispositivo; asigna los qubits del circuito a los qubits del dispositivo y añade puertas de intercambio para permitir todas las operaciones de dos qubits. El nivel de optimización más alto es mucho más inteligente y utiliza muchos trucos para reducir el recuento total de puertas. Dado que las puertas de múltiples qubits tienen altas tasas de error y los qubits se descoheren con el tiempo, los circuitos más cortos deberían dar mejores resultados.\n",
        "\n",
        "<Admonition type=\"important\">\n",
        "  En este ejemplo se utiliza un IBM Quantum®, pero puedes probarlo en cualquier QPU compatible con Qiskit.  Tus resultados pueden ser diferentes.\n",
        "</Admonition>\n",
        "\n",
        "La siguiente celda transpilada `qc` para ambos valores de `optimization_level`, imprime el número de puertas de dos qubits y añade los circuitos transpilados a una lista. Algunos de los algoritmos del transpilador son aleatorios, por lo que establece una semilla para garantizar la reproducibilidad.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "61181ac0-3f89-417f-a31e-9430f63e670b",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Use Qiskit Runtime to run jobs on hardware\n",
        "from qiskit_ibm_runtime import (\n",
        "    QiskitRuntimeService,\n",
        "    SamplerV2 as Sampler,\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "c3062a60-1cdc-46e7-8eb3-efc62a1396bd",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'ibm_marrakesh'"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Select the backend with the fewest number of jobs in the queue\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(\n",
        "    operational=True, simulator=False, min_num_qubits=127\n",
        ")\n",
        "backend.name"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "2a3ebe8c-e47d-4440-b004-f47f6af826f0",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Two-qubit gates (optimization_level=0):  21\n",
            "Two-qubit gates (optimization_level=3):  12\n"
          ]
        }
      ],
      "source": [
        "# Need to add measurements to the circuit\n",
        "qc.measure_all()\n",
        "\n",
        "# Find the correct two-qubit gate\n",
        "twoQ_gates = set([\"ecr\", \"cz\", \"cx\"])\n",
        "for gate in backend.basis_gates:\n",
        "    if gate in twoQ_gates:\n",
        "        twoQ_gate = gate\n",
        "\n",
        "circuits = []\n",
        "for optimization_level in [0, 3]:\n",
        "    pm = generate_preset_pass_manager(\n",
        "        optimization_level, backend=backend, seed_transpiler=0\n",
        "    )\n",
        "    t_qc = pm.run(qc)\n",
        "    print(\n",
        "        f\"Two-qubit gates (optimization_level={optimization_level}): \",\n",
        "        t_qc.count_ops()[twoQ_gate],\n",
        "    )\n",
        "    circuits.append(t_qc)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "99928d6b-a7e7-40c9-b59c-104fc430b57c",
      "metadata": {},
      "source": [
        "Dado que los CNOT suelen tener una alta tasa de error, el circuito transpilado con `optimization_level=3` debería funcionar mucho mejor.\n",
        "\n",
        "Otra forma de mejorar el rendimiento es mediante [el desacoplamiento dinámico](/docs/api/qiskit/qiskit.transpiler.passes.PadDynamicalDecoupling), aplicando una secuencia de puertas a los qubits inactivos. Esto elimina algunas interacciones no deseadas con el entorno. La siguiente celda añade un desacoplamiento dinámico al circuito compilado con `optimization_level=3` y lo añade a la lista.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "b20ebca3-4adb-4a95-9f6a-bb4cbd836daf",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.transpiler.passes.scheduling import (\n",
        "    ASAPScheduleAnalysis,\n",
        "    PadDynamicalDecoupling,\n",
        ")\n",
        "\n",
        "# Get gate durations so the transpiler knows how long each operation takes\n",
        "durations = backend.target.durations()\n",
        "\n",
        "# This is the sequence we'll apply to idling qubits\n",
        "dd_sequence = [XGate(), XGate()]\n",
        "\n",
        "# Run scheduling and dynamic decoupling passes on circuit\n",
        "pm = PassManager(\n",
        "    [\n",
        "        ASAPScheduleAnalysis(durations),\n",
        "        PadDynamicalDecoupling(durations, dd_sequence),\n",
        "    ]\n",
        ")\n",
        "circ_dd = pm.run(circuits[1])\n",
        "\n",
        "# Add this new circuit to our list\n",
        "circuits.append(circ_dd)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "c1c91fbd-acfe-413e-a6c9-ad97f4dd5543",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/circuit-transpilation-settings/extracted-outputs/c1c91fbd-acfe-413e-a6c9-ad97f4dd5543-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "circ_dd.draw(output=\"mpl\", style=\"iqp\", idle_wires=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5bcc75c7-8af0-4862-8e3c-ec4d06aed1f1",
      "metadata": {},
      "source": [
        "<span id=\"execute-the-circuit\" />\n",
        "\n",
        "## Realiza el circuito\n",
        "\n",
        "En este momento, dispones de una lista de circuitos compilados con diferentes configuraciones. A continuación, ejecuta estos circuitos utilizando la primitiva «Sampler» y guarda los resultados en `result`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "c1b36384-fd9b-4e24-a399-32d35fc6fa5b",
      "metadata": {},
      "outputs": [],
      "source": [
        "sampler = Sampler(backend)\n",
        "job = sampler.run(\n",
        "    [(circuit) for circuit in circuits],  # sample all three circuits\n",
        "    shots=8000,\n",
        ")\n",
        "result = job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c85b4da4-592f-45a6-87a2-a8f2d3415576",
      "metadata": {},
      "source": [
        "<span id=\"view-results\" />\n",
        "\n",
        "## Ver resultados\n",
        "\n",
        "Por último, representa gráficamente los resultados de las mediciones del dispositivo en comparación con la distribución ideal. Se puede observar que los resultados con `optimization_level=3` se acercan más a la distribución ideal debido al menor número de puertas, y `optimization_level=3 + dd` se acerca aún más gracias al desacoplamiento dinámico.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "9e86132d-a8b2-40db-af42-53042dfa108b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/circuit-transpilation-settings/extracted-outputs/9e86132d-a8b2-40db-af42-53042dfa108b-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "binary_prob = [\n",
        "    {\n",
        "        k: v / res.data.meas.num_shots\n",
        "        for k, v in res.data.meas.get_counts().items()\n",
        "    }\n",
        "    for res in result\n",
        "]\n",
        "plot_histogram(\n",
        "    binary_prob + [ideal_distribution],\n",
        "    bar_labels=False,\n",
        "    legend=[\n",
        "        \"optimization_level=0\",\n",
        "        \"optimization_level=3\",\n",
        "        \"optimization_level=3 + dd\",\n",
        "        \"ideal distribution\",\n",
        "    ],\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "47a9eec8-7b31-4b2d-a291-559ddfd7a36b",
      "metadata": {},
      "source": [
        "Puedes confirmarlo calculando la [fidelidad de Hellinger](/docs/api/qiskit/quantum_info) entre cada conjunto de resultados y la distribución ideal (cuanto más alta, mejor, y 1 es la fidelidad perfecta).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "d2b5e797-176b-48b9-ac2b-ba73abe9300f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "0.982\n",
            "0.992\n",
            "0.995\n"
          ]
        }
      ],
      "source": [
        "for prob in binary_prob:\n",
        "    print(f\"{hellinger_fidelity(prob, ideal_distribution):.3f}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1b5b7bb9-eedb-45eb-a4cf-9b7708cbbb3e",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximos pasos\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendaciones\">\n",
        "  * Explora algunos recursos avanzados de transpilación, como:\n",
        "\n",
        "    * [Escribir un paso de transpilador personalizado](/docs/guides/custom-transpiler-pass)\n",
        "    * [Crear y transpilar utilizando backends personalizados](/docs/guides/custom-backend)\n",
        "    * [Instalar y utilizar complementos de transpilador](/docs/guides/transpiler-plugins)\n",
        "\n",
        "  * Echa un vistazo a los [tutoriales](/docs/tutorials) disponibles.\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
}