{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "33f4bb3c",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Visualiser la synchronisation du circuit\"\n",
        "description: \"Visualisez la synchronisation des circuits générés en créant un graphique que vous pouvez consulter, télécharger, ou les deux.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore mactex, backgroundcolor, lightgreen */}\n",
        "\n",
        "<span id=\"visualize-circuit-timing\" />\n",
        "\n",
        "# Visualiser la synchronisation du circuit\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=\"Versions de package\">\n",
        "    Le code présenté sur cette page a été développé en tenant compte des exigences suivantes.\n",
        "    Nous vous recommandons d'utiliser ces versions ou des versions plus récentes.\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": "ad24e3a0",
      "metadata": {},
      "source": [
        "Si le [volet « Timeline »](/docs/guides/visualize-circuit-timing) intégré à Qiskit s'avère utile pour les circuits statiques, il se peut qu'il ne reflète pas fidèlement la synchronisation des [circuits dynamiques](/docs/guides/classical-feedforward-and-control-flow) en raison d'opérations implicites telles que la diffusion et la détermination des branches. Dans le cadre de la prise en charge dynamique des circuits, le service de calcul d' IBM Quantum fournit, sur demande, des informations précises sur la synchronisation des circuits dans les résultats des tâches.\n",
        "\n",
        "<Admonition type=\"note\" title=\"Remarques\">\n",
        "  * Il s'agit d'une fonctionnalité expérimentale. Il s'agit d'une version préliminaire et elle est donc susceptible d'être modifiée.\n",
        "  * Cette fonction s'applique uniquement aux tâches de l'échantillonneur « IBM Quantum ».\n",
        "  * Bien que la durée totale d'exécution soit indiquée dans les métadonnées de « compilation », il ne s'agit PAS de la durée prise en compte pour la facturation (temps de QPU).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "995a99e8",
      "metadata": {},
      "source": [
        "<span id=\"enable-timing-data-retrieval\" />\n",
        "\n",
        "### Activer la récupération des données de synchronisation\n",
        "\n",
        "Pour activer la récupération des données de chronométrage, activez l'indicateur `scheduler_timing` expérimental lors `True` de l'exécution de la tâche primitive.\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",
        "### Accéder aux données de chronométrage du circuit\n",
        "\n",
        "Sur demande, les données de chronométrage du circuit pour chaque « PUB » sont fournies dans les métadonnées du résultat de la tâche, sous `[\"compilation\"][\"scheduler_timing\"][\"timing\"]`. Ce champ contient les informations brutes relatives au timing. Pour afficher les informations de synchronisation, utilisez l'outil de visualisation intégré, comme décrit dans la section «[ Visualiser les synchronisations](#visualize-timings) ».\n",
        "\n",
        "Utilisez le code suivant pour accéder aux données de temps de circuit pour le premier circuit « 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",
        "#### Comprendre les données brutes de synchronisation\n",
        "\n",
        "Bien que la visualisation des données de synchronisation du circuit à l'aide de cette `draw_circuit_schedule_timing` méthode constitue le cas d'utilisation le plus courant, il peut être utile de comprendre la structure des données de synchronisation brutes renvoyées. Cela pourrait vous aider, par exemple, à extraire des informations par programmation.\n",
        "\n",
        "Les données de synchronisation renvoyées dans `[\"compilation\"][\"scheduler_timing\"][\"timing\"]` sont une liste de chaînes de caractères. Chaque chaîne représente une instruction unique sur un canal donné et est divisée par des virgules en types de données suivants :\n",
        "\n",
        "* `Branch` - Détermine si l'instruction se trouve dans une branche de contrôle (then / else) ou dans une branche principale.\n",
        "* `Instruction` - La porte et le qubit sur lequel opérer.\n",
        "* `Channel` - Le canal auquel l'instruction est attribuée. Il peut s'agir de l'un des éléments suivants :\n",
        "  * `Qubit x` - Le canal de commande du qubit *x*.\n",
        "  * `AWGRx_y` (affichage du générateur de formes d'onde arbitraires) - Utilisé par les canaux d'affichage pour communiquer lors de la mesure des qubits. Les arguments *x* et *y* correspondent respectivement à l'identifiant de l'instrument de lecture et au numéro du qubit.\n",
        "* `T0` - L'heure de début du cours dans le planning complet\n",
        "* `Duration` - La durée de l'instruction, exprimée en unités de *dt* secondes, où 1 dt = 1 cycle de planification. Vous pouvez trouver la `dt` valeur d'un backend en utilisant [`backend.dt`](/docs/api/qiskit/qiskit.providers.BackendV2#dt).\n",
        "* `Pulse` - Le type de fonctionnement par impulsions utilisé.\n",
        "\n",
        "Exemple :\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",
        "### Visualisez les durées\n",
        "\n",
        "Avec `qiskit-ibm-runtime`v0.43.0 ou une version ultérieure, vous pouvez visualiser les temps de propagation des circuits. Pour visualiser les durées, vous devez d'abord convertir les métadonnées du résultat en `fig` à l'aide de [`draw_circuit_schedule_timing` méthode](https://github.com/Qiskit/qiskit-ibm-runtime/blob/3d1bf1e1d49e5123841639fce259859c90ce9314/qiskit_ibm_runtime/visualization/draw_circuit_schedule_timings.py#L26). Cette méthode renvoie une `plotly` figure que vous pouvez afficher directement, enregistrer dans un fichier, ou les deux.  Pour plus d'informations sur les `plotly` commandes à utiliser, consultez [`fig.show()`](https://plotly.com/python-api-reference/generated/plotly.io.show.html) et [`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": [
        "![En passant la souris sur le résultat, vous pouvez voir des informations telles que l'heure de début, l'heure de fin et la durée.](https://quantum.cloud.ibm.com/docs/images/guides/visualize-circuit-timing/image_1.avif \" Exemple de figure générée\")\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "323a7d38",
      "metadata": {},
      "source": [
        "<span id=\"understand-the-generated-figure\" />\n",
        "\n",
        "#### Comprendre le graphique généré\n",
        "\n",
        "L'image des données de synchronisation du circuit fournies par `draw_circuit_schedule_timing` fournit les informations suivantes :\n",
        "\n",
        "* L'axe X représente le temps en unités de *dt* secondes, où 1 dt = 1 cycle de planification. Vous pouvez trouver la `dt` valeur d'un backend en utilisant [`backend.dt`](/docs/api/qiskit/qiskit.providers.BackendV2#dt).\n",
        "* L'axe Y correspond au canal (considérez les canaux comme des instruments qui émettent des impulsions).\n",
        "  * `Receive channel` - Le seul canal qui n'est pas un instrument en soi. Il s'agit d'une instruction diffusée sur tous les canaux participant à une procédure de communication avec le concentrateur à ce moment-là.\n",
        "  * `Qubit x` - Le canal de commande du qubit x.\n",
        "  * `AWGRx_y` (affichage du générateur de formes d'onde arbitraires) - Utilisé par les canaux d'affichage pour communiquer lors de la mesure des qubits. Les arguments *x* et *y* correspondent respectivement à l'identifiant de l'instrument de lecture et au numéro du qubit.\n",
        "  * `Hub` - Gère la diffusion.\n",
        "\n",
        "De plus, chaque instruction se présente sous la forme *X\\_Y*, où *X* correspond au nom de l'instruction et *Y* au type d'impulsion. L'un `play` applique des impulsions de commande, et l'autre `capture` enregistre l'état du qubit. Vous pouvez également passer la souris sur chaque instruction pour obtenir plus de détails. Par exemple, la figure précédente montre une impulsion de commande pour la porte X appliquée au qubit 10 à 1161 dt.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "86af09ca",
      "metadata": {},
      "source": [
        "<span id=\"end-to-end-example\" />\n",
        "\n",
        "### Exemple de bout en bout\n",
        "\n",
        "Cet exemple vous montre comment activer cette option, extraire les informations de synchronisation du circuit à partir des métadonnées et les afficher sous forme d'image.\n",
        "\n",
        "Commencez par configurer l'environnement, définissez les circuits et convertissez-les en circuits ISA, puis définissez et exécutez les tâches.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "b46908a0",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>>  Job ID:    d9mqmk7urbec73e67nng (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": [
        "Ensuite, consultez les horaires du circuit :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "7e943812",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'main,rz_0,Qubit 0,1393,0,shift_phase\\nmain,sx_0,Qubit 0,1393,9,play\\nmain,sx_0,Qubit 0,1397,0,shift_phase\\nmain,rz_0,Qubit 0,1402,0,shift_phase\\nmain,barrier,Qubit 0,1402,0,barrier\\nmain,measure_0,Qubit 0,1402,64,play\\nmain,measure_0,Qubit 0,1466,108,play\\nmain,measure_0,AWGR0_0,1523,325,capture\\nmain,measure_0,Qubit 0,1574,64,play\\nmain,measure_0,Qubit 0,1638,64,play\\nmain,barrier,Qubit 0,2049,0,barrier\\nmain,broadcast,Hub,1523,526,broadcast\\nmain,receive,Receive,2049,7,receive\\nthen,x_0,Qubit 0,2064,9,play\\nmain,barrier,Qubit 0,2082,0,barrier\\nmain,measure_0,Qubit 0,2082,64,play\\nmain,measure_0,Qubit 0,2146,108,play\\nmain,measure_0,AWGR0_0,2203,325,capture\\nmain,measure_0,Qubit 0,2254,64,play\\nmain,measure_0,Qubit 0,2318,64,play\\nmain,barrier,Qubit 0,2753,0,barrier\\nmain,barrier,Qubit 0,2753,0,barrier\\nmain,FINI_0,Qubit 0,2753,64,play\\nmain,FINI_0,Qubit 0,2817,108,play\\nmain,FINI_0,AWGR0_0,2874,325,capture\\nmain,FINI_0,Qubit 0,2925,64,play\\nmain,FINI_0,Qubit 0,2989,64,play\\nmain,FINI_0,Qubit 0,3424,9,play\\nmain,FINI_0,Qubit 0,3433,64,play\\nmain,FINI_0,Qubit 0,3497,108,play\\nmain,FINI_0,AWGR0_0,3554,325,capture\\nmain,FINI_0,Qubit 0,3605,64,play\\nmain,FINI_0,Qubit 0,3669,64,play\\nmain,FINI_0,Qubit 0,4104,9,play\\nmain,barrier,Qubit 0,4113,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": [
        "Enfin, vous pouvez visualiser et enregistrer la chronométrie :\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",
        "## Etapes suivantes\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recommandations\">\n",
        "  * [Commande directe classique et flux de commande](/docs/guides/classical-feedforward-and-control-flow) (circuits dynamiques)\n",
        "  * [Visualiser des circuits](/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
}