{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "5b6cbc5d-14d4-40c6-a702-0ce635c483d8",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Représenter les ordinateurs quantiques pour le transpileur\"\n",
        "description: \"Découvrez les cartes de couplage, les portes de base et les erreurs de processeur pour la transcompilation\"\n",
        "---\n",
        "\n",
        "<span id=\"represent-quantum-computers-for-the-transpiler\" />\n",
        "\n",
        "# Représenter les ordinateurs quantiques pour le transpileur\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "aed00912-17af-4e4c-8639-77957b314b98",
      "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 de cette page a été développé en tenant compte des exigences suivantes.\n",
        "    Nous 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": "9dbd70a7-3353-4286-aa6b-3547d7894f58",
      "metadata": {},
      "source": [
        "Pour convertir un circuit abstrait en un circuit ISA qui peut fonctionner sur une QPU (unité de traitement quantique) spécifique, le transpileur a besoin de certaines informations sur la QPU. Ces informations se trouvent à deux endroits : l'objet `BackendV2` (ou l'ancien `BackendV1`) auquel vous prévoyez de soumettre des travaux et l'attribut `Target` du backend.\n",
        "\n",
        "* Le [`Target`](/docs/api/qiskit/qiskit.transpiler.Target) contient toutes les contraintes pertinentes d'un dispositif, telles que son jeu d'instructions pris en charge, la connectivité des qubits et les informations relatives aux impulsions ou à la synchronisation.\n",
        "* Le [`Backend`](/docs/api/qiskit/qiskit.providers.BackendV2) possède un `Target` par défaut, contient des informations supplémentaires, telles que le [`InstructionScheduleMap`](/docs/api/qiskit/1.4/qiskit.pulse.InstructionScheduleMap), et fournit l'interface permettant de soumettre des tâches de circuit quantique.\n",
        "\n",
        "Vous pouvez également fournir explicitement des informations au transpondeur, par exemple si vous avez un cas d'utilisation spécifique ou si vous pensez que ces informations aideront le transpondeur à générer un circuit plus optimisé.\n",
        "\n",
        "La précision avec laquelle le transpileur produit le circuit le plus approprié pour un matériel spécifique dépend de la quantité d'informations dont dispose le site `Target` ou `Backend` sur ses contraintes.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Étant donné que de nombreux algorithmes de transpilation sous-jacents sont stochastiques, il n'y a aucune garantie qu'un meilleur circuit sera trouvé.\n",
        "</Admonition>\n",
        "\n",
        "Cette page présente plusieurs exemples de transmission d'informations QPU au transcompilateur.\n",
        "\n",
        "<span id=\"default-config\" />\n",
        "\n",
        "<span id=\"default-configuration\" />\n",
        "\n",
        "## Configuration par défaut\n",
        "\n",
        "L'utilisation la plus simple du transpondeur consiste à fournir toutes les informations relatives à la QPU en fournissant le site `Backend` ou `Target`. Pour mieux comprendre le fonctionnement du transpileur, construisez un circuit et transpilez-le avec différentes informations, comme suit.\n",
        "\n",
        "Importez les bibliothèques nécessaires et instanciez la QPU : Afin de convertir un circuit abstrait en un circuit ISA qui peut fonctionner sur un processeur spécifique, le transpileur a besoin de certaines informations sur le processeur.  En règle générale, ces informations sont stockées dans les fichiers [`Backend`](/docs/api/qiskit/qiskit.providers.Backend#backend) ou [`Target`](/docs/api/qiskit/qiskit.transpiler.Target#target) fournie au transpondeur, et aucune autre information n'est nécessaire. Cependant, vous pouvez également fournir explicitement des informations à utiliser par le transpondeur, par exemple si vous avez un cas d'utilisation spécifique ou si vous pensez que ces informations aideront le transpondeur à générer un circuit plus optimisé.\n",
        "\n",
        "Cette rubrique présente plusieurs exemples de transmission d'informations au transcompilateur.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Ces exemples utilisent la cible du backend `qiskit_ibm_runtime`[`FakeSherbrooke`](/docs/api/qiskit-ibm-runtime/fake-provider-fake-sherbrooke#fakesherbrooke) fictif.  Vous pouvez toutefois l'essayer sur n'importe quel backend réel ou fictif compatible avec Qiskit.  Vos résultats peuvent varier.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "a52d0681-5436-4d7a-8d45-9832472e59ca",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime.fake_provider import FakeSherbrooke\n",
        "\n",
        "backend = FakeSherbrooke()\n",
        "target = backend.target"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4064b5ad-8a3a-462b-ae30-29576230c084",
      "metadata": {},
      "source": [
        "Le circuit d'exemple utilise une instance de [`efficient_su2`](/docs/api/qiskit/qiskit.circuit.library.efficient_su2) de la bibliothèque de circuits de Qiskit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "97f9acc1-ac53-4025-b413-485777932a9b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/represent-quantum-computers/extracted-outputs/97f9acc1-ac53-4025-b413-485777932a9b-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.circuit.library import efficient_su2\n",
        "\n",
        "qc = efficient_su2(12, entanglement=\"circular\", reps=1)\n",
        "\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "b133229c-0146-4feb-a366-548d175b858e",
      "metadata": {},
      "source": [
        "Cet exemple utilise les paramètres par défaut pour transposer vers le site `backend`'s `target`, qui fournit toutes les informations nécessaires pour convertir le circuit en un circuit qui fonctionnera sur le backend.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "4b81fb9d-d199-45c5-b119-c1f0b973afe9",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/represent-quantum-computers/extracted-outputs/4b81fb9d-d199-45c5-b119-c1f0b973afe9-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=1, target=target, seed_transpiler=12345\n",
        ")\n",
        "qc_t_target = pass_manager.run(qc)\n",
        "qc_t_target.draw(\"mpl\", idle_wires=False, fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2ad3848d",
      "metadata": {},
      "source": [
        "Cet exemple est utilisé dans les sections suivantes de cette rubrique pour illustrer que la carte de couplage et le jeu d'instructions pris en charge sont les informations essentielles à transmettre au transcompilateur pour une construction optimale du circuit. Le QPU peut généralement sélectionner des paramètres par défaut pour d'autres informations qui ne sont pas transmises, telles que la synchronisation et la planification.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "956f1b7a-80b4-4cda-9ecf-6057f560deb9",
      "metadata": {},
      "source": [
        "<span id=\"coupling-map\" />\n",
        "\n",
        "## Carte de couplage\n",
        "\n",
        "La carte de couplage est un graphique qui montre quels qubits sont connectés et ont donc des portes à deux qubits entre eux. Parfois, ce graphique est directionnel, ce qui signifie que les portes à deux qubits ne peuvent aller que dans une direction. Toutefois, le transpileur peut toujours inverser la direction d'une porte en ajoutant des portes supplémentaires à un qubit. Un circuit quantique abstrait peut toujours être représenté sur ce graphe, même si sa connectivité est limitée, en introduisant des portes SWAP pour déplacer l'information quantique.\n",
        "\n",
        "Les qubits de nos circuits abstraits sont appelés *qubits virtuels* et ceux de la carte de couplage sont des *qubits physiques*. Le transpileur fournit une correspondance entre les qubits virtuels et les qubits physiques. L'une des premières étapes de la transpilation, la *mise en page*, permet d'établir cette correspondance.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Bien que l'étape de routage soit étroitement liée à l'étape d' *agencement* - qui sélectionne les qubits proprement dits - par défaut, cette rubrique les traite comme des étapes distinctes pour des raisons de simplicité. La combinaison du routage et de l'agencement est appelée *cartographie des qubits*.  Pour en savoir plus sur ces étapes, consultez la rubrique [Étapes du transpondeur](transpiler-stages).\n",
        "</Admonition>\n",
        "\n",
        "Passez le mot-clé `coupling_map` en argument pour voir son effet sur le transpileur :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "ec354bee-e06b-42ea-a117-6c1a9308ca73",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/represent-quantum-computers/extracted-outputs/ec354bee-e06b-42ea-a117-6c1a9308ca73-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "coupling_map = target.build_coupling_map()\n",
        "\n",
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=0, coupling_map=coupling_map, seed_transpiler=12345\n",
        ")\n",
        "qc_t_cm_lv0 = pass_manager.run(qc)\n",
        "qc_t_cm_lv0.draw(\"mpl\", idle_wires=False, fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0d3fe7d4-3a40-423d-975f-b4de6613efe9",
      "metadata": {},
      "source": [
        "Comme indiqué ci-dessus, plusieurs portes SWAP ont été insérées (chacune consistant en trois portes CX), ce qui entraînera de nombreuses erreurs sur les dispositifs actuels. Pour voir quels qubits sont sélectionnés dans la topologie réelle des qubits, utilisez le site `plot_circuit_layout` de Qiskit Visualizations :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "9be74535-ed36-4d51-afeb-ee53c3f8a046",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/represent-quantum-computers/extracted-outputs/9be74535-ed36-4d51-afeb-ee53c3f8a046-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import plot_circuit_layout\n",
        "\n",
        "plot_circuit_layout(qc_t_cm_lv0, backend, view=\"physical\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "633744e3-b9e7-4333-ac7b-0089f28e9c27",
      "metadata": {},
      "source": [
        "Cela montre que nos qubits virtuels 0-11 ont été trivialement mis en correspondance avec la ligne de qubits physiques 0-11. Revenons à la valeur par défaut (`optimization_level=1`), qui utilise `VF2Layout` si un routage est nécessaire.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "8035fd05-f7cd-4151-b19a-4968202246e6",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/represent-quantum-computers/extracted-outputs/8035fd05-f7cd-4151-b19a-4968202246e6-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=1, coupling_map=coupling_map, seed_transpiler=12345\n",
        ")\n",
        "qc_t_cm_lv1 = pass_manager.run(qc)\n",
        "qc_t_cm_lv1.draw(\"mpl\", idle_wires=False, fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "217c75f4-4c86-46bb-9a34-b451ff4743ef",
      "metadata": {},
      "source": [
        "Désormais, aucune porte SWAP n'est insérée et les qubits physiques sélectionnés sont les mêmes lorsque l'on utilise la classe `target` .\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "25d9fac3-abda-4b2d-81b4-351dc0772722",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/represent-quantum-computers/extracted-outputs/25d9fac3-abda-4b2d-81b4-351dc0772722-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import plot_circuit_layout\n",
        "\n",
        "plot_circuit_layout(qc_t_cm_lv1, backend, view=\"physical\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "db62df0f",
      "metadata": {},
      "source": [
        "Maintenant, la disposition est dans un anneau.  Comme cette disposition respecte la connectivité du circuit, il n'y a pas de portes SWAP, ce qui permet d'obtenir un circuit de bien meilleure qualité pour l'exécution.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f62e0541",
      "metadata": {},
      "source": [
        "<span id=\"supported-instructions\" />\n",
        "\n",
        "## Instructions prises en charge\n",
        "\n",
        "Chaque ordinateur quantique prend en charge un jeu d'instructions limité.  Chaque porte du circuit doit être traduite en éléments de cet ensemble. Cet ensemble doit être constitué de portes à un et deux qubits qui fournissent un ensemble de portes universelles, ce qui signifie que toute opération quantique peut être décomposée en ces portes.  Cette opération est effectuée par [BasisTranslator](/docs/api/qiskit/qiskit.transpiler.passes.BasisTranslator) et `basis_gates` peut être spécifiée comme argument clé du transpilateur afin de fournir ces informations.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "4445ff03",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "['sx', 'switch_case', 'if_else', 'rz', 'for_loop', 'ecr', 'id', 'reset', 'measure', 'x', 'delay']\n"
          ]
        }
      ],
      "source": [
        "basis_gates = list(target.operation_names)\n",
        "print(basis_gates)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6e9aed06",
      "metadata": {},
      "source": [
        "Les portes à un qubit par défaut sur `FakeSherbrooke` sont `rz`, `x`, et `sx`, et la porte à deux qubits par défaut est `ecr` (résonance croisée avec écho). Les portes CX sont construites à partir de `ecr` portes, de sorte que sur certains QPU, `ecr` est définie comme la porte de base à deux qubits, tandis que sur d'autres, `cx` est la valeur par défaut. La `ecr` porte est la partie qui `cx`\\* s'enclenche\\*. Outre les portes de contrôle, il existe également les instructions `delay``measurement` et.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Les QPU ont des portes de base par défaut, mais vous pouvez choisir les portes que vous souhaitez, à condition de fournir l'instruction ou d'ajouter des portes d'impulsion (voir [Créer des passes de transcompilateur](/docs/guides/custom-transpiler-pass) ) Les portes de base par défaut sont celles pour lesquelles des étalonnages ont été effectués sur le QPU, de sorte qu'aucune autre porte d'instruction/impulsion n'est nécessaire. Par exemple, sur certains QPU, `cx` est la porte à deux qubits par défaut et `ecr` sur d'autres. Consultez la liste des [portes et opérations natives](/docs/guides/qpu-information#native-gates) possibles pour plus de détails.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "313e4743",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/represent-quantum-computers/extracted-outputs/313e4743-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=1,\n",
        "    coupling_map=coupling_map,\n",
        "    basis_gates=basis_gates,\n",
        "    seed_transpiler=12345,\n",
        ")\n",
        "qc_t_cm_bg = pass_manager.run(qc)\n",
        "qc_t_cm_bg.draw(\"mpl\", idle_wires=False, fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b0195ba6",
      "metadata": {},
      "source": [
        "Notez que les `CXGate` objets ont été décomposés en `ecr` portes et en portes de base à un seul qubit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "eb3f5aff-3ca2-4688-a59e-da05c724ef09",
      "metadata": {},
      "source": [
        "<span id=\"device-error-rates\" />\n",
        "\n",
        "## Taux d'erreur des appareils\n",
        "\n",
        "La classe `Target` peut contenir des informations sur les taux d'erreur des opérations effectuées sur l'appareil.\n",
        "Par exemple, le code suivant récupère les propriétés de la porte de résonance croisée échangée (ECR) entre les qubits 1 et 0 (notez que la porte ECR est directionnelle) :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "38aa1eca-a6aa-4db9-af36-66289e2059d2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "InstructionProperties(duration=5.333333333333332e-07, error=0.007494257741828603)"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "target[\"ecr\"][(1, 0)]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "90cca3a8-ca25-4795-a22f-57ba6d8cfcaa",
      "metadata": {},
      "source": [
        "La sortie affiche la durée de la porte (en secondes) et son taux d'erreur. Pour révéler les informations d'erreur au transpondeur, construisez un modèle cible avec les modèles `basis_gates` et `coupling_map` ci-dessus et alimentez-le avec les valeurs d'erreur provenant du backend `FakeSherbrooke`.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "e92c39d7-4aab-4657-aa9a-1b8b5788cb58",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.transpiler import Target\n",
        "from qiskit.circuit.controlflow import IfElseOp, SwitchCaseOp, ForLoopOp\n",
        "\n",
        "err_targ = Target.from_configuration(\n",
        "    basis_gates=basis_gates,\n",
        "    coupling_map=coupling_map,\n",
        "    num_qubits=target.num_qubits,\n",
        "    custom_name_mapping={\n",
        "        \"if_else\": IfElseOp,\n",
        "        \"switch_case\": SwitchCaseOp,\n",
        "        \"for_loop\": ForLoopOp,\n",
        "    },\n",
        ")\n",
        "\n",
        "for i, (op, qargs) in enumerate(target.instructions):\n",
        "    if op.name in basis_gates:\n",
        "        err_targ[op.name][qargs] = target.instruction_properties(i)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "433f2772-b397-42ab-b3a5-a44a85192f3c",
      "metadata": {},
      "source": [
        "Transpile avec notre nouvelle cible `err_targ` comme cible :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "f1e270c4-e2cc-487e-a050-4180bc321b0b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/represent-quantum-computers/extracted-outputs/f1e270c4-e2cc-487e-a050-4180bc321b0b-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "pass_manager = generate_preset_pass_manager(\n",
        "    optimization_level=1, target=err_targ, seed_transpiler=12345\n",
        ")\n",
        "qc_t_cm_bg_et = pass_manager.run(qc)\n",
        "qc_t_cm_bg_et.draw(\"mpl\", idle_wires=False, fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f8b516be-805d-4d0b-92f9-44d3fbe3b51f",
      "metadata": {},
      "source": [
        "Comme la cible contient des informations sur les erreurs, la passe `VF2PostLayout` tente de trouver les qubits optimaux à utiliser, ce qui donne le même circuit que celui qui a été trouvé à l'origine avec les mêmes qubits physiques.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e815a158-c77a-4e82-bebe-1710d0ae4f1f",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Etapes suivantes\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recommandations\">\n",
        "  * Comprendre [les paramètres par défaut et les options de configuration de Transpilation](defaults-and-configuration-options).\n",
        "  * Revoir la rubrique [Paramètres couramment utilisés pour la transpilation](common-parameters).\n",
        "  * Consultez le guide [Comparer les paramètres du transpiler](/docs/guides/circuit-transpilation-settings#compare-transpiler-settings).\n",
        "  * Consultez la [documentation de l'API Transpile](/docs/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": 5
}