{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b9fd7c5e-f3b8-4f0d-8632-821d601af52c",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Executar tarefas em uma sessão\"\n",
        "description: \"Como executar uma tarefa de computação quântica em uma sessão do Qiskit Runtime.\"\n",
        "---\n",
        "\n",
        "<span id=\"run-jobs-in-a-session\" />\n",
        "\n",
        "# Executar tarefas em uma sessão\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "817c70e7-29dd-4f70-85ad-6487d7c4b010",
      "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=\"Versões do pacote\">\n",
        "    O código nesta página foi desenvolvido utilizando os seguintes requisitos.\n",
        "    Recomendamos usar essas versões ou mais recentes.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.3.1\n",
        "    qiskit-ibm-runtime~=0.45.0\n",
        "    scipy~=1.17.1\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "be06e0ee-e593-4fe7-aa98-4f6e0dcbaa9f",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\" title=\"Nota\">\n",
        "  Os usuários do Open Plan não podem enviar trabalhos de sessão. As cargas de trabalho devem ser executadas no [modo de trabalho](/docs/guides/execution-modes#job-mode) ou no [modo de lote](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n",
        "Use as sessões quando precisar de acesso dedicado e exclusivo à QPU.\n",
        "\n",
        "<span id=\"set-up-to-use-sessions\" />\n",
        "\n",
        "## Configurar para usar sessões\n",
        "\n",
        "Antes de iniciar uma sessão, você deve [configurar o Qiskit Runtime](/docs/guides/install-qiskit) e inicializá-lo como um serviço:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "117d0471-1f98-489c-906f-8aab836cd877",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import (\n",
        "    QiskitRuntimeService,\n",
        "    Session,\n",
        "    SamplerV2 as Sampler,\n",
        "    EstimatorV2 as Estimator,\n",
        "    Executor,\n",
        ")\n",
        "\n",
        "service = QiskitRuntimeService()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1e1cd9a3-7f36-4f42-8924-7f4dac202788",
      "metadata": {},
      "source": [
        "<span id=\"open-a-session\" />\n",
        "\n",
        "## Abrir uma sessão\n",
        "\n",
        "Você pode abrir uma sessão de tempo de execução usando o gerenciador de contexto `with Session(...)` ou inicializando a `Session` classe. Ao iniciar uma sessão, você deve especificar uma QPU passando um objeto `backend` . A sessão começa quando seu primeiro trabalho inicia a execução.\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Se você abrir uma sessão, mas não enviar nenhum trabalho para ela por 30 minutos, a sessão será fechada automaticamente.\n",
        "</Admonition>\n",
        "\n",
        "**Aula de sessão**\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  O bloco de código a seguir retornará um erro para os usuários no Open Plan porque usa sessões. As cargas de trabalho no Open Plan podem ser executadas somente no [modo de trabalho](/docs/guides/execution-modes#job-mode) ou no [modo de lote](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "2694bd4c-2011-4671-9625-3e7e941dd381",
      "metadata": {},
      "outputs": [],
      "source": [
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "session = Session(backend=backend)\n",
        "estimator = Estimator(mode=session)\n",
        "sampler = Sampler(mode=session)\n",
        "executor = Executor(mode=session)\n",
        "# Close the session because no context manager was used.\n",
        "session.close()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e0460f64-f5a8-4663-834a-a4c15c9ad82b",
      "metadata": {},
      "source": [
        "**Gerenciador de contexto**\n",
        "\n",
        "O gerenciador de contexto abre e fecha automaticamente a sessão.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  O bloco de código a seguir retornará um erro para os usuários no Open Plan porque usa sessões. As cargas de trabalho no Open Plan podem ser executadas somente no [modo de trabalho](/docs/guides/execution-modes#job-mode) ou no [modo de lote](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "192e5e57-2f9d-4f8e-b3e7-1dd31907e8a6",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_runtime import (\n",
        "    Session,\n",
        "    SamplerV2 as Sampler,\n",
        "    EstimatorV2 as Estimator,\n",
        "    Executor,\n",
        ")\n",
        "\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "with Session(backend=backend):\n",
        "    estimator = Estimator()\n",
        "    sampler = Sampler()\n",
        "    executor = Executor()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e4219769-6348-4d0c-8e13-830177a4e7b8",
      "metadata": {},
      "source": [
        "<span id=\"specify-length\" />\n",
        "\n",
        "<span id=\"session-length\" />\n",
        "\n",
        "## Duração da sessão\n",
        "\n",
        "O tempo máximo de vida da sessão (TTL) determina por quanto tempo uma sessão pode ser executada.  Você pode definir esse valor com o parâmetro `max_time` . Isso deve exceder o tempo de execução do trabalho mais longo.\n",
        "\n",
        "Esse cronômetro começa quando a sessão é iniciada.  Quando o valor é atingido, a sessão é encerrada.  Todos os trabalhos que estiverem em execução serão concluídos, mas os trabalhos que ainda estiverem na fila falharão.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  O bloco de código a seguir retornará um erro para os usuários no Open Plan porque usa sessões. As cargas de trabalho no Open Plan podem ser executadas somente no [modo de trabalho](/docs/guides/execution-modes#job-mode) ou no [modo de lote](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n",
        "```python\n",
        "with Session(backend=backend, max_time=\"25m\"):\n",
        "  ...\n",
        "```\n",
        "\n",
        "Há também um valor de tempo de vida interativo (TTL interativo) que não pode ser configurado.  Se nenhum trabalho de sessão for enfileirado dentro dessa janela, a sessão será temporariamente desativada.\n",
        "\n",
        "Valores padrão:\n",
        "\n",
        "| Tipo de instância (Plano Aberto ou Premium)                                                  | TTL interativo | TTL Máximo |\n",
        "| -------------------------------------------------------------------------------------------- | -------------- | ---------- |\n",
        "| Plano Premium                                                                                | 60 seg\\*       | 8 h\\*      |\n",
        "| *\\* Algumas instâncias do Plano Premium podem ser configuradas para ter um valor diferente.* |                |            |\n",
        "\n",
        "Para determinar o TTL máximo ou o TTL interativo de uma sessão, siga as instruções em [Determinar detalhes da sessão](#session-details) e procure o valor `max_time`ou `interactive_timeout` , respectivamente.\n",
        "\n",
        "<span id=\"ends\" />\n",
        "\n",
        "<span id=\"end-a-session\" />\n",
        "\n",
        "## Encerrar uma sessão\n",
        "\n",
        "Uma sessão termina nas seguintes circunstâncias:\n",
        "\n",
        "* O valor de tempo limite máximo (TTL) é atingido, resultando no cancelamento de todos os trabalhos na fila.\n",
        "* A sessão é cancelada manualmente, resultando no cancelamento de todos os trabalhos na fila.\n",
        "* A sessão é encerrada manualmente.  A sessão para de aceitar novos trabalhos, mas continua a executar trabalhos na fila com prioridade.\n",
        "* Se você usar a Session como um gerenciador de contexto, ou seja, `with Session()`, a sessão será automaticamente encerrada quando o contexto terminar (o mesmo comportamento do uso de `session.close()`).\n",
        "\n",
        "<span id=\"close\" />\n",
        "\n",
        "<span id=\"close-a-session\" />\n",
        "\n",
        "### Fechar uma sessão\n",
        "\n",
        "Uma sessão é fechada automaticamente quando sai do gerenciador de contexto. Quando o gerenciador de contexto de sessão é encerrado, a sessão é colocada no status \"Em andamento, não aceitando novos trabalhos\". Isso significa que a sessão termina o processamento de todos os trabalhos em execução ou em fila até que o valor máximo de tempo limite seja atingido. Após a conclusão de todos os trabalhos, a sessão é imediatamente encerrada. Isso permite que o agendador execute o próximo trabalho sem esperar pelo tempo limite interativo da sessão, reduzindo assim o tempo médio de enfileiramento do trabalho. Não é possível enviar trabalhos para uma sessão fechada.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  O bloco de código a seguir retornará um erro para os usuários no Open Plan porque usa sessões. As cargas de trabalho no Open Plan podem ser executadas somente no [modo de trabalho](/docs/guides/execution-modes#job-mode) ou no [modo de lote](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "c6646bed-3064-488f-b2ff-da9ba793775a",
      "metadata": {},
      "outputs": [],
      "source": [
        "with Session(backend=backend) as session:\n",
        "    estimator = Estimator()\n",
        "    sampler = Sampler()\n",
        "    job1 = estimator.run([estimator_pub])\n",
        "    job2 = sampler.run([sampler_pub])\n",
        "\n",
        "# The session is no longer accepting jobs but the submitted job will run to completion.\n",
        "result = job1.result()\n",
        "result2 = job2.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "20eb23f3-fc34-4f38-8ad7-85278ff4c823",
      "metadata": {},
      "source": [
        "<Admonition type=\"tip\">\n",
        "  Se não estiver usando um gerenciador de contexto, feche manualmente a sessão para evitar custos indesejados. Você pode fechar uma sessão assim que terminar de enviar trabalhos para ela. Quando uma sessão é fechada com `session.close()`, ela não aceita mais novos trabalhos, mas os trabalhos já enviados ainda serão executados até a conclusão e seus resultados poderão ser recuperados.\n",
        "</Admonition>\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  O bloco de código a seguir retornará um erro para os usuários no Open Plan porque usa sessões. As cargas de trabalho no Open Plan podem ser executadas somente no [modo de trabalho](/docs/guides/execution-modes#job-mode) ou no [modo de lote](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "861cf6b3-9695-41eb-9d3d-d5293880ca75",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Result1: PrimitiveResult([PubResult(data=DataBin(evs=np.ndarray(<shape=(3, 2), dtype=float64>), stds=np.ndarray(<shape=(3, 2), dtype=float64>), ensemble_standard_error=np.ndarray(<shape=(3, 2), dtype=float64>), shape=(3, 2)), 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"
          ]
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Result2: PrimitiveResult([SamplerPubResult(data=DataBin(meas=BitArray(<shape=(3, 2), num_shots=4096, num_bits=2>), meas0=BitArray(<shape=(3, 2), num_shots=4096, num_bits=156>), shape=(3, 2)), metadata={'circuit_metadata': {}})], metadata={'execution': {'execution_spans': ExecutionSpans([DoubleSliceSpan(<start='2026-03-15 07:33:44', stop='2026-03-15 07:33:51', size=24576>)])}, 'version': 2})\n"
          ]
        }
      ],
      "source": [
        "session = Session(backend=backend)\n",
        "\n",
        "# If using qiskit-ibm-runtime earlier than 0.24.0, change `mode=` to `session=`\n",
        "estimator = Estimator(mode=session)\n",
        "sampler = Sampler(mode=session)\n",
        "job1 = estimator.run([estimator_pub])\n",
        "job2 = sampler.run([sampler_pub])\n",
        "print(f\"Result1: {job1.result()}\")\n",
        "print(f\"Result2: {job2.result()}\")\n",
        "\n",
        "# Manually close the session. Running and queued jobs will run to completion.\n",
        "session.close()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "aad804ed-027f-49c3-9f7d-8851a4f3de3a",
      "metadata": {},
      "source": [
        "<span id=\"session-status\" />\n",
        "\n",
        "<span id=\"check-session-status\" />\n",
        "\n",
        "## Verifique o status da sessão\n",
        "\n",
        "Você pode consultar o status de uma sessão para entender seu estado atual usando `session.status()` ou visualizando a página [Workloads](/workloads).\n",
        "\n",
        "O status da sessão pode ser um dos seguintes:\n",
        "\n",
        "* `Pending`: A sessão não foi iniciada ou foi desativada. O próximo trabalho de sessão precisa aguardar na fila como os outros trabalhos.\n",
        "* `In progress, accepting new jobs`: A sessão está ativa e aceitando novos trabalhos.\n",
        "* `In progress, not accepting new jobs`: A sessão está ativa, mas não está aceitando novos trabalhos. O envio de trabalhos para a sessão é rejeitado, mas os trabalhos pendentes da sessão serão executados até a conclusão. A sessão é fechada automaticamente quando todos os trabalhos são concluídos.\n",
        "* `Closed`: O valor máximo de tempo limite da sessão foi atingido ou a sessão foi encerrada explicitamente.\n",
        "\n",
        "<span id=\"session-details\" />\n",
        "\n",
        "<span id=\"determine-session-details\" />\n",
        "\n",
        "## Determine os detalhes da sessão\n",
        "\n",
        "Para obter uma visão geral abrangente da configuração e do status de uma sessão, use o site `session.details() method`.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  O bloco de código a seguir retornará um erro para os usuários no Open Plan porque usa sessões. As cargas de trabalho no Open Plan podem ser executadas somente no [modo de trabalho](/docs/guides/execution-modes#job-mode) ou no [modo de lote](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "82a2599e-3e32-4e01-9a36-b77a56af7647",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "{'id': 'a9fd2f9d-6239-4451-a19c-9b45aa6a0618', 'backend_name': 'ibm_torino', 'interactive_timeout': 60, 'max_time': 28800, 'active_timeout': 28800, 'state': 'open', 'accepting_jobs': True, 'last_job_started': None, 'last_job_completed': None, 'started_at': None, 'closed_at': None, 'activated_at': None, 'mode': 'dedicated', 'usage_time': None}\n"
          ]
        }
      ],
      "source": [
        "from qiskit_ibm_runtime import (\n",
        "    QiskitRuntimeService,\n",
        "    Session,\n",
        "    EstimatorV2 as Estimator,\n",
        ")\n",
        "\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(operational=True, simulator=False)\n",
        "\n",
        "with Session(backend=backend) as session:\n",
        "    print(session.details())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7db97311-25cb-4b81-9dba-494264c554c6",
      "metadata": {},
      "source": [
        "<span id=\"usage-patterns\" />\n",
        "\n",
        "## Padrões de uso\n",
        "\n",
        "As sessões são especialmente úteis para algoritmos que exigem comunicação frequente entre recursos clássicos e quânticos.\n",
        "\n",
        "Exemplo: Execute uma carga de trabalho iterativa que usa o otimizador clássico SciPy para minimizar uma função de custo. Nesse modelo, o site SciPy usa o resultado da função de custo para calcular seu próximo input.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  O bloco de código a seguir retornará um erro para os usuários no Open Plan porque usa sessões. As cargas de trabalho no Open Plan podem ser executadas somente no [modo de trabalho](/docs/guides/execution-modes#job-mode) ou no [modo de lote](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "77cc7c96-e8c0-4970-b05e-361ddf74d707",
      "metadata": {},
      "outputs": [],
      "source": [
        "from scipy.optimize import minimize\n",
        "from qiskit.circuit.library import efficient_su2\n",
        "\n",
        "\n",
        "def cost_func(params, ansatz, hamiltonian, estimator):\n",
        "    # Return estimate of energy from estimator\n",
        "\n",
        "    energy = sum(\n",
        "        estimator.run([(ansatz, hamiltonian, params)]).result()[0].data.evs\n",
        "    )\n",
        "    return energy\n",
        "\n",
        "\n",
        "hamiltonian = SparsePauliOp.from_list(\n",
        "    [(\"YZ\", 0.3980), (\"ZI\", -0.3980), (\"ZZ\", -0.0113), (\"XX\", 0.1810)]\n",
        ")\n",
        "su2_ansatz = efficient_su2(hamiltonian.num_qubits)\n",
        "pm = generate_preset_pass_manager(backend=backend, optimization_level=3)\n",
        "ansatz = pm.run(su2_ansatz)\n",
        "mapped_hamiltonian = [\n",
        "    operator.apply_layout(ansatz.layout) for operator in hamiltonian\n",
        "]\n",
        "\n",
        "num_params = ansatz.num_parameters\n",
        "x0 = 2 * np.pi * np.random.random(num_params)\n",
        "\n",
        "session = Session(backend=backend)\n",
        "\n",
        "\n",
        "# If using qiskit-ibm-runtime earlier than 0.24.0, change `mode=` to `session=`\n",
        "estimator = Estimator(mode=session, options={\"default_shots\": int(1e4)})\n",
        "res = minimize(\n",
        "    cost_func,\n",
        "    x0,\n",
        "    args=(ansatz, mapped_hamiltonian, estimator),\n",
        "    method=\"cobyla\",\n",
        "    options={\"maxiter\": 25},\n",
        ")\n",
        "\n",
        "# Close the session because no context manager was used.\n",
        "session.close()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8c03c721-f040-4066-a9d2-f2dd39777789",
      "metadata": {},
      "source": [
        "<span id=\"two-vqe\" />\n",
        "\n",
        "<span id=\"run-two-vqe-algorithms-in-a-session-by-using-threading\" />\n",
        "\n",
        "## Execute dois algoritmos VQE em uma sessão usando threading\n",
        "\n",
        "Você pode tirar mais proveito de uma sessão executando várias cargas de trabalho simultaneamente. O exemplo a seguir mostra como é possível executar dois algoritmos VQE, cada um usando um otimizador clássico diferente, simultaneamente em uma única sessão. As tags de trabalho também são usadas para diferenciar os trabalhos de cada carga de trabalho.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  O bloco de código a seguir retornará um erro para os usuários no Open Plan porque usa sessões. As cargas de trabalho no Open Plan podem ser executadas somente no [modo de trabalho](/docs/guides/execution-modes#job-mode) ou no [modo de lote](/docs/guides/execution-modes#batch-mode).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "e83f7d60-13f0-4df1-9766-6fa67c970362",
      "metadata": {},
      "outputs": [],
      "source": [
        "from concurrent.futures import ThreadPoolExecutor\n",
        "from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
        "\n",
        "\n",
        "def minimize_thread(estimator, method):\n",
        "    return minimize(\n",
        "        cost_func,\n",
        "        x0,\n",
        "        args=(ansatz, mapped_hamiltonian, estimator),\n",
        "        method=method,\n",
        "        options={\"maxiter\": 25},\n",
        "    )\n",
        "\n",
        "\n",
        "with Session(backend=backend), ThreadPoolExecutor() as executor:\n",
        "    estimator1 = Estimator()\n",
        "    estimator2 = Estimator()\n",
        "\n",
        "    # Use different tags to differentiate the jobs.\n",
        "    estimator1.options.environment.job_tags = [\"cobyla\"]\n",
        "    estimator2.options.environment.job_tags = [\"nelder-mead\"]\n",
        "\n",
        "    # Submit the two workloads.\n",
        "    cobyla_future = executor.submit(minimize_thread, estimator1, \"cobyla\")\n",
        "    nelder_mead_future = executor.submit(\n",
        "        minimize_thread, estimator2, \"nelder-mead\"\n",
        "    )\n",
        "\n",
        "    # Get workload results.\n",
        "    cobyla_result = cobyla_future.result()\n",
        "    nelder_mead_result = nelder_mead_future.result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0194fb4b-0917-45d7-aeb1-9fdff38cc5c5",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Próximas etapas\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Recomendações\">\n",
        "  * Experimente um exemplo no tutorial [do algoritmo de otimização aproximada quântica (QAOA)](/docs/tutorials/quantum-approximate-optimization-algorithm).\n",
        "  * Analise a referência [da Session API](/docs/api/qiskit-ibm-runtime/session).\n",
        "  * Entenda os [limites do trabalho](/docs/guides/job-limits) ao enviar um trabalho para uma QPU IBM®.\n",
        "  * Consulte [as perguntas frequentes sobre os modos de execução](/docs/guides/execution-modes-faq).\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
}