{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "33f4bb3c",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Visualizar la sincronización del circuito\"\n",
        "description: \"Visualiza la sincronización de los circuitos generados creando una imagen que puedas ver, descargar o ambas cosas.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore mactex, backgroundcolor, lightgreen */}\n",
        "\n",
        "<span id=\"visualize-circuit-timing\" />\n",
        "\n",
        "# Visualizar la sincronización del circuito\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bfada4f0",
      "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": "ad24e3a0",
      "metadata": {},
      "source": [
        "Aunque el [diagrama de temporización](/docs/guides/visualize-circuit-timing) integrado en Qiskit resulta útil para circuitos estáticos, es posible que no refleje con precisión la temporización de [los circuitos dinámicos](/docs/guides/classical-feedforward-and-control-flow) debido a operaciones implícitas como la difusión y la determinación de ramificaciones. Como parte de la compatibilidad con circuitos dinámicos, la función « Qiskit Runtime » devuelve información precisa sobre la sincronización del circuito en los resultados del trabajo cuando se solicita.\n",
        "\n",
        "<Admonition type=\"note\" title=\"Notas\">\n",
        "  * Esta es una función experimental. Se encuentra en fase de versión preliminar y, por lo tanto, está sujeta a cambios.\n",
        "  * Esta función solo se aplica a los trabajos de muestreo de Qiskit Runtime.\n",
        "  * Aunque el tiempo total de ejecución del circuito figura en los metadatos de «compilación», este NO es el tiempo que se utiliza para la facturación (tiempo de CPU).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "995a99e8",
      "metadata": {},
      "source": [
        "<span id=\"enable-timing-data-retrieval\" />\n",
        "\n",
        "### Habilitar la recuperación de datos de sincronización\n",
        "\n",
        "Para habilitar la recuperación de datos de tiempo, active el indicador `scheduler_timing` experimental al `True` ejecutar el trabajo primitivo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "ab8c6c23",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "qc = QuantumCircuit(2)\n",
        "qc.h(0)\n",
        "qc.cx(0, 1)\n",
        "qc.measure_all()\n",
        "\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "isa_circuit = pm.run(qc)\n",
        "\n",
        "sampler = SamplerV2(backend)\n",
        "sampler.options.experimental = {\n",
        "    \"execution\": {\n",
        "        \"scheduler_timing\": True,\n",
        "    },\n",
        "}\n",
        "\n",
        "sampler_job = sampler.run([isa_circuit])\n",
        "result = sampler_job.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "531b2abd",
      "metadata": {},
      "source": [
        "<span id=\"access-the-circuit-timing-data\" />\n",
        "\n",
        "### Acceder a los datos de tiempos del circuito\n",
        "\n",
        "Cuando se solicita, los datos de tiempos del circuito para cada PUB se incluyen en los metadatos del resultado del trabajo, en `[\"compilation\"][\"scheduler_timing\"][\"timing\"]`la sección. Este campo contiene la información de sincronización sin procesar. Para visualizar la información de tiempos, utilice la herramienta de visualización integrada, tal y como se describe en la sección «[Visualizar los tiempos](#visualize-timings) ».\n",
        "\n",
        "Utiliza el siguiente código para acceder a los datos de tiempos de la primera vuelta de « PUB »:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "b6958d99",
      "metadata": {},
      "outputs": [],
      "source": [
        "job_result = sampler_job.result()\n",
        "circuit_schedule = job_result[0].metadata[\"compilation\"][\"scheduler_timing\"]\n",
        "circuit_schedule_timing = circuit_schedule[\"timing\"]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "20400401",
      "metadata": {},
      "source": [
        "<span id=\"understand-the-raw-timing-data\" />\n",
        "\n",
        "#### Comprender los datos de sincronización sin procesar\n",
        "\n",
        "Aunque la visualización de los datos de temporización del circuito mediante este `draw_circuit_schedule_timing` método es el caso de uso más habitual, puede resultar útil comprender la estructura de los datos de temporización sin procesar que se devuelven. Esto podría ayudarte, por ejemplo, a extraer información mediante programación.\n",
        "\n",
        "Los datos de tiempo devueltos en `[\"compilation\"][\"scheduler_timing\"][\"timing\"]` son una lista de cadenas. Cada cadena representa una única instrucción en un canal y está separada por comas en los siguientes tipos de datos:\n",
        "\n",
        "* `Branch` - Determina si la instrucción se encuentra en una rama de control (then / else) o en una rama principal.\n",
        "* `Instruction` - La puerta y el qubit sobre el que se va a operar.\n",
        "* `Channel` - El canal al que se le asigna la instrucción. Puede ser uno de los siguientes:\n",
        "  * `Qubit x` - El canal de excitación del qubit *x*.\n",
        "  * `AWGRx_y` (lectura del generador de formas de onda arbitrarias) - Utilizado por los canales de lectura para comunicarse durante la medición de qubits. Los argumentos *x* e *y* corresponden al identificador del instrumento de lectura y al número de qubit, respectivamente.\n",
        "* `T0` - La hora de inicio de la clase dentro del horario completo\n",
        "* `Duration` - La duración de la instrucción, expresada en unidades de *dt* segundos, donde 1 dt = 1 ciclo de programación. Puedes averiguar el `dt` valor de un backend utilizando [`backend.dt`](/docs/api/qiskit/qiskit.providers.BackendV2#dt).\n",
        "* `Pulse` - El tipo de funcionamiento por impulsos que se utiliza.\n",
        "\n",
        "Ejemplo:\n",
        "\n",
        "```python\n",
        "main,barrier,Qubit 0,7,0,barrier # A barrier on the main branch on qubit 0 at time 7 with 0 duration\n",
        "main,reset_0,Qubit 0,7,64,play # A reset instruction on the main branch on qubit 0 at time 7 with duration 64 and a play operation\n",
        "...\n",
        "```\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9d34100f",
      "metadata": {},
      "source": [
        "<span id=\"visualize-timings\" />\n",
        "\n",
        "<span id=\"visualize-the-timings\" />\n",
        "\n",
        "### Visualiza los tiempos\n",
        "\n",
        "Con `qiskit-ibm-runtime`v0.43.0 o una versión posterior, puedes visualizar los tiempos de los circuitos. Para visualizar los tiempos, primero debes convertir los metadatos del resultado a `fig` utilizando el [`draw_circuit_schedule_timing` método](https://github.com/Qiskit/qiskit-ibm-runtime/blob/3d1bf1e1d49e5123841639fce259859c90ce9314/qiskit_ibm_runtime/visualization/draw_circuit_schedule_timings.py#L26). Este método devuelve una `plotly` figura, que puedes visualizar directamente, guardar en un archivo o ambas cosas.  Para obtener más información sobre los `plotly` comandos que se deben utilizar, consulte [`fig.show()`](https://plotly.com/python-api-reference/generated/plotly.io.show.html) y [`fig.write_image(\"<path.format>\")`](https://plotly.com/python-api-reference/generated/plotly.io.write_image.html).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "4ad3acfb",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.visualization import draw_circuit_schedule_timing\n",
        "\n",
        "# Create a figure from the metadata\n",
        "fig = draw_circuit_schedule_timing(\n",
        "    circuit_schedule=circuit_schedule_timing,\n",
        "    included_channels=None,\n",
        "    filter_readout_channels=False,\n",
        "    filter_barriers=False,\n",
        "    width=1000,\n",
        ")\n",
        "\n",
        "# Uncomment the following line to display the figure\n",
        "# fig.show(renderer=\"notebook\")\n",
        "\n",
        "# Save to a file\n",
        "# fig.write_html(\"scheduler_timing.html\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2788e992",
      "metadata": {},
      "source": [
        "![Al pasar el cursor por encima del resultado, se muestra información como la hora de inicio, la hora de finalización y la duración.](https://quantum.cloud.ibm.com/docs/images/guides/visualize-circuit-timing/image_1.avif \" Ejemplo de una figura generada\")\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "323a7d38",
      "metadata": {},
      "source": [
        "<span id=\"understand-the-generated-figure\" />\n",
        "\n",
        "#### Entender la figura generada\n",
        "\n",
        "La imagen de los datos de temporización del circuito generados por `draw_circuit_schedule_timing` ofrece la siguiente información:\n",
        "\n",
        "* El eje X representa el tiempo en unidades de *dt* segundos, donde 1 dt = 1 ciclo de programación. Puedes averiguar el `dt` valor de un backend utilizando [`backend.dt`](/docs/api/qiskit/qiskit.providers.BackendV2#dt).\n",
        "* El eje Y representa el canal (piensa en los canales como instrumentos que emiten pulsos).\n",
        "  * `Receive channel` - El único canal que no es un instrumento en sí mismo. Se trata de una instrucción que se transmite por todos los canales que forman parte de un procedimiento de comunicación con el concentrador en ese momento.\n",
        "  * `Qubit x` - El canal de excitación del qubit x.\n",
        "  * `AWGRx_y` (lectura del generador de formas de onda arbitrarias) - Utilizado por los canales de lectura para comunicarse durante la medición de qubits. Los argumentos *x* e *y* corresponden al identificador del instrumento de lectura y al número de qubit, respectivamente.\n",
        "  * `Hub` - Controla la emisión.\n",
        "\n",
        "Además, cada instrucción tiene el formato *X\\_Y*, donde *X* es el nombre de la instrucción y *Y* es el tipo de pulso. Uno aplica los impulsos `play` de control y el otro `capture` registra el estado del qubit. También puedes pasar el cursor por encima de cada instrucción para obtener más detalles. Por ejemplo, la figura anterior muestra un pulso de control para la puerta X aplicado al qubit 10 a los 1161 dt.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "86af09ca",
      "metadata": {},
      "source": [
        "<span id=\"end-to-end-example\" />\n",
        "\n",
        "### Ejemplo global\n",
        "\n",
        "En este ejemplo se muestra cómo activar la opción, obtener la información de temporización del circuito a partir de los metadatos y mostrarla en forma de imagen.\n",
        "\n",
        "En primer lugar, configura el entorno, define los circuitos y conviértelos a circuitos ISA, y define y ejecuta los trabajos.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "b46908a0",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>>  Job ID:    d9bk4smg26ic73dg33fg (DONE)\n"
          ]
        }
      ],
      "source": [
        "from qiskit_ibm_runtime import SamplerV2, QiskitRuntimeService\n",
        "from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "# Create a dynamic circuit\n",
        "\n",
        "qubits = QuantumRegister(1)\n",
        "clbits = ClassicalRegister(1)\n",
        "qc = QuantumCircuit(qubits, clbits)\n",
        "(q0,) = qubits\n",
        "(c0,) = clbits\n",
        "\n",
        "qc.h(q0)\n",
        "qc.measure(q0, c0)\n",
        "with qc.if_test((c0, 1)):\n",
        "    qc.x(q0)\n",
        "qc.measure(q0, c0)\n",
        "\n",
        "# Convert to an ISA circuit for the given backend\n",
        "\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n",
        "isa_circuit = pm.run(qc)\n",
        "\n",
        "# Generate samplers for backend targets\n",
        "sampler = SamplerV2(backend)\n",
        "sampler.options.experimental = {\"execution\": {\"scheduler_timing\": True}}\n",
        "\n",
        "# Submit jobs\n",
        "sampler_job = sampler.run([isa_circuit])\n",
        "result = sampler_job.result()\n",
        "\n",
        "print(\n",
        "    f\">>> {' Job ID:':<10}  {sampler_job.job_id()} ({sampler_job.status()})\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1bd5993c",
      "metadata": {},
      "source": [
        "A continuación, consulta los horarios del circuito:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "7e943812",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'main,rz_0,Qubit 0,897,0,shift_phase\\nmain,sx_0,Qubit 0,897,6,play\\nmain,sx_0,Qubit 0,901,0,shift_phase\\nmain,rz_0,Qubit 0,903,0,shift_phase\\nmain,barrier,Qubit 0,903,0,barrier\\nmain,measure_0,Qubit 0,904,180,play\\nmain,measure_0,AWGR0_0,1025,205,capture\\nmain,barrier,Qubit 0,1431,0,barrier\\nmain,broadcast,Hub,1025,406,broadcast\\nmain,receive,Receive,1431,7,receive\\nthen,x_0,Qubit 0,1446,6,play\\nmain,barrier,Qubit 0,1460,0,barrier\\nmain,measure_0,Qubit 0,1461,180,play\\nmain,measure_0,AWGR0_0,1582,205,capture\\nmain,barrier,Qubit 0,1886,0,barrier\\nmain,barrier,Qubit 0,1886,0,barrier\\nmain,FINI_0,Qubit 0,1887,180,play\\nmain,FINI_0,AWGR0_0,2008,205,capture\\nmain,FINI_0,Qubit 0,2312,6,play\\nmain,FINI_0,Qubit 0,2319,180,play\\nmain,FINI_0,AWGR0_0,2440,205,capture\\nmain,FINI_0,Qubit 0,2744,6,play\\nmain,barrier,Qubit 0,2750,0,barrier\\n'"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Get the circuit schedule timing\n",
        "result[0].metadata[\"compilation\"][\"scheduler_timing\"][\"timing\"]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "04db1f41",
      "metadata": {},
      "source": [
        "Por último, puedes visualizar y guardar la sincronización:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "9d1901c3",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.visualization import draw_circuit_schedule_timing\n",
        "\n",
        "circuit_schedule = result[0].metadata[\"compilation\"][\"scheduler_timing\"][\n",
        "    \"timing\"\n",
        "]\n",
        "fig = draw_circuit_schedule_timing(\n",
        "    circuit_schedule=circuit_schedule,\n",
        "    included_channels=None,\n",
        "    filter_readout_channels=False,\n",
        "    filter_barriers=False,\n",
        "    width=1000,\n",
        ")\n",
        "\n",
        "# Uncomment the following line to display the figure\n",
        "# fig.show(renderer=\"notebook\")\n",
        "\n",
        "# Save to a file\n",
        "# fig.write_html(\"scheduler_timing.html\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9daa7cf7",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximos pasos\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendaciones\">\n",
        "  * [Control clásico de avance y flujo de control](/docs/guides/classical-feedforward-and-control-flow) (circuitos dinámicos)\n",
        "  * [Visualizar circuitos](/docs/guides/visualize-circuits)\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": 5
}