{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "dde95705",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Parity Twine Optimizer： ParityQC によるQiskit関数\"\n",
        "description: \"Parity Twine を使用して、量子コンピュータ上で最適化問題を解く。 量子最適化アルゴリズムを実行するために、ゲート数と回路の深さを最小限に抑えます。\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore parityqc QOBLIB  */}\n",
        "\n",
        "<span id=\"parity-twine-optimizer-a-qiskit-function-by-parityqc\" />\n",
        "\n",
        "# Parity Twine Optimizer： ParityQC によるQiskit関数\n",
        "\n",
        "*[APIリファレンス](/docs/api/functions/parity-twine-optimizer)を参照してください*\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  Qiskit Functions これらは、 IBM Quantum® Premium Plan、Flex Plan、および On-Prem （ IBM Quantum Platform API経由）プランのユーザーのみが利用できる実験的な機能です。 これらはプレビュー版であり、変更される可能性があります。\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"overview\" />\n",
        "\n",
        "## 概要\n",
        "\n",
        "「Parity Twine Optimizer」は、ユーザーが[パリティ・トワイン](https://arxiv.org/abs/2501.14020)法を用いて量子コンピュータで最適化問題を解くことを可能にするものです。\n",
        "Parity Architecture を基盤とするこのアプローチでは、 ParityQC コンパイラを用いて、デバイスの接続性を考慮しつつ、量子アルゴリズムの実行に必要なゲート数と回路の深さを最小限に抑えます。\n",
        "\n",
        "このリソース削減により、標準的なSWAP負荷の高いトランスパイル手法では処理が不可能な規模の、業界に関連する最適化問題を解くことが可能になります。\n",
        "Parity Twine Optimizer はトランスパイリングのプロセスを自動化しており、ユーザーによる操作を最小限に抑えて利用できます。\n",
        "\n",
        "「パリティ・トワイン」アプローチは、\n",
        "[量子近似最適化アルゴリズム（QAOA）](https://arxiv.org/abs/2501.14020) や[量子フーリエ変換（QFT）](https://arxiv.org/abs/2604.12465) といった量子アルゴリズムにおいて、ゲート数や回路深度の削減という点で、他のあらゆるコンパイル手法を上回る性能を発揮する。\n",
        "量子情報を物理的な量子ビットから抽象化することで、SWAPゲートを使用せずに非局所的な相互作用を実現することができる。 その代わりに、パリティ・トワイン・チェーン（CNOTゲートの連鎖）は、論理的な\n",
        "パリティ情報を量子ビット間で体系的に分散させる。\n",
        "\n",
        "オプティマイザーは、QAOAを用いて、与えられたコスト関数のエネルギーを最小化します。 QAOAは、コストハミルトニアン（ $H_C$ ）の基底状態を近似することで、組み合わせ最適化問題を解くために設計された、量子・古典ハイブリッドの変分アルゴリズムである。\n",
        "混合項（ $H_B$ ）が状態間の遷移を促進し、解空間を探索する。 パラメータ $\\gamma$ および $\\beta$ によって制御されるこれらの項の交互の列が、初期状態に作用するユニタリ\n",
        "$U(\\gamma, \\beta) = \\Pi_{i=1}^p e^{-i \\beta_i H_B} e^{-i \\gamma_i H_C}$ を定義する。\n",
        "\n",
        "問題を表すユニタリー演算 exp( $-i \\beta H_C)$ ) を符号化するには、すべての論理 $n$ 体回転演算子 exp( $-i \\beta J_{i,j,...n}Z_iZ_j...Z_n$ ) を符号化する必要がある。\n",
        "これは、 $n$ 体ジェネレータ（パリティ・トワイン・ネットワーク）を用いて実現でき、これによりQAOA回路の深さと2量子ビットゲートの数が削減される。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "02f8e130",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5f761442",
      "metadata": {},
      "source": [
        "<span id=\"description\" />\n",
        "\n",
        "## 説明\n",
        "\n",
        "Parity Twine Optimizerへの入力は、最適化問題、選択した IBM Quantum のハードウェア名、およびトランスパイラやハードウェア実行の設定を調整するための追加のオプション引数で構成されます。 オプティマイザー\n",
        "関数は、問題定義をParity Twineコンパイラに転送します。 図1は、この機能のワークフローの概要を示しています。\n",
        "\n",
        "![Parity Twine Optimizer のワーク](https://quantum.cloud.ibm.com/docs/images/guides/parity-twine-optimizer/process_pipeline.avif \"フロー 図 1：Parity Twine Optimizer のワークフローの概要。\")\n",
        "\n",
        "入力最適化問題は、（正規化された）ハミルトニアンへと前処理される。 その後、 ParityQC コンパイラは、パラメータ化されたParity Twineアンザッツ回路を構築し、これを、選択されたハードウェアのネイティブ\n",
        "ゲートセットに一致する論理アンザッツへとトランスパイルします。\n",
        "\n",
        "QAOA回路のパラメータは、従来、 [「効率的な深度1」](https://github.com/qiskit-community/qaoa_training_pipeline/blob/main/how_tos/efficient_depth_one.ipynb) アプローチを用いて最適化され、トランスパイルされた回路に割り当てられる。\n",
        "QAOAを1回実行するだけで、多くの回路呼び出しを伴うコストのかかる反復最適化を行う必要なく、CPU上でグリッド検索を用いて最適な$\\gamma$および$\\beta$パラメータが得られる これにより、オプティマイザに必要なQPUの実行時間が大幅に短縮されます。 1回路あたりの実行時間は、主にQPU上でジョブを実行するための定数オーバーヘッドによって決まります。\n",
        "回路パラメータの設定が完了すると、そのジョブは指定された IBM® のQPUに送信されます。\n",
        "\n",
        "その後、生データは後処理されます。 このステップでは、局所的な貪欲探索を用い、解の文字列をランダムに順にたどりながら、コスト関数の値が減少する場合にビット値を反転させます。\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "b34fe075",
      "metadata": {},
      "source": [
        "<span id=\"benchmarks\" />\n",
        "\n",
        "## ベンチマーク\n",
        "\n",
        "<Admonition type=\"caution\" title=\"特記事項\">\n",
        "  パフォーマンスは、問題のインスタンスと、それに続く処理ステップの両方に左右される場合があります。 場合によっては、古典的なサンプルと量子生成されたサンプルは、同等の後処理を行った後、同等の最終的な解の品質を達成する可能性があります。 したがって、評価にあたっては、最適化ワークフロー全体を考慮すべきである。\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"sherrington-kirkpatrick-model\" />\n",
        "\n",
        "### シェリントン・カークパトリック・モデル\n",
        "\n",
        "図2は、Parity Twine Optimizerの有効性を示している。 ここでは、量子ビット数を増やしたシェリントン・カークパトリックモデルについて、\n",
        "オプティマイザーを用いて得られた結果とランダムサンプリングによる結果を比較している。\n",
        "\n",
        "ランダムな結果とオプティマイザーによる結果の両方に後処理を施すと、正確な基底状態が得られるが、Twine QAOAから得られる生の最小エネルギー値は、常にランダムな\n",
        "値よりも優れている。 検討対象となった最大の量子ビット数（90および100）の場合、ハードウェアノイズの影響により最適化結果の精度が低下し、ランダムサンプリングの結果と一致する生値に戻ってしまう。\n",
        "\n",
        "![Parity Twine Optimizer SK ベンチマーク](https://quantum.cloud.ibm.com/docs/images/guides/parity-twine-optimizer/benchmark_run_sk.avif \"図 2：SK モデルに対する Parity Twine Optimizer とランダムサンプリングとの比較ベンチマーク結果。 結果は、\n",
        "\\`ibm_boston` において、20,000ショットの反復を3回行って得られた。\")\n",
        "\n",
        "シェリントン・カークパトリック・モデルの概要や、Parity Twine Optimizer を使用してこれを解く方法の詳細については、こちらの[チュートリアル](/docs/tutorials/parity-twine-optimizer-sk)をご覧ください。\n",
        "\n",
        "<span id=\"market-split-problem\" />\n",
        "\n",
        "### 市場の分割問題\n",
        "\n",
        "表1は、マーケット・スプリット（MS）問題のさまざまな事例に適用した「Parity Twine Optimizer」の具体的な性能指標を示している。\n",
        "[これらはQOBLIB（Quantum Optimization Benchmarking Library）](https://github.com/ZIB-AOPT/QOBLIB) から取得したものであり、\n",
        "Parity Twineオプティマイザーを使用して\n",
        "同ライブラリに[提出された結果](https://github.com/ZIB-AOPT/QOBLIB/tree/main/01-marketsplit/submissions/20260728_Parity_Twine_Optimizer)に対応しています。\n",
        "\n",
        "MS違反は、解がすべての制約を満たす状態からどれだけ離れているかを測定する精度指標であり、 $\\sum_i ((Ax - b)_i)^2$ と定義される。この指標の値が小さいほど、解の精度は高いことを示す。\n",
        "表1は、Parity Twine Optimizerを使用し、当該デバイ `ibm_boston` スをバックエンドとして、10万ショットの実行を行った各インスタンスについて、5回の実行結果の平均値をまとめたものである。\n",
        "各インスタンスの実行から得られたMS違反の最小値が報告される。\n",
        "\n",
        "| インスタンス           | 量子ビット  | 2量子ビットゲート | 2量子ビットの深さ | MS違反 | マッピング時間（秒） | QPUの実行時間（秒） | 後処理時間（秒） |\n",
        "| :--------------- | :----- | :-------- | :-------- | :--- | :--------- | :---------- | :------- |\n",
        "| ms\\_03\\_050\\_002 | 20     | 399       | 76        | 0    | 45         | 29 日        | 71       |\n",
        "| ms\\_03\\_100\\_022 | 20     | 399       | 76        | 0    | 30時間まで     | 29 日        | 77       |\n",
        "| ms\\_03\\_200\\_177 | 20     | 399       | 76        | 0    | 33         | 29 日        | 63       |\n",
        "| ms\\_04\\_050\\_001 | 30時間まで | 899       | 116       | 1    | 68         | 29 日        | 216      |\n",
        "| ms\\_04\\_100\\_003 | 30時間まで | 899       | 116       | 2    | 89         | 29 日        | 187      |\n",
        "| ms\\_04\\_200\\_030 | 30時間まで | 899       | 116       | 3    | 89         | 29 日        | 219      |\n",
        "| ms\\_05\\_100\\_003 | 40     | 1599      | 156       | 3    | 237        | 30時間まで      | 364      |\n",
        "| ms\\_06\\_050\\_001 | 50     | 2499      | 196       | 4    | 499        | 30時間まで      | 464      |\n",
        "| ms\\_07\\_050\\_001 | 60     | 3599      | 236       | 17   | 858        | 31          | 637      |\n",
        "| ms\\_08\\_050\\_001 | 70     | 4899      | 276       | 36   | 1561       | 31          | 773      |\n",
        "\n",
        "表1：マーケット・スプリット問題のさまざまなインスタンスに関する性能指標。 インスタンス名は、 [QOBLIB問題](https://github.com/ZIB-AOPT/QOBLIB)ライブラリ内の対応する例を示しています。 前述の説明セクションで述べたように、CPU上で得られた最適な回路パラメータを用いてQAOAを1ラウンドのみ実行するため、QPUの処理時間はごくわずかで、ほぼ一定です。\n",
        "\n",
        "「マーケット・スプリット」問題の概要や、Parity Twine Optimizer を使用してこれを解く方法の詳細については、こちらの[チュートリアル](/docs/tutorials/parity-twine-optimizer-ms)をご覧ください。\n",
        "\n",
        "<span id=\"maximum-independent-set-problem\" />\n",
        "\n",
        "### 最大独立集合問題\n",
        "\n",
        "図3は、[QOBLIB（量子最適化ベンチマークライブラリ）](https://github.com/ZIB-AOPT/QOBLIB)から抽出された特定のインスタンスについて、最大独立集合問題に対し、Parity Twineオプティマイザーとランダムサンプリングを用いて得られた結果を比較したものである これらは、18キュービット（mammalia-kangaroo-interactions）から\n",
        "114キュービット（ es60fst03 ）まで多岐にわたります。\n",
        "\n",
        "小規模なインスタンスの場合、オプティマイザーとランダムサンプリングによる最大独立集合のサイズ（raw）の結果は類似していますが、大規模なインスタンスでは、オプティマイザーの方がはるかに優れた結果をもたらします。\n",
        "ランダムサンプリングの結果とオプティマイザーの結果の両方を後処理すると、再び正確な値と一致する集合のサイズが得られる。\n",
        "\n",
        "![Parity Twine Optimizer MIS ベンチマーク](https://quantum.cloud.ibm.com/docs/images/guides/parity-twine-optimizer/benchmark_run_mis.avif \"図 3：MIS モデルにおける Parity Twine Optimizer のベンチマーク結果とランダムサンプリングとの比較。\n",
        "結果は、`ibm_boston`上で20,000ショットの反復を3回行って得られた。\")\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "73390a19",
      "metadata": {},
      "source": [
        "<span id=\"get-started\" />\n",
        "\n",
        "## 使用を開始する\n",
        "\n",
        "[IBM Quantum Platform のAPIトークンを](/docs/guides/functions-get-started)使用して認証を行い、Qiskit関数を次のように選択してください：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "95a715d2",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "# Authenticate and load the Qiskit Function\n",
        "catalog = QiskitFunctionsCatalog(\n",
        "    channel=\"ibm_quantum_platform\",\n",
        ")\n",
        "function = catalog.load(\"parityqc/parity-twine-optimizer\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e8837f5f",
      "metadata": {},
      "source": [
        "<span id=\"example\" />\n",
        "\n",
        "## 例\n",
        "\n",
        "Parity Twine Optimizerは、次のように単純なQUBOの例に適用することができます。 まず、辞書を用いて問題を定義します：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "d56e1440",
      "metadata": {},
      "outputs": [],
      "source": [
        "problem = {\"()\": 3, \"(0,)\": 1, \"(0, 1)\": 2, \"(1, 2)\": -1}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "69ea92c9",
      "metadata": {},
      "source": [
        "その場合、変数の型は または `binary` として定義する必要があります `spin`：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "06fc4134",
      "metadata": {},
      "outputs": [],
      "source": [
        "variable_type = \"spin\""
      ]
    },
    {
      "cell_type": "markdown",
      "id": "03998691",
      "metadata": {},
      "source": [
        "これは、目的関数 $3 + s_0 + 2 s_0s_1 - s_1s_2$ を定義する。ここで、 $s_i \\in \\{-1, 1\\}$ である。\n",
        "\n",
        "バックエンドを選択してください。 例:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "856fe992",
      "metadata": {},
      "outputs": [],
      "source": [
        "backend_name = \"ibm_phoenix\""
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6f88b8ee-47a8-4c93-b25c-f4eceaf3dbf8",
      "metadata": {},
      "source": [
        "を使用して、そのユーザーアカウント／インスタンスで利用可能なバックエンドの一覧を表示 `catalog.backends()` します。\n",
        "\n",
        "バックエンドが指定されていない場合、最も負荷の低いバックエンド（保留中のジョブ数が最も少ないもの）が自動的に選択されます。\n",
        "\n",
        "オプティマイザが読み込まれたら（前述参照）、デフォルトのオプションを使用して、その問題に対してオプティマイザを実行できます：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "27558d79-01c1-4616-aec0-2a9623e0e9e1",
      "metadata": {},
      "outputs": [],
      "source": [
        "function_job = function.run(\n",
        "    problem=problem, variable_type=variable_type, backend_name=backend_name\n",
        ")\n",
        "print(f\"Job ID: {function_job.job_id}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c036d9c6a386323",
      "metadata": {},
      "source": [
        "以下の手順でジョブのステータスを確認してください：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "5c71411c8ac8271d",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Monitor the job status\n",
        "function_job.status()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "646bd940-80ad-4e79-b4e2-0db447edf41b",
      "metadata": {},
      "source": [
        "結果は次のように取得します：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "197d53b9-2b5e-44e5-99e3-0c285db903a9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Retrieve the job result if the status is DONE\n",
        "result = function_job.result()\n",
        "\n",
        "result"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bb1bba96-4689-4ddf-b72f-6c6e5cf2c3ba",
      "metadata": {},
      "source": [
        "結果を出力すると、次のようになります：\n",
        "\n",
        "```\n",
        "{\n",
        "    'solution': {'0': -1, '1': 1, '2': 1},\n",
        "    'objective_value': -1.0,\n",
        "    'solution_bitstring': '100',\n",
        "    'metadata': {\n",
        "        'circuit_metrics': {\n",
        "            'depth': 20,\n",
        "            'gate_count': 198,\n",
        "            'two_qubit_gate_depth': 4,\n",
        "            'two_qubit_gate_count': 4,\n",
        "            'num_qubits': 3,\n",
        "            'operations': {'delay': 158, 'rz': 17, 'sx': 14, 'cz': 4, 'measure': 3, 'x': 2}\n",
        "        },\n",
        "        'solver_info': {\n",
        "            'variable_mapping': {'0': 0, '1': 1, '2': 2},\n",
        "            'bitstring_distributions': {\n",
        "                'before_postprocessing': {'100': 71760, ... },\n",
        "                'after_postprocessing': {'100': 88440, '011': 11560}\n",
        "            },\n",
        "            'best_parameters': {\n",
        "                'beta': [-0.46259546391008877],\n",
        "                'gamma': [0.6181957189727373]\n",
        "            }\n",
        "        },\n",
        "        'resource_usage': {\n",
        "            'RUNNING: MAPPING': {'CPU_TIME': 42.878},\n",
        "            'RUNNING: OPTIMIZING_FOR_HARDWARE': {'CPU_TIME': 0.094},\n",
        "            'RUNNING: WAITING_FOR_QPU': {'CPU_TIME': 790.623},\n",
        "            'RUNNING: EXECUTING_QPU': {'QPU_TIME': 28.0},\n",
        "            'RUNNING: POST_PROCESSING': {'CPU_TIME': 0.828}\n",
        "        }\n",
        "    }\n",
        "}\n",
        "```\n",
        "\n",
        "この辞書 `solution` は、問題で定義された量子ビット（ $s_0, s_1$、および $s_2$ ）に対応しており、それらの最適化されたスピン値を示しています。\n",
        "\n",
        "は、最適化問題のコストまたはエネルギーである `objective_value` 。 品質 `solution` を数値化します。\n",
        "\n",
        "`metadata` トランスパイレーションに関する情報（2量子ビットゲートの数／深さ、使用されたゲート、アクティブな量子ビット）や、量子計算時間および古典計算時間の各種実行時間を示しています。\n",
        "\n",
        "さらに、このアルゴリズムの内部の仕組みを垣間見 `metadata` ることができます。 最適化された変分パラメータ（ベータとガンマ）を確認し、生の量子測定結果に古典的な後処理を適用した後に、測定されたビット列の分布がどのように改善されたかを確認することができます。\n",
        "\n",
        "結果出力に含まれるすべてのビット文字列は、. を使用することで、問題の変数にマッピングすることができます `variable_mapping`。\n",
        "たとえば、とをバイナリ解に `'solution_bitstring': '100'``'variable_mapping': {'0': 0, '1': 1, '2': 2}` 写像することができます： `{'0': 1, '1': 0, '2': 0}`。\n",
        "スピン変数を用いて問題を解くため、二進数からスピンへの変換（`0` → `1`、 `1` → ） `-1` を適用する必要があります。\n",
        "そうすることで、最終的な解 が得られます `'solution': {'0': -1, '1': 1, '2': 1}`。\n",
        "\n",
        "Parity Twine Optimizer 関数の入力および出力に関する詳細については、 [API リファレンス](/docs/api/functions/parity-twine-optimizer)を参照してください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8ba474e4",
      "metadata": {},
      "source": [
        "<span id=\"changelog\" />\n",
        "\n",
        "## 変更ログ\n",
        "\n",
        "<span id=\"[101]---2026-09-15\" />\n",
        "\n",
        "### \\[1.0.1] - 2026年9月15日\n",
        "\n",
        "**ノード**\n",
        "\n",
        "今回のリリースは、Parity Twine Optimizer Qiskit 関数の最初の安定版です。 今後のリリースでは、以下の機能が導入される見込みです：\n",
        "\n",
        "* 高次問題のまとめ、\n",
        "* その他の最適化アルゴリズム、および\n",
        "* 前処理および後処理の改善。\n",
        "\n",
        "**特徴**\n",
        "\n",
        "* 効率的なパリティ・トワイン・コンパイラを用いて、疎なQUBO問題および密なQUBO問題を解きます。\n",
        "\n",
        "**資料**\n",
        "\n",
        "* はじめに：ユーザーガイド。\n",
        "* マーケット・スプリットおよびシェリントン・カークパトリックの問題に関する、例題付きのチュートリアル。\n",
        "* API ドキュメント。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e9ec2e67",
      "metadata": {},
      "source": [
        "<span id=\"get-support\" />\n",
        "\n",
        "## サポートの利用\n",
        "\n",
        "ご質問や問題がある場合は、 [ParityQC](mailto:support@parityqc.com) までご連絡ください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5a6a25c8",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 次のステップ\n",
        "\n",
        "<Admonition type=\"tip\" title=\"推奨事項\">\n",
        "  * この[フォーム](https://parityqc.com/products/parity-twine-optimizer/free-trial)に必要事項を記入して、当該機能へのアクセス権を申請してください。\n",
        "  * このQiskit関数の [APIリファレンス](/docs/api/functions/parity-twine-optimizer)をご覧ください。\n",
        "  * 「Market Split」問題に「Parity Twine Optimizer」を適用する方法について、 [チュートリアル](/docs/tutorials/parity-twine-optimizer-ms)を試してみてください。\n",
        "  * 「Parity Twine Optimizer」をシェリントン・カークパトリック・モデルに適用する方法について、 [チュートリアル](/docs/tutorials/parity-twine-optimizer-sk)をお試しください。\n",
        "  * [Drier ら（2025）による](https://arxiv.org/abs/2501.14020) 「量子アルゴリズムの接続性考慮合成」に関するプレプリント（ ArXiv ）を参照のこと。\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": 5
}