{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "3b140909-ace6-4665-a0bf-f3bb9bd094c0",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Simulazione esatta con primitive dell' Qiskit SDK\"\n",
        "description: \"Come eseguire una simulazione esatta dei circuiti quantistici utilizzando primitive in Qiskit.\"\n",
        "---\n",
        "\n",
        "<span id=\"exact-simulation-with-qiskit-sdk-primitives\" />\n",
        "\n",
        "# Simulazione esatta con primitive dell' Qiskit SDK\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b820ca5f-60cc-41c7-98db-4b41df4534cc",
      "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",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "867f73c6-dd57-4755-9bbd-55ffffe7e09e",
      "metadata": {},
      "source": [
        "Le primitive di riferimento presenti nell' Qiskit SDK o eseguono simulazioni con vettori di stato locali. Queste simulazioni non consentono di\n",
        "modellare il rumore dei dispositivi, ma sono utili per realizzare rapidamente prototipi di algoritmi prima di passare a tecniche di simulazione\n",
        "più avanzate ( [utilizzando Qiskit Aer](/docs/guides/simulate-stabilizer-circuits) ) o di eseguire gli algoritmi su dispositivi reali ( [primitive IBM Quantum](primitives) ).\n",
        "\n",
        "La primitiva Estimator può calcolare i valori di aspettativa dei circuiti, mentre la primitiva Sampler può campionare dalle distribuzioni di uscita dei circuiti.\n",
        "\n",
        "Le sezioni seguenti mostrano come utilizzare le primitive di riferimento per eseguire il flusso di lavoro a livello locale.\n",
        "\n",
        "<span id=\"use-the-reference-estimator\" />\n",
        "\n",
        "## Utilizza lo strumento di stima di riferimento\n",
        "\n",
        "L'implementazione di riferimento di `EstimatorV2` in `qiskit.primitives` che viene eseguita su un simulatore locale di statevector è la classe [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) classe. Può ricevere in ingresso circuiti, osservabili e parametri e restituire i valori di aspettativa calcolati localmente.\n",
        "\n",
        "Il codice seguente prepara i dati di input che verranno utilizzati negli esempi che seguono. Il tipo di input previsto per gli\n",
        "osservabili è [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). Si noti che\n",
        "il circuito dell'esempio è parametrizzato, ma è possibile eseguire Estimator anche su circuiti non parametrizzati.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Qualsiasi circuito passato a un Estimatore **non** deve includere alcuna **misura**.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "5b41a52d-8f15-4ce4-b3f6-effd91946d9c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/simulate-with-qiskit-sdk-primitives/extracted-outputs/5b41a52d-8f15-4ce4-b3f6-effd91946d9c-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "from qiskit.circuit import Parameter\n",
        "\n",
        "# circuit for which you want to obtain the expected value\n",
        "circuit = QuantumCircuit(2)\n",
        "circuit.ry(Parameter(\"theta\"), 0)\n",
        "circuit.h(0)\n",
        "circuit.cx(0, 1)\n",
        "circuit.draw(\"mpl\", style=\"iqp\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "18658518-304a-49a7-8958-82adef366de6",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.quantum_info import SparsePauliOp\n",
        "import numpy as np\n",
        "\n",
        "# observable(s) whose expected values you want to compute\n",
        "\n",
        "observable = SparsePauliOp([\"II\", \"XX\", \"YY\", \"ZZ\"], coeffs=[1, 1, -1, 1])\n",
        "\n",
        "# value(s) for the circuit parameter(s)\n",
        "parameter_values = [[0], [np.pi / 6], [np.pi / 2]]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4c39904c-d586-41b9-ade0-e6a508ef7c2e",
      "metadata": {},
      "source": [
        "<Admonition type=\"tip\" title=\"Transpile ai circuiti e agli osservabili ISA\">\n",
        "  Il flusso di lavoro delle primitive \" IBM Quantum \" richiede che i circuiti e gli osservabili vengano trasformati in modo da utilizzare esclusivamente istruzioni supportate dalla QPU (denominati \"circuiti e osservabili con *architettura del set di istruzioni* \" (ISA)). Le primitive di riferimento continuano ad accettare istruzioni astratte, poiché si basano su simulazioni con vettori di stato locali, ma la transpilazione del circuito potrebbe comunque rivelarsi vantaggiosa in termini di ottimizzazione del circuito stesso.\n",
        "\n",
        "  ```python\n",
        "  # Generate a pass manager without providing a backend\n",
        "  from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "  pm = generate_preset_pass_manager(optimization_level=1)\n",
        "  isa_circuit = pm.run(circuit)\n",
        "  isa_observable = observable.apply_layout(isa_circuit.layout)\n",
        "  ```\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"initialize-estimator\" />\n",
        "\n",
        "### Inizializza stimatore\n",
        "\n",
        "Istanziare un [`qiskit.primitives.StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "56f39026-7874-4f14-8529-b97df373eaf5",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.primitives import StatevectorEstimator\n",
        "\n",
        "estimator = StatevectorEstimator()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9c4c81b1-8b87-450d-9a93-4f209364ee83",
      "metadata": {},
      "source": [
        "<span id=\"run-and-get-results\" />\n",
        "\n",
        "### Corri e ottieni risultati\n",
        "\n",
        "Questo esempio utilizza solo un circuito (di tipo [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)) e un osservabile.\n",
        "\n",
        "Eseguire la stima chiamando il metodo [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) che restituisce un'istanza di un oggetto [`PrimitiveJob`](/docs/api/qiskit/qiskit.primitives.PrimitiveJob) oggetto. È possibile ottenere i risultati del lavoro (come oggetto [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) oggetto) con il metodo [`qiskit.primitives.PrimitiveJob.result`](../api/qiskit/qiskit.primitives.PrimitiveJob#result) metodo.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "0c424291-abb3-420c-80e1-a09ecbd6c035",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            " > Result class: <class 'qiskit.primitives.containers.primitive_result.PrimitiveResult'>\n"
          ]
        }
      ],
      "source": [
        "job = estimator.run([(circuit, observable, parameter_values)])\n",
        "result = job.result()\n",
        "print(f\" > Result class: {type(result)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "871ce7d6-402c-417f-8a83-805d92fa0298",
      "metadata": {},
      "source": [
        "<span id=\"get-the-expected-value-from-the-result\" />\n",
        "\n",
        "#### Ottieni il valore atteso dal risultato\n",
        "\n",
        "Il risultato delle primitive restituisce un array di [`PubResult`](/docs/api/qiskit/qiskit.primitives.PubResult#pubresult) oggetti, dove ogni elemento dell'array è un `PubResult` oggetto che contiene nei propri dati l'array delle valutazioni corrispondenti a ogni combinazione osservabile del circuito nell' PUB e.\n",
        "\n",
        "Per recuperare i valori di aspettativa e i metadati per la prima (e in questo caso unica) valutazione del circuito, dobbiamo accedere alla valutazione [`data`](/docs/api/qiskit/qiskit.primitives.PubResult#data) per PUB 0:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "145b3f62-dfaf-4288-8764-f2ecb90e38a1",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            " > Expectation value: [4.         3.73205081 2.        ]\n",
            " > Metadata: {'target_precision': 0.0, 'circuit_metadata': {}}\n"
          ]
        }
      ],
      "source": [
        "print(f\" > Expectation value: {result[0].data.evs}\")\n",
        "print(f\" > Metadata: {result[0].metadata}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e29ec8cc-2c38-464a-a8b3-8f05b282c807",
      "metadata": {},
      "source": [
        "<span id=\"set-estimator-run-options\" />\n",
        "\n",
        "### Imposta le opzioni di esecuzione di Estimator\n",
        "\n",
        "Per impostazione predefinita, l'Estimatore di riferimento esegue un calcolo esatto del vettore di stato in base al valore di [`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) classe.\n",
        "Tuttavia, questo può essere modificato per introdurre l'effetto dell'overhead di campionamento (noto anche come \"shot noise\").\n",
        "\n",
        "Estimator accetta un argomento `precision` che esprime le barre di errore che l'implementazione per le stime dei valori di aspettativa.  Si tratta dell'overhead di campionamento ed è definito esclusivamente nel metodo `.run()` . In questo modo è possibile regolare con precisione l'opzione fino al livello PUB.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "04047e7a-23f4-431b-8e3a-11edf035e8fc",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Estimate expectation values for two PUBs, both with 0.05 precision.\n",
        "precise_job = estimator.run(\n",
        "    [(circuit, observable, parameter_values)], precision=0.05\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d54f110f-004a-4337-8b4d-7d4287f22be9",
      "metadata": {},
      "source": [
        "Per un esempio completo, consulta la pagina [degli esempi di Estimator](/docs/guides/estimator-examples).\n",
        "\n",
        "<span id=\"use-the-reference-sampler\" />\n",
        "\n",
        "## Utilizza il campionatore di riferimento\n",
        "\n",
        "L'implementazione di riferimento di `SamplerV2` in `qiskit.primitives` è la classe [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) classe. Prende in ingresso circuiti e parametri e restituisce i risultati del campionamento dalle distribuzioni di probabilità di uscita come una distribuzione di quasi-probabilità degli stati di uscita.\n",
        "\n",
        "Il codice seguente prepara gli input utilizzati negli esempi che seguono. Si noti che\n",
        "questi esempi eseguono un singolo circuito parametrizzato, ma è possibile eseguire Sampler\n",
        "anche su circuiti non parametrizzati.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "d4c0ac3b-8e5b-4cde-bb26-256324982c2c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/simulate-with-qiskit-sdk-primitives/extracted-outputs/d4c0ac3b-8e5b-4cde-bb26-256324982c2c-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "\n",
        "circuit = QuantumCircuit(2)\n",
        "circuit.h(0)\n",
        "circuit.cx(0, 1)\n",
        "circuit.measure_all()\n",
        "circuit.draw(\"mpl\", style=\"iqp\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b34ae490-9efb-45f5-937d-3ce86afa445f",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\">\n",
        "  Qualsiasi circuito quantistico passato a un campionatore **deve** includere misure.\n",
        "</Admonition>\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Transpile ai circuiti e agli osservabili ISA\">\n",
        "  Il flusso di lavoro delle primitive \" IBM Quantum \" richiede che i circuiti vengano trasformati in modo da utilizzare esclusivamente istruzioni supportate dalla QPU (denominati \"circuiti ISA\"). Le primitive di riferimento continuano ad accettare istruzioni astratte, poiché si basano su simulazioni con vettori di stato locali, ma la transpilazione del circuito potrebbe comunque rivelarsi vantaggiosa in termini di ottimizzazione del circuito stesso.\n",
        "\n",
        "  ```python\n",
        "  # Generate a pass manager without providing a backend\n",
        "  from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "  pm = generate_preset_pass_manager(optimization_level=1)\n",
        "  isa_circuit = pm.run(qc)\n",
        "  ```\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"initialize-samplerv2\" />\n",
        "\n",
        "### Inizializza `SamplerV2`\n",
        "\n",
        "Istanziare [`qiskit.primitives.StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler):\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "626177e7-f06a-4216-89c8-daf703520457",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit.primitives import StatevectorSampler\n",
        "\n",
        "sampler = StatevectorSampler()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "626fb8d6-75ae-47b2-ac0b-00acc4ce5afe",
      "metadata": {},
      "source": [
        "<span id=\"run-and-get-results\" />\n",
        "\n",
        "### Corri e ottieni risultati\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "19659756-a01d-42ec-8fa7-d7a1bf2303d5",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            " > Result class: <class 'qiskit.primitives.containers.sampler_pub_result.SamplerPubResult'>\n"
          ]
        }
      ],
      "source": [
        "# execute 1 circuit with Sampler\n",
        "job = sampler.run([circuit])\n",
        "pub_result = job.result()[0]\n",
        "print(f\" > Result class: {type(pub_result)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ee6d88f3-0115-4ea9-a2c5-633906841d9f",
      "metadata": {},
      "source": [
        "Le primitive accettano più PUB come input e ogni PUB ottiene il proprio risultato. Pertanto, è possibile eseguire diversi circuiti con varie combinazioni di parametri/osservabili e recuperare i risultati PUB :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "fb91dbfc-0340-4ea6-8d33-95357d7907e3",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            " > Result class: <class 'qiskit.primitives.containers.sampler_pub_result.SamplerPubResult'>\n"
          ]
        }
      ],
      "source": [
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "# create two circuits\n",
        "circuit1 = circuit.copy()\n",
        "circuit2 = circuit.copy()\n",
        "\n",
        "# transpile circuits\n",
        "pm = generate_preset_pass_manager(optimization_level=1)\n",
        "isa_circuit1 = pm.run(circuit1)\n",
        "isa_circuit2 = pm.run(circuit2)\n",
        "# execute 2 circuits using Sampler\n",
        "job = sampler.run([(isa_circuit1), (isa_circuit2)])\n",
        "pub_result_1 = job.result()[0]\n",
        "pub_result_2 = job.result()[1]\n",
        "print(f\" > Result class: {type(pub_result)}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6e7b2199-3c00-477a-a248-824b442431b5",
      "metadata": {},
      "source": [
        "<span id=\"get-the-probability-distribution-or-measurement-outcome\" />\n",
        "\n",
        "### Ottieni la distribuzione di probabilità o il risultato della misurazione\n",
        "\n",
        "I campioni dei risultati della misurazione vengono restituiti come **bitstring** o **conteggi**. Le stringhe di bit mostrano i risultati della misurazione, conservando l'ordine di scatto in cui sono stati misurati. Gli oggetti risultato del campionatore organizzano i dati in termini di nomi dei registri classici dei circuiti di ingresso, per compatibilità con i circuiti dinamici.\n",
        "\n",
        "<Admonition>\n",
        "  Il nome del registro classico è predefinito a `\"meas\"`. Questo nome verrà utilizzato in seguito per accedere alle stringhe di bit delle misure.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "1dc395b4-5716-44be-9622-7c99df95616b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "        ┌───┐      ░ ┌─┐   \n",
              "   q_0: ┤ H ├──■───░─┤M├───\n",
              "        └───┘┌─┴─┐ ░ └╥┘┌─┐\n",
              "   q_1: ─────┤ X ├─░──╫─┤M├\n",
              "             └───┘ ░  ║ └╥┘\n",
              "meas: 2/══════════════╩══╩═\n",
              "                      0  1 "
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Define quantum circuit with 2 qubits\n",
        "circuit = QuantumCircuit(2)\n",
        "circuit.h(0)\n",
        "circuit.cx(0, 1)\n",
        "circuit.measure_all()\n",
        "circuit.draw()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "27a2847b-6553-4c73-9b8a-85ba28725ed8",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "The number of bitstrings is: 1024\n",
            "The counts are: {'00': 538, '11': 486}\n"
          ]
        }
      ],
      "source": [
        "# Transpile circuit\n",
        "pm = generate_preset_pass_manager(optimization_level=1)\n",
        "isa_circuit = pm.run(circuit)\n",
        "# Run using Sampler\n",
        "result = sampler.run([circuit]).result()\n",
        "# Access result data for PUB 0\n",
        "data_pub = result[0].data\n",
        "# Access bitstring for the classical register \"meas\"\n",
        "bitstrings = data_pub.meas.get_bitstrings()\n",
        "print(f\"The number of bitstrings is: {len(bitstrings)}\")\n",
        "# Get counts for the classical register \"meas\"\n",
        "counts = data_pub.meas.get_counts()\n",
        "print(f\"The counts are: {counts}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "de705fab-e718-4924-a03f-f19bdf6578d8",
      "metadata": {},
      "source": [
        "<span id=\"change-run-options\" />\n",
        "\n",
        "### Modifica opzioni di esecuzione\n",
        "\n",
        "Per impostazione predefinita, il campionatore di riferimento esegue un calcolo esatto del vettore di stato in base al valore di [`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) classe.\n",
        "Tuttavia, questo può essere modificato per introdurre l'effetto dell'overhead di campionamento (noto anche come \"shot noise\"). Per gestire questo overhead, l'interfaccia Sampler accetta un argomento `shots` che può essere definito al livello PUB.\n",
        "\n",
        "Questo esempio presuppone che siano stati definiti due circuiti.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "927faaab-60c0-4b73-bf53-72f7c4c9ad65",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<qiskit.primitives.primitive_job.PrimitiveJob at 0x7f94d59db010>"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Sample two circuits at 128 shots each.\n",
        "sampler.run([isa_circuit1, isa_circuit2], shots=128)\n",
        "# Sample two circuits at different amounts of shots. The \"None\"s are necessary\n",
        "# as placeholders\n",
        "# for the lack of parameter values in this example.\n",
        "sampler.run([(isa_circuit1, None, 123), (isa_circuit2, None, 456)])"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1c0e76fe-4b5d-4fd4-9eec-da5332d76cfb",
      "metadata": {},
      "source": [
        "Per un esempio completo, consulta la pagina [degli esempi di Sampler](/docs/guides/sampler-examples).\n",
        "\n",
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Suggerimenti\">\n",
        "  * Per una simulazione più performante, in grado di gestire circuiti più grandi, o per incorporare modelli di rumore nella simulazione, vedere [Simulazione esatta e rumorosa con le primitive Aer di Qiskit](simulate-with-qiskit-aer).\n",
        "  * Per imparare a usare Quantum Composer per la simulazione, consultare la guida [IBM Quantum Composer](/docs/guides/composer).\n",
        "  * Leggete il riferimento all' [API di Qiskit Estimator](/docs/api/qiskit/1.4/qiskit.primitives.Estimator).\n",
        "  * Leggete il riferimento all' [API di Qiskit Sampler](/docs/api/qiskit/1.4/qiskit.primitives.Sampler).\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": 4
}