{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b9fd7c5e-f3b8-4f0d-8632-821d601af52c",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"セッション内でジョブを実行する\"\n",
        "description: \"IBM Quantum Compute Service セッションで量子コンピューティングジョブを実行する方法。\"\n",
        "---\n",
        "\n",
        "<span id=\"run-jobs-in-a-session\" />\n",
        "\n",
        "# セッション内でジョブを実行する\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=\"パッケージ・バージョン\">\n",
        "    このページ上のコードは、以下の要件に基づいて開発されました。\n",
        "    これらのバージョンまたはそれ以降のバージョンを使用することを推奨します。\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=\"注\">\n",
        "  オープンプランのユーザーはセッションジョブを送信できません。 ワークロードは、 [ジョブモード](/docs/guides/execution-modes#job-mode)または[バッチ](/docs/guides/execution-modes#batch-mode)モードで実行しなければならない。\n",
        "</Admonition>\n",
        "\n",
        "QPUへの専用アクセスが必要な場合は、セッションをご利用ください。\n",
        "\n",
        "<span id=\"set-up-to-use-sessions\" />\n",
        "\n",
        "## セッションを使用する設定\n",
        "\n",
        "セッションを開始する前に、 [IBM Quantum Compute クライアントを設定し](/docs/guides/install-qiskit-runtime)、サービスとして初期化する必要があります\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",
        "## セッションを開く\n",
        "\n",
        "ランタイム・セッションを開くには、コンテキスト・マネージャー `with Session(...)` を使うか、あるいは `Session` クラスを初期化することで開くことができる。 セッションの開始時に、 `backend` オブジェクトを渡して QPU を指定する必要があります。 セッションは、最初のジョブが実行を開始した時点で開始する。\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  セッションを開いたが、30分間ジョブを送信しなかった場合、セッションは自動的に終了する。\n",
        "</Admonition>\n",
        "\n",
        "**セッションクラス**\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  次のコードブロックは、セッションを使用しているため、オープンプランのユーザーに対してエラーを返します。 オープンプラン上のワークロードは、 [ジョブモード](/docs/guides/execution-modes#job-mode)または[バッチモードでのみ](/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": [
        "**コンテキスト・マネージャー**\n",
        "\n",
        "コンテキスト・マネージャーは自動的にセッションを開いたり閉じたりする。\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  次のコードブロックは、セッションを使用しているため、オープンプランのユーザーに対してエラーを返します。 オープンプラン上のワークロードは、 [ジョブモード](/docs/guides/execution-modes#job-mode)または[バッチモードでのみ](/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",
        "## セッションの長さ\n",
        "\n",
        "最大セッション生存時間（TTL）は、セッションが実行できる時間を決定する。  この値は `max_time` パラメータで設定できる。 これは、最長ジョブの実行時間を上回るはずである。\n",
        "\n",
        "このタイマーはセッション開始時にスタートする。  この値に達すると、セッションは終了する。  実行中のジョブはすべて終了するが、キューに残っているジョブは失敗する。\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  次のコードブロックは、セッションを使用しているため、オープンプランのユーザーに対してエラーを返します。 オープンプラン上のワークロードは、 [ジョブモード](/docs/guides/execution-modes#job-mode)または[バッチモードでのみ](/docs/guides/execution-modes#batch-mode)実行できます。\n",
        "</Admonition>\n",
        "\n",
        "```python\n",
        "with Session(backend=backend, max_time=\"25m\"):\n",
        "  ...\n",
        "```\n",
        "\n",
        "また、設定できないインタラクティブTTL（interactive time to live）値もある。  そのウィンドウ内にセッション・ジョブがキューに入っていない場合、セッションは一時的に停止される。\n",
        "\n",
        "デフォルト値:\n",
        "\n",
        "| インスタンスタイプ（オープンまたはプレミアムプラン）                   | インタラクティブTTL | 最大 TTL |\n",
        "| -------------------------------------------- | ----------- | ------ |\n",
        "| プレミアム・プラン                                    | 60秒         | 8 h\\*  |\n",
        "| *\\* プレミアムプランのインスタンスによっては、異なる値が設定される場合があります。* |             |        |\n",
        "\n",
        "セッションの最大TTLまたは対話的TTLを決定するには、 [セッションの詳細を決定する](#session-details)の指示に従って、それぞれ `max_time`、 `interactive_timeout` 。\n",
        "\n",
        "<span id=\"ends\" />\n",
        "\n",
        "<span id=\"end-a-session\" />\n",
        "\n",
        "## セッションを終了する\n",
        "\n",
        "以下の場合、セッションは終了する：\n",
        "\n",
        "* 最大タイムアウト(TTL)値に達すると、キューに入れられたすべてのジョブがキャンセルされる。\n",
        "* セッションは手動でキャンセルされ、キューに入れられたジョブはすべてキャンセルされる。\n",
        "* セッションは手動で閉じられる。  セッションは新しいジョブの受け付けを停止するが、キューに入れられたジョブは優先的に実行し続ける。\n",
        "* Sessionをコンテキストマネージャーとして使用した場合、つまり `with Session()`、コンテキストが終了するとセッションは自動的に閉じられます（ `session.close()` を使用した場合と同じ動作）。\n",
        "\n",
        "<span id=\"close\" />\n",
        "\n",
        "<span id=\"close-a-session\" />\n",
        "\n",
        "### セッションを閉じる\n",
        "\n",
        "コンテキストマネージャーを終了すると、セッションは自動的に終了する。 セッション・コンテキスト・マネージャーが終了すると、セッションは「進行中、新規ジョブは受け付けない」ステータスになる。 これは、セッションが最大タイムアウト値に達するまで、実行中またはキューに入れられたすべてのジョブの処理を終了することを意味する。 すべてのジョブが終了すると、セッションは即座に終了する。 これにより、スケジューラは、セッション・インタラクティブのタイムアウトを待たずに次のジョブを実行できるようになり、平均ジョブ待ち行列時間が短縮される。 クローズド・セッションに求人を出すことはできない。\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  次のコードブロックは、セッションを使用しているため、オープンプランのユーザーに対してエラーを返します。 オープンプラン上のワークロードは、 [ジョブモード](/docs/guides/execution-modes#job-mode)または[バッチモードでのみ](/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",
        "  コンテキストマネージャーを使用していない場合は、不要なコストを避けるために手動でセッションを終了してください。 セッションへのジョブ投入が終わったら、すぐにセッションを閉じることができる。 セッションが `session.close()` で閉じられると、新しいジョブは受け付けられなくなりますが、すでに投入されたジョブは完了するまで実行され、その結果を取得することができます。\n",
        "</Admonition>\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  次のコードブロックは、セッションを使用しているため、オープンプランのユーザーに対してエラーを返します。 オープンプラン上のワークロードは、 [ジョブモード](/docs/guides/execution-modes#job-mode)または[バッチモードでのみ](/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",
        "## セッションの状態を確認する\n",
        "\n",
        "セッションのステータスを照会して現在の状態を把握するには、 `session.status()` を使用するか、 [ワークロードページを](/workloads)表示します。\n",
        "\n",
        "セッション・ステータスは以下のいずれかである：\n",
        "\n",
        "* `Pending`:セッションが開始されていないか、無効になっています。 次のセッション・ジョブは、他のジョブと同じようにキューで待つ必要がある。\n",
        "* `In progress, accepting new jobs`:セッションはアクティブで、新しいジョブを受け付けています。\n",
        "* `In progress, not accepting new jobs`:セッションは有効ですが、新しいジョブを受け付けていません。 セッションへのジョブ投入は拒否されるが、未完了のセッション・ジョブは完了まで実行される。 すべてのジョブが終了すると、セッションは自動的に終了する。\n",
        "* `Closed`:セッションの最大タイムアウト値に達したか、セッションが明示的に閉じられた。\n",
        "\n",
        "<span id=\"session-details\" />\n",
        "\n",
        "<span id=\"determine-session-details\" />\n",
        "\n",
        "## セッションの詳細を決定する\n",
        "\n",
        "セッションのコンフィギュレーションとステータスの包括的な概要については、 `session.details() method`。\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  次のコードブロックは、セッションを使用しているため、オープンプランのユーザーに対してエラーを返します。 オープンプラン上のワークロードは、 [ジョブモード](/docs/guides/execution-modes#job-mode)または[バッチモードでのみ](/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",
        "## 使用パターン\n",
        "\n",
        "セッションは、古典的リソースと量子リソースの間で頻繁に通信を必要とするアルゴリズムに特に有効である。\n",
        "\n",
        "例コスト関数を最小化するために古典的な SciPy オプティマイザを使用する反復作業負荷を実行する。 このモデルでは、 SciPy、コスト関数の出力を使って次の入力を計算する。\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  次のコードブロックは、セッションを使用しているため、オープンプランのユーザーに対してエラーを返します。 オープンプラン上のワークロードは、 [ジョブモード](/docs/guides/execution-modes#job-mode)または[バッチモードでのみ](/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",
        "## スレッド化を使用して、1回のセッションで2つのVQEアルゴリズムを実行する\n",
        "\n",
        "複数のワークロードを同時に実行することで、セッションからより多くの成果を得ることができる。 以下の例では、2つのVQEアルゴリズム（それぞれ異なる古典的オプティマイザを使用）を、1つのセッション内で同時に実行する方法を示しています。 ジョブタグは、各ワークロードとジョブを区別するためにも使用される。\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  次のコードブロックは、セッションを使用しているため、オープンプランのユーザーに対してエラーを返します。 オープンプラン上のワークロードは、 [ジョブモード](/docs/guides/execution-modes#job-mode)または[バッチモードでのみ](/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",
        "## 次のステップ\n",
        "\n",
        "<Admonition type=\"tip\" title=\"推奨事項\">\n",
        "  * [量子近似最適化アルゴリズム(QAOA)の](/docs/tutorials/quantum-approximate-optimization-algorithm)チュートリアルの例を試してみてください。\n",
        "  * [セッション API の](/docs/api/qiskit-ibm-runtime/session)リファレンスを確認してください。\n",
        "  * IBM® QPUにジョブを送信する際の[ジョブ制限を](/docs/guides/job-limits)理解してください。\n",
        "  * [実行モードに関するよくある質問](/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
}