{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "5b6cbc5d-14d4-40c6-a702-0ce635c483d8",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Rappresentare i computer quantistici per il transpiler\"\n",
        "description: \"Scopri le mappe di accoppiamento, i gate di base e gli errori del processore per la transpilazione\"\n",
        "---\n",
        "\n",
        "<span id=\"represent-quantum-computers-for-the-transpiler\" />\n",
        "\n",
        "# Rappresentare i computer quantistici per il transpiler\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=\"Versioni del pacchetto\">\n",
        "    Il codice di questa pagina è stato sviluppato in base ai seguenti requisiti.\n",
        "    Si consiglia di utilizzare queste versioni o versioni più recenti.\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": [
        "Per convertire un circuito astratto in un circuito ISA in grado di funzionare su una specifica QPU (unità di elaborazione quantistica), il transpiler ha bisogno di alcune informazioni sulla QPU. Queste informazioni si trovano in due luoghi: l'oggetto `BackendV2` (o legacy `BackendV1`) a cui si intende inviare i lavori e l'attributo `Target` del backend.\n",
        "\n",
        "* Il [`Target`](/docs/api/qiskit/qiskit.transpiler.Target) contiene tutti i vincoli rilevanti di un dispositivo, come il set di istruzioni supportato, la connettività dei qubit e le informazioni relative agli impulsi o alla temporizzazione.\n",
        "* Il [`Backend`](/docs/api/qiskit/qiskit.providers.BackendV2) possiede un `Target` di default, contiene informazioni aggiuntive -- come il [`InstructionScheduleMap`](/docs/api/qiskit/1.4/qiskit.pulse.InstructionScheduleMap), e fornisce l'interfaccia per l'invio di lavori di circuiti quantistici.\n",
        "\n",
        "Si possono anche fornire esplicitamente informazioni da utilizzare per il transpiler, ad esempio se si ha un caso d'uso specifico o se si ritiene che queste informazioni aiutino il transpiler a generare un circuito più ottimizzato.\n",
        "\n",
        "La precisione con cui il transpiler produce il circuito più appropriato per un hardware specifico dipende dalla quantità di informazioni che `Target` o `Backend` ha sui suoi vincoli.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Poiché molti degli algoritmi di transpilazione sottostanti sono stocastici, non c'è alcuna garanzia che venga trovato un circuito migliore.\n",
        "</Admonition>\n",
        "\n",
        "Questa pagina mostra diversi esempi di come trasmettere le informazioni relative alla QPU al transpiler.\n",
        "\n",
        "<span id=\"default-config\" />\n",
        "\n",
        "<span id=\"default-configuration\" />\n",
        "\n",
        "## Configurazione predefinita\n",
        "\n",
        "L'uso più semplice del transpiler è quello di fornire tutte le informazioni sulla QPU fornendo il sito `Backend` o `Target`. Per capire meglio come funziona il transpiler, costruite un circuito e transpilatelo con informazioni diverse, come segue.\n",
        "\n",
        "Importare le librerie necessarie e istanziare la QPU: Per convertire un circuito astratto in un circuito ISA in grado di funzionare su un processore specifico, il transpiler ha bisogno di alcune informazioni sul processore.  In genere, queste informazioni sono memorizzate nel file [`Backend`](/docs/api/qiskit/qiskit.providers.Backend#backend) o [`Target`](/docs/api/qiskit/qiskit.transpiler.Target#target) fornito al transpiler e non sono necessarie altre informazioni. Tuttavia, si possono anche fornire esplicitamente informazioni da utilizzare per il transpiler, ad esempio se si ha un caso d'uso specifico o se si ritiene che queste informazioni aiutino il transpiler a generare un circuito più ottimizzato.\n",
        "\n",
        "In questa sezione vengono illustrati diversi esempi di come trasmettere informazioni al transpiler.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Questi esempi utilizzano il target del backend `qiskit_ibm_runtime`[`FakeSherbrooke`](/docs/api/qiskit-ibm-runtime/fake-provider-fake-sherbrooke#fakesherbrooke) simulato.  Tuttavia, puoi provarlo su qualsiasi backend reale o simulato compatibile con Qiskit.  I tuoi risultati potrebbero essere diversi.\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": [
        "Il circuito di esempio utilizza un'istanza di [`efficient_su2`](/docs/api/qiskit/qiskit.circuit.library.efficient_su2) della libreria di circuiti di 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": [
        "Questo esempio utilizza le impostazioni predefinite per effettuare il transpile su `backend`'s `target`, che fornisce tutte le informazioni necessarie per convertire il circuito in uno che funzionerà sul 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": [
        "Questo esempio viene utilizzato nelle sezioni successive di questo argomento per illustrare che la mappa di accoppiamento e il set di istruzioni supportato sono le informazioni essenziali da trasmettere al transpiler per una costruzione ottimale del circuito. La QPU può solitamente selezionare impostazioni predefinite per altre informazioni che non vengono trasmesse, come la temporizzazione e la programmazione.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "956f1b7a-80b4-4cda-9ecf-6057f560deb9",
      "metadata": {},
      "source": [
        "<span id=\"coupling-map\" />\n",
        "\n",
        "## Mappa di accoppiamento\n",
        "\n",
        "La mappa di accoppiamento è un grafico che mostra quali qubit sono connessi e quindi hanno porte a due qubit tra loro. A volte questo grafico è direzionale, il che significa che le porte a due qubit possono andare solo in una direzione. Tuttavia, il transpiler può sempre invertire la direzione di un gate aggiungendo ulteriori gate a singolo qubit. Un circuito quantistico astratto può sempre essere rappresentato su questo grafo, anche se la sua connettività è limitata, introducendo porte SWAP per spostare le informazioni quantistiche.\n",
        "\n",
        "I qubit dei nostri circuiti astratti sono chiamati *qubit virtuali* e quelli della mappa di accoppiamento sono *qubit fisici*. Il transpiler fornisce una mappatura tra qubit virtuali e fisici. Una delle prime fasi della transpilazione, la fase di *layout*, esegue questa mappatura.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Sebbene lo stadio di instradamento sia interconnesso con lo stadio di *layout*, che seleziona i qubit effettivi, per impostazione predefinita, questo argomento li tratta come stadi separati per semplicità. La combinazione di routing e layout è chiamata *mappatura dei qubit*.  Per ulteriori informazioni su questi stadi, consultare l'argomento [Stadi del transpiler](transpiler-stages).\n",
        "</Admonition>\n",
        "\n",
        "Passare l'argomento della parola chiave `coupling_map` per vedere il suo effetto sul transpiler:\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": [
        "Come mostrato sopra, sono state inserite diverse porte SWAP (ciascuna composta da tre porte CX), che causano molti errori sui dispositivi attuali. Per vedere quali qubit sono selezionati sulla topologia di qubit effettiva, utilizzare `plot_circuit_layout` di 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": [
        "Questo dimostra che i nostri qubit virtuali 0-11 sono stati mappati banalmente sulla linea dei qubit fisici 0-11. Torniamo al valore predefinito (`optimization_level=1`), che utilizza `VF2Layout` se è necessario un instradamento.\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": [
        "Ora non sono state inserite porte SWAP e i qubit fisici selezionati sono gli stessi quando si utilizza 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": [
        "Ora il layout si trova in un anello.  Poiché questo layout rispetta la connettività del circuito, non ci sono porte SWAP e il circuito risulta migliore per l'esecuzione.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f62e0541",
      "metadata": {},
      "source": [
        "<span id=\"supported-instructions\" />\n",
        "\n",
        "## Istruzioni supportate\n",
        "\n",
        "Ogni computer quantistico supporta un set di istruzioni limitato.  Ogni porta del circuito deve essere tradotta negli elementi di questo insieme. Questo insieme dovrebbe essere composto da porte a uno e due qubit che forniscono un insieme di porte universali, il che significa che qualsiasi operazione quantistica può essere scomposta in tali porte.  Questo viene fatto da [BasisTranslator](/docs/api/qiskit/qiskit.transpiler.passes.BasisTranslator) e `basis_gates` può essere specificato come argomento chiave al transpiler per fornire queste informazioni.\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": [
        "I gate predefiniti a un qubit su `FakeSherbrooke` sono `rz`, `x`, e `sx`, mentre il gate predefinito a due qubit è `ecr` (risonanza incrociata con eco). I gate CX sono costituiti da `ecr` gate, quindi su alcune QPU `ecr` è specificato come gate di base a due qubit, mentre su altre `cx` è l'impostazione predefinita. Il `ecr` gate è la parte *che crea l'entanglement* del `cx` gate. Oltre alle porte di controllo, esistono anche le istruzioni `delay``measurement` e.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Le QPU hanno porte di base predefinite, ma è possibile scegliere qualsiasi porta desiderata, purché si fornisca l'istruzione o si aggiungano porte a impulsi (vedere [Creare passaggi del transpiler](/docs/guides/custom-transpiler-pass) ) I gate di base predefiniti sono quelli per cui sono state eseguite le calibrazioni sulla QPU, quindi non è necessario fornire ulteriori gate di istruzioni/impulsi. Ad esempio, su alcune QPU `cx` è il gate a due qubit predefinito e `ecr` su altre. Per ulteriori dettagli, consultare l'elenco dei possibili [gate e operazioni nativi](/docs/guides/qpu-information#native-gates).\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": [
        "Si noti che gli `CXGate` oggetti sono stati scomposti in `ecr` porte e porte di base a singolo qubit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "eb3f5aff-3ca2-4688-a59e-da05c724ef09",
      "metadata": {},
      "source": [
        "<span id=\"device-error-rates\" />\n",
        "\n",
        "## Tassi di errore dei dispositivi\n",
        "\n",
        "La classe `Target` può contenere informazioni sui tassi di errore delle operazioni sul dispositivo.\n",
        "Ad esempio, il codice seguente recupera le proprietà del gate ECR (echoed cross-resonance) tra i qubit 1 e 0 (si noti che il gate ECR è direzionale):\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": [
        "L'uscita visualizza la durata del gate (in secondi) e il suo tasso di errore. Per rivelare le informazioni sugli errori al transpiler, costruire un modello di destinazione con i modelli `basis_gates` e `coupling_map` di cui sopra e popolarlo con i valori degli errori dal 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 con il nostro nuovo obiettivo `err_targ` come bersaglio:\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": [
        "Poiché il target include informazioni sull'errore, il passaggio `VF2PostLayout` cerca di trovare i qubit ottimali da utilizzare, ottenendo lo stesso circuito trovato originariamente con gli stessi qubit fisici.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e815a158-c77a-4e82-bebe-1710d0ae4f1f",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Suggerimenti\">\n",
        "  * Comprendere [le impostazioni predefinite e le opzioni di configurazione di Transpilation](defaults-and-configuration-options).\n",
        "  * Rivedere l'argomento [Parametri comunemente utilizzati per la transpilazione](common-parameters).\n",
        "  * Prova la guida [Confronta le impostazioni del transpiler](/docs/guides/circuit-transpilation-settings#compare-transpiler-settings).\n",
        "  * Consulta [la documentazione dell'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
}