{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "3b140909-ace6-4665-a0bf-f3bb9bd094c0",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Simulación exacta con primitivas e Qiskit SDK\"\n",
        "description: \"Cómo realizar una simulación exacta de circuitos cuánticos utilizando primitivas en Qiskit.\"\n",
        "---\n",
        "\n",
        "<span id=\"exact-simulation-with-qiskit-sdk-primitives\" />\n",
        "\n",
        "# Simulación exacta con primitivas e 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=\"Versiones del paquete\">\n",
        "    El código de esta página se ha desarrollado teniendo en cuenta los siguientes requisitos.\n",
        "    Recomendamos utilizar estas versiones o versiones más recientes.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.0\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "867f73c6-dd57-4755-9bbd-55ffffe7e09e",
      "metadata": {},
      "source": [
        "Las primitivas de referencia del paquete « Qiskit SDK » realizan simulaciones de vectores de estado locales. Estas simulaciones no permiten\n",
        "modelar el ruido de los dispositivos, pero resultan útiles para crear rápidamente prototipos de algoritmos antes de recurrir a técnicas de simulación más avanzadas\n",
        "( [utilizando Qiskit Aer](/docs/guides/simulate-stabilizer-circuits) ) o de ejecutarlos en dispositivos reales ( [primitivas de Qiskit Runtime](primitives) ).\n",
        "\n",
        "La primitiva Estimador puede calcular valores de expectativa de circuitos, y la primitiva Muestreador puede muestrear de las distribuciones de salida de los circuitos.\n",
        "\n",
        "Las siguientes secciones muestran cómo utilizar las primitivas de referencia para ejecutar su flujo de trabajo localmente.\n",
        "\n",
        "<span id=\"use-the-reference-estimator\" />\n",
        "\n",
        "## Utilice el estimador de referencia\n",
        "\n",
        "La implementación de referencia de `EstimatorV2` en `qiskit.primitives` que se ejecuta en un vector de estado local local es la [`StatevectorEstimator`](../api/qiskit/qiskit.primitives.StatevectorEstimator) clase Puede tomar circuitos, observables y parámetros como entradas y devuelve los valores de expectativa calculados localmente.\n",
        "\n",
        "El siguiente código prepara los datos de entrada que se utilizarán en los ejemplos que vienen a continuación. El tipo de entrada esperado para los\n",
        "observables es [`qiskit.quantum_info.SparsePauliOp`](../api/qiskit/qiskit.quantum_info.SparsePauliOp). Ten en cuenta que\n",
        "el circuito del ejemplo está parametrizado, pero también puedes ejecutar Estimator en circuitos no parametrizados.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Cualquier circuito pasado a un Estimador **no** debe incluir ninguna **medida**.\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 a circuitos ISA y observables\">\n",
        "  El flujo de trabajo de primitivas de Qiskit Runtime requiere que los circuitos y observables se transformen para que sólo utilicen instrucciones compatibles con la QPU (denominados circuitos y observables *de arquitectura de conjunto de instrucciones (ISA* )). Las primitivas de referencia siguen aceptando instrucciones abstractas, ya que se basan en simulaciones de vectores de estado locales, pero transpilar el circuito podría seguir siendo beneficioso en términos de optimización del circuito.\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",
        "### Inicializar estimador\n",
        "\n",
        "Instanciar a [`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",
        "### Corre y obtén resultados\n",
        "\n",
        "Este ejemplo sólo utiliza un circuito (de tipo [`QuantumCircuit`](../api/qiskit/qiskit.circuit.QuantumCircuit)) y un observable.\n",
        "\n",
        "Ejecute la estimación llamando al método [`StatevectorEstimator.run`](../api/qiskit/qiskit.primitives.StatevectorEstimator#run) que devuelve una instancia de un objeto [`PrimitiveJob`](/docs/api/qiskit/qiskit.primitives.PrimitiveJob) objeto. Puede obtener los resultados del trabajo (como un [`qiskit.primitives.PrimitiveResult`](../api/qiskit/qiskit.primitives.PrimitiveResult) objeto) con el método [`qiskit.primitives.PrimitiveJob.result`](../api/qiskit/qiskit.primitives.PrimitiveJob#result) método.\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",
        "#### Obtenga el valor esperado del resultado\n",
        "\n",
        "El resultado de las primitivas genera una matriz de [`PubResult`](/docs/api/qiskit/qiskit.primitives.PubResult#pubresult) objetos, donde cada elemento de la matriz es un `PubResult` objeto que contiene en sus datos la matriz de evaluaciones correspondiente a cada combinación observable del circuito en el espacio de estados ( PUB ).\n",
        "\n",
        "Para recuperar los valores de las expectativas y los metadatos de la primera (y en este caso, única) evaluación del circuito, debemos acceder a la evaluación [`data`](/docs/api/qiskit/qiskit.primitives.PubResult#data) de 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",
        "### Configurar las opciones de ejecución del estimador\n",
        "\n",
        "Por defecto, el Estimador de referencia realiza un cálculo exacto del vector de estado basado en el [`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) clase.\n",
        "Sin embargo, esto puede modificarse para introducir el efecto de la sobrecarga de muestreo (también conocido como \"ruido de disparo\").\n",
        "\n",
        "Estimator acepta un argumento `precision` que expresa las barras de error que la implementación primitiva debe apuntar para las estimaciones de los valores de expectativa.  Se trata de la sobrecarga de muestreo y se define exclusivamente en el método `.run()` . Esto le permite ajustar la opción hasta el nivel 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": [
        "Para ver un ejemplo completo, consulta la página [de ejemplos de Estimator](/docs/guides/estimator-examples).\n",
        "\n",
        "<span id=\"use-the-reference-sampler\" />\n",
        "\n",
        "## Utilice el muestreador de referencia\n",
        "\n",
        "La implementación de referencia de `SamplerV2` en `qiskit.primitives` es la clase [`StatevectorSampler`](../api/qiskit/qiskit.primitives.StatevectorSampler) clase Toma circuitos y parámetros como entradas y devuelve los resultados del muestreo de las distribuciones de probabilidad de salida como una distribución cuasi-probabilística de los estados de salida.\n",
        "\n",
        "El siguiente código prepara los datos de entrada que se utilizan en los ejemplos que vienen a continuación. Ten en cuenta que\n",
        "estos ejemplos ejecutan un único circuito parametrizado, pero también puedes ejecutar Sampler\n",
        "en circuitos no parametrizados.\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",
        "  Cualquier circuito cuántico pasado a un Muestreador **debe** incluir mediciones.\n",
        "</Admonition>\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Transpile a circuitos ISA y observables\">\n",
        "  El flujo de trabajo de primitivas de Qiskit Runtime requiere que los circuitos se transformen para que sólo utilicen instrucciones soportadas por la QPU (denominados circuitos ISA). Las primitivas de referencia siguen aceptando instrucciones abstractas, ya que se basan en simulaciones de vectores de estado locales, pero transpilar el circuito podría seguir siendo beneficioso en términos de optimización del circuito.\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",
        "### Inicializar `SamplerV2`\n",
        "\n",
        "Instanciar [`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",
        "### Corre y obtén resultados\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": [
        "Las primitivas aceptan múltiples PUBs como entradas, y cada PUB obtiene su propio resultado. Por lo tanto, puede ejecutar diferentes circuitos con varias combinaciones de parámetros/observables y recuperar los resultados de 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",
        "### Obtenga la distribución de probabilidad o el resultado de la medición\n",
        "\n",
        "Las muestras de resultados de medición se devuelven como **cadenas de bits** o **recuentos**. Las cadenas de bits muestran los resultados de las mediciones, conservando el orden de disparo en el que se midieron. Los objetos de resultados del Muestreador organizan los datos en términos de los nombres de registro clásicos de sus circuitos de entrada, por compatibilidad con los circuitos dinámicos.\n",
        "\n",
        "<Admonition>\n",
        "  El nombre del registro clásico es, por defecto, `\"meas\"`. Este nombre se utilizará más adelante para acceder a las cadenas de bits de medición.\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: {'11': 519, '00': 505}\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",
        "### Cambiar opciones de ejecución\n",
        "\n",
        "Por defecto, el Muestreador de referencia realiza un cálculo exacto del vector de estado basado en el [`quantum_info.Statevector`](../api/qiskit/qiskit.quantum_info.Statevector) clase.\n",
        "Sin embargo, esto puede modificarse para introducir el efecto de la sobrecarga de muestreo (también conocido como \"ruido de disparo\"). Para ayudar a gestionar esta sobrecarga, la interfaz Sampler acepta un argumento `shots` que puede definirse en el nivel PUB.\n",
        "\n",
        "Este ejemplo supone que ha definido dos circuitos.\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 0x7fab09442490>"
            ]
          },
          "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": [
        "Para ver un ejemplo completo, consulta la página [de ejemplos de Sampler](/docs/guides/sampler-examples).\n",
        "\n",
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximos pasos\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendaciones\">\n",
        "  * Para una simulación de mayor rendimiento que pueda manejar circuitos más grandes, o para incorporar modelos de ruido a su simulación, consulte [Simulación exacta y ruidosa con primitivas Qiskit Aer](simulate-with-qiskit-aer).\n",
        "  * Para aprender a utilizar Quantum Composer para simulación, consulte la guía [de IBM Quantum Composer](/docs/guides/composer).\n",
        "  * Lea la referencia de [la API de Qiskit Estimator](/docs/api/qiskit/1.4/qiskit.primitives.Estimator).\n",
        "  * Lea la referencia de [la API del muestreador Qiskit](/docs/api/qiskit/1.4/qiskit.primitives.Sampler).\n",
        "  * Lea [Migrar a V2 primitives](/docs/guides/v2-primitives).\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
}