{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "8fe3ca32",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Matériel\"\n",
        "description: \"Cette leçon explore le matériel informatique quantique moderne. Il est basé sur un cours dispensé en direct à l'université de Tokyo.\"\n",
        "---\n",
        "\n",
        "<span id=\"hardware\" />\n",
        "\n",
        "# Matériel\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Masao Tokunari et Tamiya Onodera (14 juin 2024)\n",
        "\n",
        "  Ce cours est basé sur un cours en direct dispensé à l'Université de Tokyo.\n",
        "\n",
        "  L'exposé pdf de cette leçon a été divisé en deux parties. [Télécharger la partie 1](https://ibm.ent.box.com/public/static/ruz8wf353hncenmaywjlfjilflaumnzt.zip) et [télécharger la partie 2](https://ibm.ent.box.com/public/static/tg8vv00ern2bmxmm033xt9oe0fcvwamc.zip). Notez que certains extraits de code peuvent devenir obsolètes car il s'agit d'images statiques.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e0cf0747",
      "metadata": {},
      "source": [
        "<span id=\"1-introduction\" />\n",
        "\n",
        "## 1. Introduction\n",
        "\n",
        "Cette leçon explore le matériel moderne d'informatique quantique.\n",
        "\n",
        "Nous commencerons par vérifier quelques versions et par importer quelques paquets pertinents.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "798d0ab4-34f5-4c64-83f0-02ef5149e6f3",
      "metadata": {},
      "outputs": [],
      "source": [
        "import statistics\n",
        "\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2cc2f2a3-947f-439b-b683-911539f1e6f2",
      "metadata": {},
      "source": [
        "<span id=\"2-backend-and-target\" />\n",
        "\n",
        "## 2. Backend et cible\n",
        "\n",
        "Qiskit fournit une API permettant d'obtenir des informations, à la fois statiques et dynamiques, sur un dispositif quantique. Nous utilisons une instance Backend pour interfacer avec un appareil, qui comprend une instance Target, un modèle de machine abstraite qui résume les caractéristiques pertinentes telles que l'architecture du jeu d'instructions (ISA) et toutes les propriétés ou contraintes qui y sont associées.\n",
        "Utilisons ces instances backend pour obtenir certaines des informations que vous voyez sur la page [Ressources de calcul](/computers) sur IBM Quantum® Platform.   Tout d'abord, nous créons une instance de backend pour l'appareil qui nous intéresse.  Dans ce qui suit, nous choisissons \"ibm\\_kyoto\", \"ibm\\_kawasaki\" ou la machine Eagle la moins occupée. Votre accès aux QPU peut être différent; mettez à jour le nom du backend en conséquence.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "b92ad1bf-6ad4-420c-8a3a-5bfc488d5923",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'ibm_strasbourg'"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "service = QiskitRuntimeService()\n",
        "# backend = service.backend(\"ibm_kawasaki\") # an Eagle, if you have access to ibm_kawasaki\n",
        "backend = service.least_busy(\n",
        "    operational=True, simulator=False, min_num_qubits=127\n",
        ")  # Eagle\n",
        "backend.name"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c082da02-fcc5-4506-b4fe-9015e99e63dc",
      "metadata": {},
      "source": [
        "Nous commençons par quelques informations de base (statiques) sur l'appareil.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "33c39786-d44a-47bb-8245-72eb6b97e394",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "ibm_strasbourg, 127 qubits\n",
            "processor type = {'family': 'Eagle', 'revision': 3} \n",
            "basis gates = ['ecr', 'id', 'rz', 'sx', 'x']\n",
            "\n"
          ]
        }
      ],
      "source": [
        "print(\n",
        "    f\"\"\"\n",
        "{backend.name}, {backend.num_qubits} qubits\n",
        "processor type = {backend.processor_type}\n",
        "basis gates = {backend.basis_gates}\n",
        "\"\"\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "31675447-1a26-4168-a038-09cc7535e037",
      "metadata": {},
      "source": [
        "<span id=\"21-exercise\" />\n",
        "\n",
        "### 2.1 Exercice\n",
        "\n",
        "Essayez d'obtenir les informations de base sur un appareil Heron, \"ibm\\_strasbourg\". Essayez par vous-même, mais le code a été ajouté ci-dessous pour que vous puissiez vérifier par vous-même.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f29afd7e-af40-4cd5-bc0e-a864663a616d",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "ibm_strasbourg, 133 qubits\n",
            "processor type = {'family': 'Heron', 'revision': '1'} \n",
            "basis gates = ['cz', 'id', 'rz', 'sx', 'x']\n",
            "\n"
          ]
        }
      ],
      "source": [
        "a_heron = service.backend(\"ibm_strasbourg\")  # a Heron\n",
        "\n",
        "# your code here\n",
        "print(\n",
        "    f\"\"\"\n",
        "{backend.name}, {a_heron.num_qubits} qubits\n",
        "processor type = {a_heron.processor_type}\n",
        "basis gates = {a_heron.basis_gates}\n",
        "\"\"\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "08fef064-3fc6-4c27-9288-a2e3aa7f5d08",
      "metadata": {},
      "source": [
        "<span id=\"22-coupling-map\" />\n",
        "\n",
        "### 2.2 Carte de couplage\n",
        "\n",
        "Nous allons maintenant dessiner la carte de couplage de l'appareil. Comme vous pouvez le voir, les nœuds sont des qubits numérotés. Les arêtes indiquent les paires auxquelles vous pouvez directement appliquer la porte d'enchevêtrement à 2 qubits.  Cette topologie est appelée \"treillis lourd-hex\".\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "51b87458-a5e8-4e77-a34d-39fe425a5f01",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/hardware/extracted-outputs/51b87458-a5e8-4e77-a34d-39fe425a5f01-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# This function requires that Graphviz is installed. If you need to install Graphviz\n",
        "# you can refer to:\n",
        "# https://graphviz.org/download/#executable-packages for instructions.\n",
        "try:\n",
        "    fig = backend.coupling_map.draw()\n",
        "except RuntimeError as ex:\n",
        "    print(ex)\n",
        "fig"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "881a5350-282c-4a89-b9e2-ac6bf61c6571",
      "metadata": {},
      "source": [
        "<span id=\"3-qubit-properties\" />\n",
        "\n",
        "## 3. Propriétés des qubits\n",
        "\n",
        "Le dispositif Eagle possède 127 qubits.   Obtenons les propriétés de certains d'entre eux.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "9bcb9ce2-5ea8-487b-a7ac-a2956e8cbc34",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "0: QubitProperties(t1=0.000183686508736532, t2=0.00023613944465408068, frequency=4832100227.116953)\n",
            "1: QubitProperties(t1=0.00048794378526038294, t2=9.007098375327869e-05, frequency=4736264354.075363)\n",
            "2: QubitProperties(t1=0.00021247781834456527, t2=7.81037910324034e-05, frequency=4859349851.150393)\n",
            "3: QubitProperties(t1=0.0002936462084765663, t2=0.00011400214529510604, frequency=4679749549.503852)\n",
            "4: QubitProperties(t1=0.00044229440258559125, t2=0.0003181648356339447, frequency=4845872064.050596)\n"
          ]
        }
      ],
      "source": [
        "for qn in range(backend.num_qubits):\n",
        "    if qn >= 5:\n",
        "        break\n",
        "    print(f\"{qn}: {backend.qubit_properties(qn)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "be601762",
      "metadata": {},
      "source": [
        "Calculons la médiane des temps T1 des qubits.   Comparez le résultat à celui obtenu pour l'appareil sur [IBM Quantum Platform.](/)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "e8f398b2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'Median T1: 285.43 μs'"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "t1s = [backend.qubit_properties(qq).t1 for qq in range(backend.num_qubits)]\n",
        "f\"Median T1: {(statistics.median(t1s)*10**6):.2f} \\u03bcs\""
      ]
    },
    {
      "cell_type": "markdown",
      "id": "01695904-2cb2-4f1d-9396-82cc94429d81",
      "metadata": {},
      "source": [
        "<span id=\"31-exercise\" />\n",
        "\n",
        "### 3.1 Exercice\n",
        "\n",
        "Pease calcule la médiane des temps T2 des qubits. Essayez par vous-même, mais le code a été ajouté ci-dessous pour que vous puissiez vérifier par vous-même.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "49fbe7a4-3dea-442f-ae3f-e82df93d406a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'Median T2: 173.10 μs'"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Your code here\n",
        "\n",
        "t2s = [backend.qubit_properties(qq).t2 for qq in range(backend.num_qubits)]\n",
        "f\"Median T2: {(statistics.median(t2s)*10**6):.2f} \\u03bcs\""
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7bdf8873-359e-4b03-98af-ede989a4a96d",
      "metadata": {},
      "source": [
        "<span id=\"32-gate-and-readout-errors\" />\n",
        "\n",
        "### 3.2 Erreurs de porte et d'affichage\n",
        "\n",
        "Nous allons maintenant nous pencher sur les erreurs de point d'entrée. Pour commencer, nous étudions la structure des données de l'instance cible. Il s'agit d'un dictionnaire dont les clés sont les noms des opérations.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "c9188662",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "dict_keys(['measure', 'id', 'sx', 'delay', 'x', 'for_loop', 'rz', 'if_else', 'ecr', 'reset', 'switch_case'])"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "target = backend.target\n",
        "target.keys()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "46e3a8ac-65dc-4973-bd72-820676727f4e",
      "metadata": {},
      "source": [
        "Ses valeurs sont également des dictionnaires.  Examinons quelques-uns des éléments de la valeur (dictionnaire) de l'opération \"sx\".\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "c9b30ede-c00f-4e18-bb72-3bfc06e6afa5",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "0 (0,) InstructionProperties(duration=6e-08, error=0.0007401311759115297)\n",
            "1 (1,) InstructionProperties(duration=6e-08, error=0.0003163759907528654)\n",
            "2 (2,) InstructionProperties(duration=6e-08, error=0.0003183859004638003)\n",
            "3 (3,) InstructionProperties(duration=6e-08, error=0.00042235914178831863)\n",
            "4 (4,) InstructionProperties(duration=6e-08, error=0.011163151923589715)\n"
          ]
        }
      ],
      "source": [
        "for i, qq in enumerate(target[\"sx\"]):\n",
        "    if i >= 5:\n",
        "        break\n",
        "    print(i, qq, target[\"sx\"][qq])"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5a322b40-bbf0-4b54-a151-9ba52f7bffe1",
      "metadata": {},
      "source": [
        "Faisons de même pour les opérations 'ecr' et 'measure'.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "f9cac843-4789-4ca3-84bd-0a4c165820a9",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "0 (0, 14) InstructionProperties(duration=6.6e-07, error=0.01486295709788732)\n",
            "1 (1, 0) InstructionProperties(duration=6.6e-07, error=0.015201590794522601)\n",
            "2 (2, 1) InstructionProperties(duration=6.6e-07, error=0.00697838102630724)\n",
            "3 (2, 3) InstructionProperties(duration=6.6e-07, error=0.008075067943986797)\n",
            "4 (3, 4) InstructionProperties(duration=6.6e-07, error=0.0630164507876913)\n"
          ]
        }
      ],
      "source": [
        "for i, edge in enumerate(target[\"ecr\"]):\n",
        "    if i >= 5:\n",
        "        break\n",
        "    print(i, edge, target[\"ecr\"][edge])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "af36138a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "0 (0,) InstructionProperties(duration=1.6e-06, error=0.0078125)\n",
            "1 (1,) InstructionProperties(duration=1.6e-06, error=0.155029296875)\n",
            "2 (2,) InstructionProperties(duration=1.6e-06, error=0.057373046875)\n",
            "3 (3,) InstructionProperties(duration=1.6e-06, error=0.02880859375)\n",
            "4 (4,) InstructionProperties(duration=1.6e-06, error=0.01318359375)\n"
          ]
        }
      ],
      "source": [
        "for i, qq in enumerate(target[\"measure\"]):\n",
        "    if i >= 5:\n",
        "        break\n",
        "    print(i, qq, target[\"measure\"][qq])"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5d0c106a-3641-42ed-9230-7dc6dbd47252",
      "metadata": {},
      "source": [
        "Comme vous pouvez le constater, les erreurs de lecture ont tendance à être plus importantes que celles de l'opération à 2 qubits, qui à leur tour ont tendance à être plus importantes que l'opération à 1 qubit.\n",
        "\n",
        "Après avoir compris les structures de données, nous sommes prêts à calculer les erreurs médianes pour les portes 'sx' et 'ecr'. Comparez à nouveau les résultats avec ceux obtenus pour l'appareil sur la [plate-forme Quantum IBM](/)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "b239d726",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'Median SX error: 2.277e-04'"
            ]
          },
          "execution_count": 16,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "sx_errors = [inst_prop.error for inst_prop in target[\"sx\"].values()]\n",
        "f\"Median SX error: {(statistics.median(sx_errors)):.3e}\""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "8003f34b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'Median ECR error: 6.895e-03'"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ecr_errors = [inst_prop.error for inst_prop in target[\"ecr\"].values()]\n",
        "f\"Median ECR error: {(statistics.median(ecr_errors)):.3e}\""
      ]
    },
    {
      "cell_type": "markdown",
      "id": "695ee4bd",
      "metadata": {},
      "source": [
        "<span id=\"4-appendix\" />\n",
        "\n",
        "## 4. Annexe\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b538e8b5",
      "metadata": {},
      "source": [
        "L'une des caractéristiques les plus appréciées de Qiskit est sa capacité de visualisation. Il comprend des visualisateurs de circuits, des visualisateurs d'état et de distribution et des visualisateurs de cibles.   Vous avez déjà utilisé les deux premiers dans les précédents carnets jupyter.   Utilisons certaines capacités du visualisateur de cibles.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "97fead46",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/hardware/extracted-outputs/97fead46-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 22,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import plot_gate_map\n",
        "\n",
        "plot_gate_map(backend, font_size=14)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "id": "c9e05530",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/courses/utility-scale-quantum-computing/hardware/extracted-outputs/c9e05530-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 23,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import plot_error_map\n",
        "\n",
        "plot_error_map(backend)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "id": "22a48124-e6b4-4144-bee1-f01fa4c7ccbb",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'2.0.2'"
            ]
          },
          "execution_count": 24,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Check Qiskit version\n",
        "import qiskit\n",
        "\n",
        "qiskit.__version__"
      ]
    },
    {
      "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"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "state": {},
        "version_major": 2,
        "version_minor": 0
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}