{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "008d2ceb-f6fa-42f6-a7df-6bd604775278",
      "metadata": {},
      "source": [
        "---\n",
        "title: Get started with primitives\n",
        "description: How to use the Estimator and Sampler primitives in Qiskit Runtime.\n",
        "---\n",
        "\n",
        "# Get started with primitives\n",
        "\n",
        "<Admonition type=\"note\" title=\"New execution model, now in beta release\">\n",
        "  The beta release of a new execution model is now available. The directed execution model provides more flexibility when customizing your error mitigation workflow. See the [Directed execution model](/docs/guides/directed-execution-model) guide for more information.\n",
        "</Admonition>\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  While this documentation uses the primitives from Qiskit Runtime, which allow you to use IBM® backends, the primitives can be run on any provider by using the [backend primitives](#backend) instead.  Additionally, you can use the *reference* primitives to run on a local statevector simulator.  See [Exact simulation with Qiskit primitives](/docs/guides/simulate-with-qiskit-sdk-primitives) for details.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b7e96291-0925-4d7f-81a8-a7738549477c",
      "metadata": {},
      "source": [
        "The steps in this topic describe how to set up primitives, explore the options you can use to configure them, and invoke them in a program.\n",
        "\n",
        "<Admonition type=\"note\" title=\"Using Fractional Gates\">\n",
        "  To use the newly supported [fractional gates](./fractional-gates), set `use_fractional_gates=True` when requesting a backend from a `QiskitRuntimeService` instance. For example:\n",
        "\n",
        "  ```python\n",
        "  service = QiskitRuntimeService()\n",
        "  fractional_gate_backend = service.least_busy(use_fractional_gates=True)\n",
        "  ```\n",
        "\n",
        "  Note that this is an experimental feature and might change in the future.\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "818a2b3d-3950-4a28-8e37-39959c56484b",
      "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=\"Package versions\">\n",
        "    The code on this page was developed using the following requirements.\n",
        "    We recommend using these versions or newer.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.3.0\n",
        "    qiskit-ibm-runtime~=0.43.1\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bafa61f0-c049-4ee6-ac76-a0ed97e67caf",
      "metadata": {},
      "source": [
        "<span id=\"start-estimator\" />\n",
        "\n",
        "## Get started with Estimator\n",
        "\n",
        "{/*Verified the v2 examples 2/29/24 - updated 10/29/24*/}\n",
        "\n",
        "### 1. Initialize the account\n",
        "\n",
        "Because Qiskit Runtime Estimator is a managed service, you first need to initialize your account. You can then select the QPU you want to use to calculate the expectation value.\n",
        "\n",
        "Follow the steps in the [Install and set up topic](install-qiskit) if you don't already have an account.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "71d62ba2-b1ba-405a-b304-5bdd7ec5e11b",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "ibm_torino\n"
          ]
        }
      ],
      "source": [
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(\n",
        "    operational=True, simulator=False, min_num_qubits=127\n",
        ")\n",
        "\n",
        "print(backend.name)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d894fbe3-3ea8-4db0-908e-95790b560ddb",
      "metadata": {},
      "source": [
        "### 2. Create a circuit and an observable\n",
        "\n",
        "You need at least one circuit and one observable as inputs to the Estimator primitive.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "c0ad8982-d19b-46d4-8a2d-dd30357c0e52",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> Observable: ['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...',\n",
            " 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII...', ...]\n"
          ]
        }
      ],
      "source": [
        "from qiskit.circuit.library import qaoa_ansatz\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "\n",
        "entanglement = [tuple(edge) for edge in backend.coupling_map.get_edges()]\n",
        "observable = SparsePauliOp.from_sparse_list(\n",
        "    [(\"ZZ\", [i, j], 0.5) for i, j in entanglement],\n",
        "    num_qubits=backend.num_qubits,\n",
        ")\n",
        "circuit = qaoa_ansatz(observable, reps=2)\n",
        "# the circuit is parametrized, so we will define the parameter values for execution\n",
        "param_values = [0.1, 0.2, 0.3, 0.4]\n",
        "\n",
        "print(f\">>> Observable: {observable.paulis}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "84b42c6f-d80e-4cff-8e34-03affa566a97",
      "metadata": {},
      "source": [
        "The circuit and observable need to be transformed to only use instructions supported by the QPU (referred to as *instruction set architecture (ISA)* circuits). We'll use the transpiler to do this.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "abefc665-24a7-466e-a9ec-67cac6a50ebd",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> Circuit ops (ISA): OrderedDict([('rz', 3826), ('sx', 1601), ('cz', 968)])\n"
          ]
        }
      ],
      "source": [
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "pm = generate_preset_pass_manager(optimization_level=1, backend=backend)\n",
        "isa_circuit = pm.run(circuit)\n",
        "isa_observable = observable.apply_layout(isa_circuit.layout)\n",
        "print(f\">>> Circuit ops (ISA): {isa_circuit.count_ops()}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b53e9ab3-7d87-4dd5-b362-138b24cfa73b",
      "metadata": {},
      "source": [
        "### 3. Initialize Qiskit Runtime Estimator\n",
        "\n",
        "When you initialize the Estimator, use the `mode` parameter to specify the mode you want it to run in.  Possible values are `batch`, `session`, or `backend` objects for batch, session, and job execution mode, respectively. For more information, see [Introduction to Qiskit Runtime execution modes.](execution-modes)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "961508db-e534-4fc9-970d-7babcd6c39ef",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
        "\n",
        "estimator = Estimator(mode=backend)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "59b13a43-0c9f-4fdb-a379-af5115c153e1",
      "metadata": {},
      "source": [
        "### 4. Invoke the Estimator and get results\n",
        "\n",
        "Next, invoke the `run()` method to calculate expectation values for the input circuits and observables. The circuit, observable, and optional parameter value sets are input as *primitive unified bloc* (PUB) tuples.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "f1a60bad-cf09-4136-aa1a-4482759b3aea",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> Job ID: d6hugge48nic73aniclg\n"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> Job Status: QUEUED\n"
          ]
        }
      ],
      "source": [
        "job = estimator.run([(isa_circuit, isa_observable, param_values)])\n",
        "print(f\">>> Job ID: {job.job_id()}\")\n",
        "print(f\">>> Job Status: {job.status()}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "c817cce5-4686-43d2-89a1-ed0842d8ace3",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(), dtype=float64>), stds=np.ndarray(<shape=(), dtype=float64>), ensemble_standard_error=np.ndarray(<shape=(), dtype=float64>)), metadata={'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32})], metadata={'dynamical_decoupling': {'enable': False, 'sequence_type': 'XX', 'extra_slack_distribution': 'middle', 'scheduling_method': 'alap'}, 'twirling': {'enable_gates': False, 'enable_measure': True, 'num_randomizations': 'auto', 'shots_per_randomization': 'auto', 'interleave_randomizations': True, 'strategy': 'active-accum'}, 'resilience': {'measure_mitigation': True, 'zne_mitigation': False, 'pec_mitigation': False}, 'version': 2})\n",
            "  > Expectation value: 22.039256727626857\n",
            "  > Metadata: {'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}\n"
          ]
        }
      ],
      "source": [
        "result = job.result()\n",
        "print(f\">>> {result}\")\n",
        "print(f\"  > Expectation value: {result[0].data.evs}\")\n",
        "print(f\"  > Metadata: {result[0].metadata}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "64e2e09f-8528-4088-897b-1529b451ab1e",
      "metadata": {},
      "source": [
        "<span id=\"start-sampler\" />\n",
        "\n",
        "## Get started with Sampler\n",
        "\n",
        "### 1. Initialize the account\n",
        "\n",
        "Because Qiskit Runtime Sampler is a managed service, you first need to initialize your account. You can then select the QPU you want to use to calculate the expectation value.\n",
        "\n",
        "Follow the steps in the [Install and set up topic](install-qiskit) if you don't already have an account set up.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "b40504d7-aee5-4b30-98b1-265e70bece8d",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(\n",
        "    operational=True, simulator=False, min_num_qubits=127\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "73374fbc-d3b6-4d2d-84c6-edf85b43ea25",
      "metadata": {},
      "source": [
        "### 2. Create a circuit\n",
        "\n",
        "You need at least one circuit as the input to the Sampler primitive.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "dfe23a34-2ea9-48af-bd1d-c7e3185aa80c",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "from qiskit.circuit.library import efficient_su2\n",
        "\n",
        "circuit = efficient_su2(127, entanglement=\"linear\")\n",
        "circuit.measure_all()\n",
        "# The circuit is parametrized, so we will define the parameter values for execution\n",
        "param_values = np.random.rand(circuit.num_parameters)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6cf08ef6-34d3-42e6-8cb3-391b60217289",
      "metadata": {},
      "source": [
        "Use the transpiler to get an ISA circuit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "062bd89b-b13e-46d0-96b6-6c84b2131415",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> Circuit ops (ISA): OrderedDict([('rz', 3036), ('sx', 2994), ('cz', 1038), ('measure', 127), ('barrier', 1)])\n"
          ]
        }
      ],
      "source": [
        "from qiskit.transpiler import generate_preset_pass_manager\n",
        "\n",
        "pm = generate_preset_pass_manager(optimization_level=1, backend=backend)\n",
        "isa_circuit = pm.run(circuit)\n",
        "print(f\">>> Circuit ops (ISA): {isa_circuit.count_ops()}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cf0f2c0a-8574-45c6-a43b-1a99eac81279",
      "metadata": {},
      "source": [
        "### 3. Initialize the Qiskit Runtime Sampler\n",
        "\n",
        "When you initialize the Sampler, use the `mode` parameter to specify the mode you want it to run in.  Possible values are `batch`, `session`, or `backend` objects for batch, session, and job execution mode, respectively. For more information, see [Introduction to Qiskit Runtime execution modes.](execution-modes) Note that Open Plan users cannot submit session jobs.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "a2b80dca-dff8-49f9-8154-e2cb0b768507",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import SamplerV2 as Sampler\n",
        "\n",
        "sampler = Sampler(mode=backend)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f35972bf-17d3-40be-852b-9e56615c7c3c",
      "metadata": {},
      "source": [
        "### 4. Invoke the Sampler and get results\n",
        "\n",
        "Next, invoke the `run()` method to generate the output. The circuit and optional parameter value sets are input as *primitive unified bloc* (PUB) tuples.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "e52e6a96-dc23-4f76-8152-b54514a99dfb",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> Job ID: d6hugtm48nic73anid8g\n",
            ">>> Job Status: QUEUED\n"
          ]
        }
      ],
      "source": [
        "job = sampler.run([(isa_circuit, param_values)])\n",
        "print(f\">>> Job ID: {job.job_id()}\")\n",
        "print(f\">>> Job Status: {job.status()}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "4543fac5-abdc-4440-a1a2-d32aabe135d6",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "First ten results for the 'meas' output register: ['1100110000111011100010110000000100000110101000001001000011001100010001111000100100010100011001010110010100000110011000011010100', '0000010100111010010001010010011010100000100100001000001101000011001000101100001000100110000010110100000011000000011001101000000', '1111101100111110000010010010110011100110100011100110101000100100000000110100011001011011000101010000001010001010110010010100100', '1110011001011001110001010100110001010000011001000100110101111000010001111110001000001100000000011101000001010000001000000111000', '0010110011101100011000100000000000100100100101000011000100110000010011100100000000011110010001110100000010101001001100100001101', '0011010001000100011101111010000110100001100010100011000011000010000100100101000010001010100000001001001001101110010000100000100', '1001100111110101101101000000001010010011000111110010000011110000000101110010000001010000001011001100001000001000000010110011000', '0000101010111010011110000000011110100000110000100110000011011100001011110000100000010000110000111000001100110011010100011011000', '0001010000101111111101010000000100010101010101010110100101110100010100110000000011111010000000000100100011010010000111011010100', '0100010101111000011111110100111000010100000001000100110010100110101100110000101110011001010111010101001110010100011010101000000']\n"
          ]
        }
      ],
      "source": [
        "result = job.result()\n",
        "\n",
        "# Get results for the first (and only) PUB\n",
        "pub_result = result[0]\n",
        "print(\n",
        "    f\"First ten results for the 'meas' output register: {pub_result.data.meas.get_bitstrings()[:10]}\"\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ec04840d-5fa1-4716-b585-48aa371f67d4",
      "metadata": {},
      "source": [
        "<span id=\"backend\" />\n",
        "\n",
        "## Get started with the backend primitives\n",
        "\n",
        "Unlike provider-specific primitives, backend primitives are generic implementations that can be used with an arbitrary\n",
        "`backend` object, as long as it implements the [`Backend`](/docs/api/qiskit/qiskit.providers.Backend) interface.\n",
        "\n",
        "* The Sampler primitive can be run with any provider by using [`qiskit.primitives.BackendSamplerV2`](/docs/api/qiskit/qiskit.primitives.BackendSamplerV2).\n",
        "* The Estimator primitive can be run with any provider by using [`qiskit.primitives.BackendEstimatorV2`](../api/qiskit/qiskit.primitives.BackendEstimatorV2).\n",
        "\n",
        "Some providers implement primitives natively.  See the [Qiskit Ecosystem page](https://qiskit.github.io/ecosystem#provider) for details.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9d78f323-1c58-4360-8880-59179c8a14b7",
      "metadata": {},
      "source": [
        "### Example: BackendEstimator\n",
        "\n",
        "```python\n",
        "from qiskit.primitives import BackendEstimatorV2\n",
        "from <some_qiskit_provider> import QiskitProvider\n",
        "\n",
        "provider = QiskitProvider()\n",
        "backend = provider.get_backend('backend_name')\n",
        "estimator = BackendEstimatorV2(backend)\n",
        "```\n",
        "\n",
        "### Example: BackendSampler\n",
        "\n",
        "```python\n",
        "from qiskit.primitives import BackendSamplerV2\n",
        "from <some_qiskit_provider> import QiskitProvider\n",
        "\n",
        "provider = QiskitProvider()\n",
        "backend = provider.get_backend('backend_name')\n",
        "sampler = BackendSamplerV2(backend)\n",
        "```\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e620a7b2-233d-4e0d-8a42-ee4eda3ccd8d",
      "metadata": {},
      "source": [
        "### Similarities and differences between backend and Runtime primitives\n",
        "\n",
        "* The inputs to and outputs from [`qiskit.primitives.BackendSamplerV2`](/docs/api/qiskit/qiskit.primitives.BackendSamplerV2) and [`qiskit.primitives.BackendEstimatorV2`](../api/qiskit/qiskit.primitives.BackendEstimatorV2)\n",
        "  follow the same PUB format as the primitives in Qiskit Runtime. See [Primitive inputs and outputs](primitive-input-output) for details.\n",
        "  However, there can be differences in the fields of the returned metadata.\n",
        "\n",
        "* The [`qiskit.primitives.BackendEstimatorV2`](/docs/api/qiskit/qiskit.primitives.BackendEstimatorV2) class offers no measurement or gate error mitigation implementations out-of-the-box, as\n",
        "  backend primitives are designed to run locally in the user's machine.\n",
        "\n",
        "* The [`qiskit.primitives.BackendSamplerV2`](/docs/api/qiskit/qiskit.primitives.BackendSamplerV2) class requires a backend that supports the `memory` option.\n",
        "\n",
        "* The backend primitive interfaces expose custom [`SamplerV2`](/docs/api/qiskit/qiskit.primitives.BackendSamplerV2) and [`EstimatorV2`](/docs/api/qiskit/qiskit.primitives.BackendEstimatorV2) `Options` that are different from the Runtime implementations.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d38dd409-e0d8-4749-bb22-58ae9a53d26a",
      "metadata": {},
      "source": [
        "## Next steps\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recommendations\">\n",
        "  * Learn how to [test locally](local-testing-mode) before running on quantum computers.\n",
        "  * Review detailed [primitives examples.](primitives-examples)\n",
        "  * Practice with primitives by working through the [Cost function lesson](/learning/courses/variational-algorithm-design/cost-functions) in IBM Quantum Learning.\n",
        "  * Learn how to transpile locally in the [Transpile](transpile/) section.\n",
        "  * Try the [Compare transpiler settings](/docs/guides/circuit-transpilation-settings#compare-transpiler-settings) guide.\n",
        "  * Learn how to [use the primitive options.](runtime-options-overview)\n",
        "  * View the API for [Sampler](/docs/api/qiskit-ibm-runtime/options-sampler-options) and [Estimator](/docs/api/qiskit-ibm-runtime/options-estimator-options) options.\n",
        "  * Read [Migrate to 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
}