{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "dde95705",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"制約付き量子オプティマイザー - AqariosによるQiskit関数\"\n",
        "description: \"Aqarios社のXYミキサーを用いた反復型ウォームスタートQAOAを活用し、 IBM Quantum ハードウェア上で制約付き二値最適化問題を解きます。\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore Aqarios QOBLIB Bucher docplex forall Zachary quicksum */}\n",
        "\n",
        "<span id=\"constrained-quantum-optimizer---a-qiskit-function-by-aqarios\" />\n",
        "\n",
        "# 制約付き量子オプティマイザー - AqariosによるQiskit関数\n",
        "\n",
        "*[APIリファレンス](/docs/api/functions/aqarios-constrained-quantum-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",
        "Aqarios社の「Constrained Quantum Optimizer」を使用すれば、手動による再定式化や回路マッピングを行うことなく、 IBM® の量子ハードウェア上で制約付き二値最適化問題を解くことができます。 問題をLPファイル、MPSファイル、または [Lunaモデル](https://docs.aqarios.com/luna-model)としてご提供ください。 この関数は、再定式化、回路合成、トランスパイル、およびハードウェア実行を自動的に処理します。 このソルバーは、量子近似最適化アルゴリズム（QAOA）の制約ネイティブ拡張である [FlexQAOA](https://docs.aqarios.com/luna-solve/algorithms/quantum-gate/flexqaoa/) アルゴリズムの反復的ウォームスタート法 [\\[1\\]](#references) を採用している。\n",
        "\n",
        "このオプティマイザーは、制約付き二値問題を対象としています。 特に、ワンホット制約やセットパッキング制約は、XY-ミキサーを使用することでネイティブに適用することができます。 その他の制約の種類は、自動的にペナルティ項として再定式化されます。\n",
        "\n",
        "<Admonition type=\"note\" title=\"サポートされている変数型\">\n",
        "  この関数は離散的な問題のみを解きます。 すべての決定変数は、量子ビットにエンコードできるよう、二値であるか、あるいは明示的な下限と上限を持つ整数でなければならない。 連続（実数値）変数はサポートされていません。これらを含むモデルは、エラーコード とともに拒否されます `4710`。\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e9f4110b",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8bcd63ea",
      "metadata": {},
      "source": [
        "<span id=\"description\" />\n",
        "\n",
        "## 説明\n",
        "\n",
        "<Admonition type=\"caution\" title=\"特記事項\">\n",
        "  パフォーマンスは、問題のインスタンスと、それに続く処理ステップの両方に左右される場合があります。 場合によっては、古典的なサンプルと量子生成されたサンプルは、同等の後処理を施した後、同等の最終的な解の品質を達成することがある。 したがって、評価にあたっては、最適化ワークフロー全体を考慮すべきである。\n",
        "</Admonition>\n",
        "\n",
        "制約付き量子オプティマイザーは、反復型ウォームスタートXYミキサーQAOA（IWS-QAOA） [\\[1\\]](#references) を実装している。 このアルゴリズムは、量子ハードウェア上で固定角度のQAOA回路を実行し、前回の反復における測定結果を用いて、各回路の初期のウォームスタート確率を更新する。 変分パラメータの学習は必要なく、代わりに固定の線形ランプパラメータ化が採用される。\n",
        "\n",
        "XYミキサーを用いてワンホット制約を適用することで、制約付き問題の解の質を飛躍的に向上させることができます。これは、探索空間が実質的により小さな実行可能な部分空間に縮小されるためであり、かつ、最適化ランドスケープにペナルティ項による追加の複雑さが生じないからです。\n",
        "\n",
        "<span id=\"workflow\" />\n",
        "\n",
        "### ワークフロー\n",
        "\n",
        "この関数のワークフローは以下の通りです：\n",
        "\n",
        "1. **前処理** ：回路合成の前に、最適化アルゴリズムは入力問題の制約構造を分析します：\n",
        "   * *グラフの前処理：* 問題に応じて、変数間の関係を辺で表すグラフとして分析を行う。 このグラフ解析により、前処理に関する2つの問題の改善が可能となります。 まず、クリーク結合を用いることで、個々の制約を1つの大きな制約に集約することができ、その結果、それらは単一のXYミキサーによって表現されるようになる。 第二に、隣接する変数が1つしかない変数は決定論的に固定できるため、問題の規模と複雑さを軽減できる。\n",
        "   * *制約の解決：* プリプロセッサは各制約を個別に処理します。制約がワンホット制約である場合、XYミキサーを用いてその制約を適用することができます。 セットパッキング制約である場合、まずワンホット制約に変換されます。 等式制約は二次ペナルティによって、不等式制約は[不均衡ペナルティ](https://doi.org/10.1088/2058-9565/ad35e4)によって処理される。\n",
        "   * *ペナルティの導出：* ワンホット等式制約として表現できない制約は、ペナルティ項に変換される。 オプティマイザは、問題の構造からペナルティの強さを自動的に導出します。\n",
        "2. **反復的ウォームスタート** ：オプティマイザは、複数の*ウォームスタートチェーンを並列に*実行する。 各チェーンは、変数の割り当てに関する確率分布を保持しており、これはQAOA回路の初期確率（ウォームスタート状態）として用いられる。 各反復において、チェーンは量子回路からサンプルを抽出し、古典的な事後処理を適用し、サンプルの出現状況に基づいてその分布を更新する。 反復処理を通じて、これにより、変分最適化ループを用いることなく、高品質な解の探索に焦点を絞ることができます。\n",
        "\n",
        "チェーン数（`num_parallel`）、チェーンごとの総ショット予算（`total_shots`）、およびQAOAの反復回数（`reps`）は、解の品質と実行時間のバランスを調整するための主要な制御パラメータである。\n",
        "\n",
        "![制約付き量子オプティマイザーのワークフロー図](https://eu-de.quantum.cloud.ibm.com/docs/images/guides/aqarios-constrained-quantum-optimizer/cqo-diagram.svg)\n",
        "\n",
        "<span id=\"benchmarks\" />\n",
        "\n",
        "## ベンチマーク\n",
        "\n",
        "以下のベンチマーク結果から、Qiskitの「Constrained Quantum Optimizer」関数は、100をはるかに超える二値変数を持つ制約付き最適化問題に対して、高品質で実現可能な解を見出すことができることが示されています。 精度は、求まった目的関数値と既知の最適値との比率である。 実行時間は、関数の呼び出しから結果の返却までの実時間です。 QPU使用量は、課金対象となる量子コンピューティング時間です。\n",
        "\n",
        "2つの問題が検討された。すなわち、「 [最大独立集合](/docs/tutorials/find-the-maximum-independent-set-with-aqarios-constrained-quantum-optimizer) （MIS）」問題と、「最大 $k$ -カット」問題である。後者は、よく知られた「 MaxCut 」問題を2つ以上のカテゴリに拡張したものである。 Max- $k$ -Cutは、グラフ着色決定問題に相当する最適化問題でもあります（すべての辺が切断されたとき、そのグラフは $k$ -着色可能となります）。\n",
        "\n",
        "| 問題点                  | 変数  | 制約   | 量子ビット | 正確性    | 実現可能性 | 合計実行時間（秒） | QPU使用時間（秒） | シュート総数 |\n",
        "| -------------------- | --- | ---- | ----- | ------ | ----- | --------- | ---------- | ------ |\n",
        "| MIS es60fst02        | 186 | 280  | 124   | 100.0% | はい    | 940.2     | 147.0      | 25.0k  |\n",
        "| MIS sloane\\_2dc\\_128 | 128 | 5173 | 74    | 100.0% | はい    | 347.6     | 106.0      | 12.5k  |\n",
        "| Max-3-Cut 空手部        | 99  | 33   | 99    | 98.7%  | はい    | 279.5     | 166.0      | 25.0k  |\n",
        "| Max-4-Cut 空手部        | 132 | 33   | 132   | 100.0% | はい    | 258.3     | 200.0      | 25.0k  |\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5f761442",
      "metadata": {},
      "source": [
        "<span id=\"benchmark-notes\" />\n",
        "\n",
        "### ベンチマークの注意事項\n",
        "\n",
        "* 上記の結果は、Heron `ibm_marrakesh` r2 プロセッサ上で、デフォルトのオプションを設定し、を有効 `use_session` にした状態で得られたものです。 例えば `sloane_2dc_128` 、…が使用されました `total_shots=12500` 。\n",
        "* MISのインスタンスにおける量子ビット数の減少（変数数128および186に対して74および124）は、前処理における変数の固定を反映している。\n",
        "* MISの問題インスタンスは、 [Quantum Optimization Benchmarking](https://doi.org/10.1038/s43588-026-00991-1) Libraryから採用されている。- Max- $k$ -Cut問題のインスタンスは、色数が5である「 [Zachary Karate Club](https://en.wikipedia.org/wiki/Zachary%27s_karate_club) 」グラフである。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "73390a19",
      "metadata": {},
      "source": [
        "<span id=\"get-started\" />\n",
        "\n",
        "## 使用を開始する\n",
        "\n",
        "このガイドでは、Constrained Quantum Optimizer の関数を読み込み、簡単な問題を解く方法を示すことで、その基本的な使い方を解説します。 より詳細なチュートリアルについては、「 [Aqarios制約付き量子最適化ツールを使用した最大独立集合の探索](/docs/tutorials/find-the-maximum-independent-set-with-aqarios-constrained-quantum-optimizer)」 をご覧ください。\n",
        "\n",
        "IBM Quantum のAPIキーとインスタンス CRN を使用して認証を行い、カタログから関数を読み込んでください。\n",
        "\n",
        "<Admonition type=\"note\">\n",
        "  以下のコードは、認証情報を保存済みであることを前提としています。 設定を行うには、「 [IBM Cloud アカウントの認証情報を保存する](/docs/guides/functions-get-started#install-qiskit-functions-catalog-client) 」の手順に従ってください。\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "95a715d2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[QiskitFunction(aqarios/constrained-quantum-optimizer)]"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "catalog = QiskitFunctionsCatalog(channel=\"ibm_quantum_platform\")\n",
        "\n",
        "# Verify that you have access to the function\n",
        "catalog.list()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "fe865158",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Load the function\n",
        "optimizer = catalog.load(\"aqarios/constrained-quantum-optimizer\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "d976e101",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[<IBMBackend('ibm_pittsburgh')>,\n",
              " <IBMBackend('ibm_boston')>,\n",
              " <IBMBackend('ibm_phoenix')>,\n",
              " <IBMBackend('ibm_fez')>,\n",
              " <IBMBackend('ibm_miami')>,\n",
              " <IBMBackend('ibm_marrakesh')>,\n",
              " <IBMBackend('ibm_kingston')>]"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Check the list of backends you have access to\n",
        "catalog.backends()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "6b0f5c79",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Select the backend you want to use\n",
        "backend = catalog.backend(\"ibm_phoenix\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e4445979",
      "metadata": {},
      "source": [
        "<span id=\"example-1-a-simple-constrained-problem\" />\n",
        "\n",
        "## 例 1：単純な制約付き問題\n",
        "\n",
        "最初の例では、オペレーションズ・リサーチで一般的に用いられる最適化問題の仕様[であるLPファイル](https://www.ibm.com/docs/icos/22.1.1?topic=cplex-lp-file-format-algebraic-representation)を用いて、この関数をどのように使用するかを示しています。 5つの二値変数からなる以下の任意の最適化問題 $x_i \\in \\{0,1\\}$ を、2つの制約条件の下で定式化してください：\n",
        "\n",
        "$$\n",
        "    \\min x_1 x_2 + 2 x_2 x_3 - x_3 x_4 - 2 x_4 x_5 - 2 x_1 x_3 - 4 x_2 x_5 \\\\\n",
        "    \\text{s.t.}\\quad x_1 + x_2 + x_3 \\leq 1 \\\\\n",
        "    \\quad x_3 - x_4 + x_5 = 0\n",
        "$$\n",
        "\n",
        "<span id=\"1-formulate-the-problem\" />\n",
        "\n",
        "### 1. 問題の定式化\n",
        "\n",
        "数学式を、以下のLP文字列形式で直接記述してください：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "7c3af25d",
      "metadata": {
        "lines_to_next_cell": 0
      },
      "outputs": [],
      "source": [
        "lp_str = \"\"\"\\\\Problem name: Example\n",
        "Minimize\n",
        "  obj: [ 2 x_1 x_2 + 4 x_2 x_3 - 2 x_3 x_4 - 4 x_4 x_5 - 4 x_1 x_3 - 8 x_2 x_5 ] / 2\n",
        "Subject To\n",
        "  c1: x_1 + x_2 + x_3 <= 1\n",
        "  c2: x_3 - x_4 + x_5 = 0\n",
        "Binaries\n",
        "  x_1 x_2 x_3 x_4 x_5\n",
        "End\n",
        "\"\"\""
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f6c75f9d",
      "metadata": {},
      "source": [
        "なお、 は LP の標準規格において、二次目的関数に必須の表記である `[...] / 2` ことに留意されたい。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "003a933c",
      "metadata": {},
      "source": [
        "<span id=\"2-run-the-optimizer\" />\n",
        "\n",
        "### 2. オプティマイザーを実行する\n",
        "\n",
        "オプティマイザーを使って問題を解決してください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "242f1f89",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Job ID: 2e06a3a8-7c29-4c76-94d7-194293363f4a\n"
          ]
        }
      ],
      "source": [
        "# Set up low-resource options for the simple problem\n",
        "options = {\"total_shots\": 2000, \"num_parallel\": 5, \"use_session\": True}\n",
        "\n",
        "# Dispatch the job\n",
        "job_1 = optimizer.run(\n",
        "    problem=lp_str, backend_name=backend.name, options=options\n",
        ")\n",
        "\n",
        "print(f\"Job ID: {job_1.job_id}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "4bd4790a",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'RUNNING: WAITING_FOR_QPU'"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Monitor the job status\n",
        "job_1.status()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "acff0671",
      "metadata": {
        "lines_to_next_cell": 0
      },
      "source": [
        "<span id=\"3-retrieve-the-result\" />\n",
        "\n",
        "### 3. 結果を取得する\n",
        "\n",
        "変数名とそれに対応する代入値を関連付けるという解決策は、結果によって示されています。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "6a121188",
      "metadata": {
        "lines_to_next_cell": 0
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "{'solutions': [{'x_1': 0, 'x_2': 1, 'x_3': 0, 'x_4': 1, 'x_5': 1}],\n",
              " 'solution_bitstrings': ['01011'],\n",
              " 'raw_energy': -6.0,\n",
              " 'objective_value': -6.0,\n",
              " 'feasible': True,\n",
              " 'metadata': {'resource_usage': {'RUNNING: MAPPING': {'CPU': 5.405},\n",
              "   'RUNNING: OPTIMIZING_FOR_HARDWARE': {'CPU': 9.902},\n",
              "   'RUNNING: WAITING_FOR_QPU': {'CPU': 25.456},\n",
              "   'RUNNING: EXECUTING_QPU': {'CPU': 25.202},\n",
              "   'RUNNING: POST_PROCESSING': {'CPU': 6.481}},\n",
              "  'circuit_metrics': {'before_transpilation': {'num_qubits': 6,\n",
              "    'gate_count': 42,\n",
              "    'depth': 15,\n",
              "    'two_qubit_gate_count': 12,\n",
              "    'two_qubit_gate_depth': 7,\n",
              "    'operations': {'rz': 12,\n",
              "     'p': 8,\n",
              "     'ry': 7,\n",
              "     'rzz': 4,\n",
              "     'cx': 3,\n",
              "     'xx_plus_yy': 3,\n",
              "     'global_phase': 2,\n",
              "     'cry': 2,\n",
              "     'x': 1}},\n",
              "   'after_transpilation': {'num_qubits': 6,\n",
              "    'gate_count': 254,\n",
              "    'depth': 100,\n",
              "    'two_qubit_gate_count': 48,\n",
              "    'two_qubit_gate_depth': 33,\n",
              "    'operations': {'rz': 78, 'sx': 122, 'cz': 48, 'measure': 6, 'x': 0}}},\n",
              "  'solver_info': {'variable_mapping': {'x_1': 0,\n",
              "    'x_2': 1,\n",
              "    'x_3': 2,\n",
              "    'x_4': 3,\n",
              "    'x_5': 4}}}}"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "result = job_1.result()\n",
        "\n",
        "result"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e8837f5f",
      "metadata": {},
      "source": [
        "リターン辞書のこのフィールド `solutions` には、見つかったすべての縮退した最適解が、各変数名とその代入値を対応付ける辞書として格納されています。 これらの解は、ビット文字列としても返されます。 `solution_bitstrings`; を使用すると、ビット文字列のどの文字位置がどの変数に対応しているかがわかります `metadata.solver_info.variable_mapping` 。 ソリューションデータに加え、 `objective_value`、フラグ `feasible` 、および追加のデータ `metadata` が提供されています。\n",
        "\n",
        "<span id=\"example-2-maximum-independent-set\" />\n",
        "\n",
        "## 例 2：最大独立集合\n",
        "\n",
        "最大独立集合（MIS）問題とは、グラフ内の頂点の最大の部分集合で、その部分集合内のどの2つの頂点も辺を共有しないものを求める問題である。 この例では、12ノードの正則グラフ上でMISを解きます。 この問題に関する詳細や、より大規模な例については、 [チュートリアル](/docs/tutorials/find-the-maximum-independent-set-with-aqarios-constrained-quantum-optimizer)を参照してください。\n",
        "\n",
        "この問題は、 [qiskit-addon-opt-mapper](https://github.com/qiskit/qiskit-addon-opt-mapper) を使用して構築されています。\n",
        "必要に応じて、必要なパッケージをインストールしてください：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "a1e2f301",
      "metadata": {},
      "outputs": [],
      "source": [
        "# %pip install networkx qiskit-addon-opt-mapper"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d56e1440",
      "metadata": {},
      "source": [
        "<span id=\"step-1-define-the-problem\" />\n",
        "\n",
        "### ステップ1：問題を明確にする\n",
        "\n",
        "ランダムな3-正則グラフを構築し、MIS最適化問題を定式化する。 各グラフのノードは二値変数となり、各辺は、その両端点のうち最大1つだけが選択されることを保証する制約を導入する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "03998691",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\\ This file has been generated by DOcplex\n",
            "\\ ENCODING=ISO-8859-1\n",
            "\\Problem name: Independent set\n",
            "\n",
            "Maximize\n",
            " obj: x_0 + x_1 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7 + x_8 + x_9 + x_10 + x_11\n",
            "Subject To\n",
            " c0: x_0 + x_4 <= 1\n",
            " c1: x_0 + x_9 <= 1\n",
            " c2: x_0 + x_8 <= 1\n",
            " c3: x_1 + x_2 <= 1\n",
            " c4: x_1 + x_7 <= 1\n",
            " c5: x_1 + x_3 <= 1\n",
            " c6: x_2 + x_4 <= 1\n",
            " c7: x_2 + x_11 <= 1\n",
            " c8: x_3 + x_10 <= 1\n",
            " c9: x_3 + x_11 <= 1\n",
            " c10: x_4 + x_5 <= 1\n",
            " c11: x_5 + x_10 <= 1\n",
            " c12: x_5 + x_6 <= 1\n",
            " c13: x_6 + x_8 <= 1\n",
            " c14: x_6 + x_7 <= 1\n",
            " c15: x_7 + x_9 <= 1\n",
            " c16: x_8 + x_11 <= 1\n",
            " c17: x_9 + x_10 <= 1\n",
            "\n",
            "Bounds\n",
            " 0 <= x_0 <= 1\n",
            " 0 <= x_1 <= 1\n",
            " 0 <= x_2 <= 1\n",
            " 0 <= x_3 <= 1\n",
            " 0 <= x_4 <= 1\n",
            " 0 <= x_5 <= 1\n",
            " 0 <= x_6 <= 1\n",
            " 0 <= x_7 <= 1\n",
            " 0 <= x_8 <= 1\n",
            " 0 <= x_9 <= 1\n",
            " 0 <= x_10 <= 1\n",
            " 0 <= x_11 <= 1\n",
            "\n",
            "Binaries\n",
            " x_0 x_1 x_2 x_3 x_4 x_5 x_6 x_7 x_8 x_9 x_10 x_11\n",
            "End\n",
            "\n"
          ]
        }
      ],
      "source": [
        "import networkx as nx\n",
        "from qiskit_addon_opt_mapper.applications import IndependentSet\n",
        "from qiskit_addon_opt_mapper.translators import to_docplex_mp\n",
        "\n",
        "# 12-node random 3-regular graph\n",
        "G = nx.random_regular_graph(3, 12, seed=7)\n",
        "\n",
        "# Build MIS problem and export as LP string\n",
        "mis = IndependentSet(G)\n",
        "mis_problem = mis.to_optimization_problem()\n",
        "lp_str = to_docplex_mp(mis_problem).export_as_lp_string()\n",
        "\n",
        "print(lp_str)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e6f7a8b9",
      "metadata": {
        "lines_to_next_cell": 0
      },
      "source": [
        "<span id=\"step-2-run-the-optimizer\" />\n",
        "\n",
        "### ステップ 2：オプティマイザーを実行する\n",
        "\n",
        "オプティマイザーを使って問題を解決してください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "04236c83",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Job ID: f041431c-b42e-4627-afe5-522fea61faf6\n"
          ]
        }
      ],
      "source": [
        "options = {\"total_shots\": 2000, \"use_session\": True}\n",
        "\n",
        "# Dispatch the job\n",
        "job_2 = optimizer.run(\n",
        "    problem=lp_str, backend_name=backend.name, options=options\n",
        ")\n",
        "\n",
        "print(f\"Job ID: {job_2.job_id}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "079ebc2f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'QUEUED'"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Monitor the job status\n",
        "job_2.status()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "90c6de7c",
      "metadata": {},
      "source": [
        "<span id=\"step-3-retrieve-and-interpret-results\" />\n",
        "\n",
        "### ステップ3：結果の取得と解釈\n",
        "\n",
        "最後に、解を求め、その正しさを検証します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "f1a2b3c4",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Feasible: True\n",
            "Independent set size: 5\n",
            "Selected nodes: [1, 4, 6, 9, 11]\n",
            "Edge conflicts: []\n"
          ]
        }
      ],
      "source": [
        "result = job_2.result()\n",
        "\n",
        "print(f\"Feasible: {result['feasible']}\")\n",
        "print(f\"Independent set size: {int(result['objective_value'])}\")\n",
        "\n",
        "# Extract the selected nodes\n",
        "solution = result[\"solutions\"][0]\n",
        "independent_set = [\n",
        "    int(k.split(\"_\")[1]) for k, v in solution.items() if v == 1\n",
        "]\n",
        "print(f\"Selected nodes: {sorted(independent_set)}\")\n",
        "\n",
        "# Verify no two selected nodes share an edge\n",
        "conflicts = [\n",
        "    (u, v)\n",
        "    for u, v in G.edges()\n",
        "    if u in independent_set and v in independent_set\n",
        "]\n",
        "print(f\"Edge conflicts: {conflicts}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a2b3c4d5",
      "metadata": {},
      "source": [
        "<span id=\"example-3-graph-3-coloring-max-3-cut\" />\n",
        "\n",
        "## 例 3：グラフの 3 色塗り（ Max-3-Cut ）\n",
        "\n",
        "「最大- $k$ -Cut問題」とは、グラフの頂点を $k$ つのグループに分割し、端点が異なるグループに属する辺の数を最大化する問題である。 $k = 3$ の場合、これは、異色辺の数を最大化する 3 色着色を見つけることと同等である。\n",
        "\n",
        "形式的には、各ノード $i \\in V$ を、二値変数 $x_{i,c}$ （色 $c \\in \\{1, \\ldots, k\\}$ ）を持つ $k$ のグループのいずれかに割り当てます。各ノードに対するワンホット制約 $\\sum_c x_{i,c} = 1$ により、一意な割り当てが保証されます。 この目的関数は、グループ間のエッジの数を最大化する：\n",
        "\n",
        "$$\n",
        "\\min \\sum_{(u,v) \\in E} \\sum_c x_{u,c} \\, x_{v,c}\\\\\n",
        "\\text{s.t.} \\sum_{c} x_{i,c} = 1 \\quad \\forall i \\in  V\n",
        "$$\n",
        "\n",
        "ワンホット制約は、最適化ツールがネイティブに処理するXYミキサーに最適です。\n",
        "\n",
        "この例では、 [ザカリー空手クラブのグラフ](https://en.wikipedia.org/wiki/Zachary%27s_karate_club) （34ノード、78エッジ）を使用し、 [Luna Model](https://docs.aqarios.com/luna-model/) を用いてモデルを構築します。\n",
        "必要に応じて、必要なパッケージをインストールしてください：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "b3c4d5e6",
      "metadata": {},
      "outputs": [],
      "source": [
        "# %pip install networkx matplotlib luna-model"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c4d5e6f7",
      "metadata": {},
      "source": [
        "<span id=\"step-1-define-the-problem\" />\n",
        "\n",
        "### ステップ1：問題を明確にする\n",
        "\n",
        "まず、パッケージ `luna-model` を使用して二値変数を生成します。 次に、目的関数を定義し、制約条件をモデルに追加します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "d5e6f7a8",
      "metadata": {},
      "outputs": [],
      "source": [
        "import networkx as nx\n",
        "from luna_model import Model, quicksum\n",
        "\n",
        "k = 3\n",
        "G = nx.karate_club_graph()\n",
        "\n",
        "# Instantiate the Model object\n",
        "model = Model(name=\"Max-3-Cut\")\n",
        "\n",
        "# Add binary variables\n",
        "x = model.add_variables(\"x\", shape=(G.number_of_nodes(), k))\n",
        "\n",
        "# Add the objective by using the numpy dot abstraction\n",
        "model.objective = quicksum(x[i].dot(x[j]) for i, j in G.edges)\n",
        "\n",
        "# Bulk-add the one-hot constraints\n",
        "model.add_constraints(x.sum(axis=1) == 1)\n",
        "\n",
        "# Encode the model to send via API\n",
        "model_enc = model.encode_b64()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "263ccb5d",
      "metadata": {
        "lines_to_next_cell": 0
      },
      "source": [
        "<span id=\"step-2-run-the-optimizer\" />\n",
        "\n",
        "### ステップ 2：オプティマイザーを実行する\n",
        "\n",
        "オプティマイザーを使って問題を解決してください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f7a8b9c0",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Job ID: df911d83-9df7-44a1-bfad-5d66e08676c3\n"
          ]
        }
      ],
      "source": [
        "options = {\"use_session\": True}\n",
        "\n",
        "# Dispatch the job\n",
        "job_3 = optimizer.run(\n",
        "    problem=model_enc, backend_name=backend.name, options=options\n",
        ")\n",
        "\n",
        "print(f\"Job ID: {job_3.job_id}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "e2ff9b51",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'RUNNING: WAITING_FOR_QPU'"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Monitor the job status\n",
        "job_3.status()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a8b9c0d1",
      "metadata": {},
      "source": [
        "<span id=\"step-3-retrieve-and-visualize-results\" />\n",
        "\n",
        "### ステップ3：結果の取得と可視化\n",
        "\n",
        "結果を取得し、可視化します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "b9c0d1e2",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Feasible: True\n",
            "Violations: 4\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/aqarios-constrained-quantum-optimizer/extracted-outputs/b9c0d1e2-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "result = job_3.result()\n",
        "solution = result[\"solutions\"][0]\n",
        "\n",
        "# Map each node to its assigned color group\n",
        "node_group = {}\n",
        "for i in G.nodes:\n",
        "    for c in range(k):\n",
        "        if solution[f\"x{i},{c}\"] == 1:\n",
        "            node_group[i] = c\n",
        "\n",
        "print(f\"Feasible: {result['feasible']}\")\n",
        "print(f\"Violations: {int(result['objective_value'])}\")\n",
        "\n",
        "# Visualize the partition\n",
        "colors = [\"tab:blue\", \"tab:orange\", \"tab:green\"]\n",
        "node_colors = [colors[node_group[i]] for i in G.nodes()]\n",
        "nx.draw(G, nx.kamada_kawai_layout(G), node_color=node_colors, node_size=200)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3f1a7c02",
      "metadata": {},
      "source": [
        "<span id=\"changelog\" />\n",
        "\n",
        "## 変更ログ\n",
        "\n",
        "<span id=\"[040]---2026-09-22\" />\n",
        "\n",
        "### \\[0.4.0] - 2026年9月22日\n",
        "\n",
        "**最新の変更**\n",
        "\n",
        "* 入力パラメータの名前を `model` に変更しました `problem`。\n",
        "* 出力フィールドの名前を `obj_value` に変更しました `objective_value`。\n",
        "* オプション `postprocessing` を に置き換えました `postprocessing_level`。これは、文字列の `[0, 3]` 代わりに 範囲の整数を受け取ります。 以前の値は、 `\"off\"` -> `0`、 `\"weak\"` -> `1`、 `\"medium\"` -> `2`、および `\"strong\"` -> に対応しており `3`、デフォルト値は のまま変更されていません `3`。\n",
        "* 再編成されました `metadata.circuit_metrics`。 現在では `num_qubits`、平均化されたゲート数の単一のフラットな辞書ではなく `after_transpilation`、 `before_transpilation` とについて、 `gate_count`、 `depth`、 `two_qubit_gate_count`、 `two_qubit_gate_depth`、、を個 `operations` 別に報告するようになっている。 このフィールドは、前処理の段階で問題が解決され、回路の実行が行われなかった `None` 場合（エラーコード `4712`）に設定されます。\n",
        "\n",
        "**特徴**\n",
        "\n",
        "* 実行ごとに回路合成と配線の再現性を確保するためのオプション `seed_transpiler` を追加しました。\n",
        "* この関数が送信するすべての Qiskit Runtime ジョブに、独自のタグを付与するオプション `job_tags` を追加しました。\n",
        "* 出力フィールドを追加しました `solution_bitstrings`。これは、と同じ解をビット列形式 `solutions` で返します。\n",
        "* 各変数名を `metadata.solver_info.variable_mapping`、のエントリ内でのその文字位置にマッピングするを追加しました `solution_bitstrings`。\n",
        "\n",
        "**資料**\n",
        "\n",
        "* 連続（実数値）変数はサポートされていないこと、および整数変数には明示的な境界を指定する必要があることが記載されています。 このようなモデルでは、エラーコード が表示され、処理が失敗します `4710`。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e9ec2e67",
      "metadata": {},
      "source": [
        "<span id=\"get-support\" />\n",
        "\n",
        "## サポートの利用\n",
        "\n",
        "ご質問や問題がある場合は、ジョブIDを明記の上、 [support@aqarios.com](mailto:support@aqarios.com) までご連絡ください。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5a6a25c8",
      "metadata": {
        "jp-MarkdownHeadingCollapsed": true
      },
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 次のステップ\n",
        "\n",
        "<Admonition type=\"tip\" title=\"推奨事項\">\n",
        "  * [Aqarios社の「Constrained Quantum Optimizer」へのアクセス権を申請してください](https://aqarios.com/qiskit-function-access/)。\n",
        "  * パラメータおよび出力の詳細については、 [APIリファレンス](/docs/api/functions/aqarios-constrained-quantum-optimizer)をご覧ください。\n",
        "  * 「 [Aqarios制約付き量子オプティマイザーを用いた最大独立集合の探索](/docs/tutorials/find-the-maximum-independent-set-with-aqarios-constrained-quantum-optimizer) 」チュートリアルを試して、実際のQOBLIBベンチマーク事例について詳しく学びましょう。\n",
        "  * 論文「 [反復ウォームスタートXYミキサーを用いた制約付き量子最適化](https://doi.org/10.1088/1367-2630/ae8ea2)」 を参照してください。\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6c0a20cb",
      "metadata": {},
      "source": [
        "<span id=\"references\" />\n",
        "\n",
        "## 参照\n",
        "\n",
        "1. Bucher ら (2026)、 \\*反復ウォームスタートXYミキサーを用いた制約付き量子最適化 \\*[10.1088/1367-2630/ae8ea2](https://doi.org/10.1088/1367-2630/ae8ea2)\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
}