{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "492d7cec",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"CHSH不等式\"\n",
        "description: \"量子コンピュータ上で実験を実行し、Estimatorプリミティブを用いてCHSH不等式の違反を実証する。\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore zorder Tsirelson */}\n",
        "\n",
        "<span id=\"chsh-inequality\" />\n",
        "\n",
        "# CHSH不等式\n",
        "\n",
        "*推定所要時間：Heron r3 プロセッサで 2 分（注：これはあくまで目安です。 （実行時間は異なる場合があります。）*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a57d9139",
      "metadata": {},
      "source": [
        "<span id=\"learning-outcomes\" />\n",
        "\n",
        "## 学習成果\n",
        "\n",
        "このチュートリアルを修了すると、以下の内容を理解できるようになります：\n",
        "\n",
        "* パラメータ化されたベル状態CHSH回路を構築し、CHSH証人を構成する4つの期待値を測定する方法。\n",
        "* プリミティブを [`EstimatorV2`](/docs/api/qiskit-ibm-runtime/estimator-v2) 1 回呼び出すだけで、パラメータスイープにおける複数の観測量の期待値を計算する方法。\n",
        "* ハードウェアに送信する前に、 `AerSimulator.from_backend` ノイズの多いローカルシミュレータ上で量子ワークフローを検証する方法。\n",
        "* IBM Quantum® ハードウェア上で多数の独立したベル対を並列に実行することにより、CHSH実験をデバイス全体のエンタングルメントベンチマークへと拡張する方法。\n",
        "\n",
        "<span id=\"prerequisites\" />\n",
        "\n",
        "## 前提条件\n",
        "\n",
        "以下のトピックについて、あらかじめ理解しておくことをお勧めします：\n",
        "\n",
        "* 「 [エンタングルメントの実演](/learning/courses/basics-of-quantum-information/entanglement-in-action/chsh-game) 」――ベル状態とCHSHゲームに関する講義。\n",
        "* [`SparsePauliOp`](/docs/api/qiskit/qiskit.quantum_info.SparsePauliOp) そして、『 Qiskit primitives 』 [の紹介](/docs/guides/primitives)。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f956eda1",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## 背景\n",
        "\n",
        "このチュートリアルでは、量子コンピューター上で実験を行い、Estimatorプリミティブを用いたCHSH不等式の違反を実証します。\n",
        "\n",
        "クラウザー、ホーン、シモニー、ホルトにちなんで名付けられたCHSH不等式は、ベルの定理（1969年）を実験的に検証するために用いられる。 この定理は、局所的な隠れ変数理論では、量子力学における量子もつれの一部の帰結を説明できないと主張している。 CHSH不等式の違反を実証することは、量子力学が局所隠変数理論と両立しないことを示しており、この実験は量子力学の理解における基礎となるものである。\n",
        "\n",
        "2022年のノーベル物理学賞は、アラン・アスペクト、ジョン・クラウザー、アントン・ツァイリンガーの3名に授与された。これは、量子情報科学における先駆的な研究、とりわけ、もつれ合った光子を用いた実験によりベルの不等式の破れを実証した功績などが評価されたものである。\n",
        "\n",
        "この実験では、もつれ状態のペアを作り出し、それぞれの量子ビットについて2つの異なる基底で測定を行います。 第1の量子ビットの基底を $A$ および $a$、第2の量子ビットの基底を $B$ および $b$ と表記する。これにより、CHSH量 $S_1$ を計算することができる：\n",
        "\n",
        "$$\n",
        "S_1 = A(B-b) + a(B+b).\n",
        "$$\n",
        "\n",
        "各観測値は、 $+1$ または $-1$ のいずれかである。明らかに、 $B\\pm b$ の項のうち一方は $0$ でなければならず、もう一方は $\\pm 2$ でなければならない。したがって、 $S_1 = \\pm 2$ となる。 $S_1$ の平均値は、次の不等式を満たさなければならない：\n",
        "\n",
        "$$\n",
        "|\\langle S_1 \\rangle|\\leq 2.\n",
        "$$\n",
        "\n",
        "$S_1$ を、 $A$、 $a$、 $B$、および $b$ を用いて展開すると、次のようになります：\n",
        "\n",
        "$$\n",
        "|\\langle S_1 \\rangle| = |\\langle AB \\rangle - \\langle Ab \\rangle + \\langle aB \\rangle + \\langle ab \\rangle| \\leq 2.\n",
        "$$\n",
        "\n",
        "別の CHSH 量を定義することができる $S_2$ ：\n",
        "\n",
        "$$\n",
        "S_2 = A(B+b) - a(B-b),\n",
        "$$\n",
        "\n",
        "これにより、別の不等式が導かれる：\n",
        "\n",
        "$$\n",
        "|\\langle S_2 \\rangle| = |\\langle AB \\rangle + \\langle Ab \\rangle - \\langle aB \\rangle + \\langle ab \\rangle| \\leq 2.\n",
        "$$\n",
        "\n",
        "もし量子力学が局所隠変数理論によって記述できるのであれば、これらの不等式は常に成り立つことになる。 このチュートリアルで示されたように、量子コンピュータ上ではこれらの条件が破られる可能性があるため、量子力学は局所隠変数理論とは両立しない。\n",
        "\n",
        "我々は、ベル状態 $|\\Phi^+\\rangle = \\frac{|00\\rangle + |11\\rangle}{\\sqrt{2}}$ を準備することで、もつれ対を生成する。Estimatorプリミティブを用いることで、生カウント値から再構築することなく、期待値 $\\langle AB \\rangle, \\langle Ab \\rangle, \\langle aB \\rangle$ および $\\langle ab \\rangle$ を直接求めることができる。 $Z$ および $X$ の基底において、2番目の量子ビットを測定する。 最初の量子ビットも直交基底で測定されますが、回転角 $\\theta$ を $0$ と $2\\pi$ の間で掃引します。Estimatorプリミティブは、このパラメータ掃引を単一の[プリミティブ統合ブロック（ PUB ）](/docs/guides/primitive-input-output) で評価します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c7346a67",
      "metadata": {},
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## 要件\n",
        "\n",
        "このチュートリアルを始める前に、以下のものがインストールされていることを確認してください：\n",
        "\n",
        "* Qiskit SDK v2.0 またはそれ以降のバージョンで、 [可視化](/docs/api/qiskit/visualization)機能をサポートしたもの\n",
        "* Qiskit Runtime v0.40 またはそれ以降 (`pip install qiskit-ibm-runtime`)\n",
        "* Qiskit Aer v0.17 以降 (`pip install qiskit-aer`)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d5ffeb42",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## セットアップ\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "323b27db",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:49.177326Z",
          "iopub.status.busy": "2026-05-19T22:38:49.177203Z",
          "iopub.status.idle": "2026-05-19T22:38:49.804694Z",
          "shell.execute_reply": "2026-05-19T22:38:49.804154Z"
        }
      },
      "outputs": [],
      "source": [
        "# General\n",
        "import numpy as np\n",
        "\n",
        "# Qiskit imports\n",
        "from qiskit import QuantumCircuit\n",
        "from qiskit.circuit import Parameter\n",
        "from qiskit.quantum_info import SparsePauliOp\n",
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "\n",
        "# `qiskit-ibm-runtime` imports\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "from qiskit_ibm_runtime import EstimatorV2 as Estimator\n",
        "\n",
        "# Qiskit Aer for local noisy simulation\n",
        "from qiskit_aer import AerSimulator\n",
        "\n",
        "# Plotting routines\n",
        "import matplotlib.pyplot as plt\n",
        "import matplotlib.ticker as tck"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "fd284a0f",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:49.806301Z",
          "iopub.status.busy": "2026-05-19T22:38:49.806113Z",
          "iopub.status.idle": "2026-05-19T22:38:53.208796Z",
          "shell.execute_reply": "2026-05-19T22:38:53.208025Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "'ibm_pittsburgh'"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Select an IBM Quantum backend.\n",
        "service = QiskitRuntimeService()\n",
        "backend = service.least_busy(\n",
        "    min_num_qubits=127, operational=True, simulator=False\n",
        ")\n",
        "backend.name"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ca035271",
      "metadata": {},
      "source": [
        "<span id=\"small-scale-simulator-example\" />\n",
        "\n",
        "## 小規模シミュレータの例\n",
        "\n",
        "ハードウェアジョブを送信する前に、ローカルのノイズを含むシミュレータ上でワークフロー全体を検証します。 これを使用して `AerSimulator.from_backend(backend)` 、選択したバックエンドのノイズモデルとカップリングマップを継承するシミュレータを構築します。これにより、シミュレータの応答は、ハードウェアから予想される応答と質的に類似したものとなります。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0539a796",
      "metadata": {},
      "source": [
        "<span id=\"step-1-map-classical-inputs-to-a-quantum-problem\" />\n",
        "\n",
        "### ステップ1：古典的な入力を量子問題にマッピングする\n",
        "\n",
        "CHSH回路は、第1の量子ビットの測定基底を掃引する単一のパラメータ $\\theta$ を用いて記述する。 このプリミティブは [`Estimator`](/docs/api/qiskit-ibm-runtime/estimator-v2) 解析を簡素化します。観測量の期待値を直接返すほか、1回の呼び出しで、パラメータ化された回路を多くのパラメータ値について評価することができます。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "c3f57d25",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:53.210931Z",
          "iopub.status.busy": "2026-05-19T22:38:53.210786Z",
          "iopub.status.idle": "2026-05-19T22:38:53.349189Z",
          "shell.execute_reply": "2026-05-19T22:38:53.348782Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/chsh-inequality/extracted-outputs/c3f57d25-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "theta = Parameter(r\"$\\theta$\")\n",
        "\n",
        "chsh_circuit = QuantumCircuit(2)\n",
        "chsh_circuit.h(0)\n",
        "chsh_circuit.cx(0, 1)\n",
        "chsh_circuit.ry(theta, 0)\n",
        "chsh_circuit.draw(output=\"mpl\", idle_wires=False, style=\"iqp\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "af999dde",
      "metadata": {},
      "source": [
        "次に、パラメータ化された回路を評価するための、 $0$ から $2\\pi$ までの 21 個の位相値のリストを作成します（ $0$、 $0.1\\pi$、 $0.2\\pi$、...、 $1.9\\pi$、 $2\\pi$ ）。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "9d587e2f",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:53.350400Z",
          "iopub.status.busy": "2026-05-19T22:38:53.350337Z",
          "iopub.status.idle": "2026-05-19T22:38:53.352045Z",
          "shell.execute_reply": "2026-05-19T22:38:53.351729Z"
        }
      },
      "outputs": [],
      "source": [
        "number_of_phases = 21\n",
        "phases = np.linspace(0, 2 * np.pi, number_of_phases)\n",
        "# Phases need to be expressed as a list of lists for the Estimator PUB\n",
        "individual_phases = [[ph] for ph in phases]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "af917afb",
      "metadata": {},
      "source": [
        "最後に、観測量について定義する。 最初の量子ビットは、 $\\theta$ だけ回転した軸に沿って測定され、2番目の量子ビットは $Z$ および $X$ で測定される。これらの選択により、4つのCHSH相関関数は、パウリ演算子 $ZZ$、 $ZX$、 $XZ$、および $XX$ に対応する：\n",
        "\n",
        "$$\n",
        "\\langle S_1 \\rangle = \\langle ZZ \\rangle - \\langle ZX \\rangle + \\langle XZ \\rangle + \\langle XX \\rangle,\n",
        "$$\n",
        "\n",
        "$$\n",
        "\\langle S_2 \\rangle = \\langle ZZ \\rangle + \\langle ZX \\rangle - \\langle XZ \\rangle + \\langle XX \\rangle.\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "21ae6238",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:53.353007Z",
          "iopub.status.busy": "2026-05-19T22:38:53.352948Z",
          "iopub.status.idle": "2026-05-19T22:38:53.355217Z",
          "shell.execute_reply": "2026-05-19T22:38:53.354857Z"
        }
      },
      "outputs": [],
      "source": [
        "# <S_1> = <ZZ> - <ZX> + <XZ> + <XX>\n",
        "observable1 = SparsePauliOp.from_list(\n",
        "    [(\"ZZ\", 1), (\"ZX\", -1), (\"XZ\", 1), (\"XX\", 1)]\n",
        ")\n",
        "\n",
        "# <S_2> = <ZZ> + <ZX> - <XZ> + <XX>\n",
        "observable2 = SparsePauliOp.from_list(\n",
        "    [(\"ZZ\", 1), (\"ZX\", 1), (\"XZ\", -1), (\"XX\", 1)]\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2d571aa2",
      "metadata": {},
      "source": [
        "<span id=\"step-2-optimize-problem-for-quantum-hardware-execution\" />\n",
        "\n",
        "### ステップ2：量子ハードウェア実行に向けた問題の最適化\n",
        "\n",
        "V2 プリミティブは、ターゲットシステムがサポートする命令および接続性（命令セットアーキテクチャ、すなわちISA、回路およびオブザーバブル）に準拠した回路およびオブザーバブルのみを受け入れます。 バックエンドからを `AerSimulator` 構築し、シミュレータのターゲットに合わせてトランスパイルを行うことで、同じパスマネージャーがエンドツーエンドで実行されるようにしています。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "3e139a89",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:53.356197Z",
          "iopub.status.busy": "2026-05-19T22:38:53.356140Z",
          "iopub.status.idle": "2026-05-19T22:38:56.713188Z",
          "shell.execute_reply": "2026-05-19T22:38:56.712683Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/chsh-inequality/extracted-outputs/3e139a89-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Build a noisy simulator from the ibm_pittsburgh backend\n",
        "aer_sim = AerSimulator.from_backend(backend)\n",
        "\n",
        "pm = generate_preset_pass_manager(target=aer_sim.target, optimization_level=3)\n",
        "chsh_isa_circuit = pm.run(chsh_circuit)\n",
        "chsh_isa_circuit.draw(output=\"mpl\", idle_wires=False, style=\"iqp\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2817b069",
      "metadata": {},
      "source": [
        "`SparsePauliOp.apply_layout`また、. を使用して、トランスパイルされた回路の量子ビット配置に合わせて観測可能量を変換します。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "d1faa7ab",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:56.714405Z",
          "iopub.status.busy": "2026-05-19T22:38:56.714288Z",
          "iopub.status.idle": "2026-05-19T22:38:56.716319Z",
          "shell.execute_reply": "2026-05-19T22:38:56.715992Z"
        }
      },
      "outputs": [],
      "source": [
        "isa_observable1 = observable1.apply_layout(layout=chsh_isa_circuit.layout)\n",
        "isa_observable2 = observable2.apply_layout(layout=chsh_isa_circuit.layout)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e734572e",
      "metadata": {},
      "source": [
        "<span id=\"step-3-execute-using-qiskit-primitives\" />\n",
        "\n",
        "### ステップ3: `Qiskit primitives`を使用して実行する\n",
        "\n",
        "モードで `aer_sim``EstimatorV2` パラメータスイープを実行します。 Estimator `run()` メソッドは、PUB の反復可能オブジェクトを受け取ります。 `(circuit, observables, parameter_values, precision)`各 PUB は、以下の形式をとります。 両方のオブザーバブルを一緒に渡すことで、同じパラメータスイープを共有するようにします。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "7f954aeb",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:56.717549Z",
          "iopub.status.busy": "2026-05-19T22:38:56.717473Z",
          "iopub.status.idle": "2026-05-19T22:38:58.217539Z",
          "shell.execute_reply": "2026-05-19T22:38:58.217000Z"
        }
      },
      "outputs": [],
      "source": [
        "# Use the AerSimulator-backed Estimator to validate the workflow locally\n",
        "estimator_sim = Estimator(mode=aer_sim)\n",
        "\n",
        "pub = (\n",
        "    chsh_isa_circuit,  # ISA circuit\n",
        "    [[isa_observable1], [isa_observable2]],  # ISA observables\n",
        "    individual_phases,  # Parameter values\n",
        ")\n",
        "\n",
        "sim_result = estimator_sim.run(pubs=[pub]).result()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9c5230fc",
      "metadata": {},
      "source": [
        "<span id=\"step-4-post-process-and-return-result-in-desired-classical-format\" />\n",
        "\n",
        "### ステップ4：後処理を行い、結果を希望の古典形式で返す\n",
        "\n",
        "Estimator は、両方の観測変数について期待値を返します。 これらを $\\theta$ に対して、従来の境界値（ $\\pm 2$ ）およびツィレルソン境界値（ $\\pm 2\\sqrt{2}$ ）とともにプロットした。灰色の塗りつぶし部分は、この2つの間の差を示している。 これらの帯域内に位置する点は、CHSH不等式に反する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "c8fd5140",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:58.219407Z",
          "iopub.status.busy": "2026-05-19T22:38:58.219306Z",
          "iopub.status.idle": "2026-05-19T22:38:58.285202Z",
          "shell.execute_reply": "2026-05-19T22:38:58.284609Z"
        }
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/chsh-inequality/extracted-outputs/c8fd5140-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "chsh1_sim = sim_result[0].data.evs[0]\n",
        "chsh2_sim = sim_result[0].data.evs[1]\n",
        "\n",
        "\n",
        "def plot_chsh(phases, chsh1, chsh2, title):\n",
        "    fig, ax = plt.subplots(figsize=(10, 6))\n",
        "\n",
        "    ax.plot(\n",
        "        phases / np.pi, chsh1, \"o-\", label=r\"$\\langle S_1 \\rangle$\", zorder=3\n",
        "    )\n",
        "    ax.plot(\n",
        "        phases / np.pi, chsh2, \"o-\", label=r\"$\\langle S_2 \\rangle$\", zorder=3\n",
        "    )\n",
        "\n",
        "    # classical bound +-2\n",
        "    ax.axhline(y=2, color=\"0.9\", linestyle=\"--\")\n",
        "    ax.axhline(y=-2, color=\"0.9\", linestyle=\"--\")\n",
        "\n",
        "    # quantum bound, +-2*sqrt(2)\n",
        "    ax.axhline(y=np.sqrt(2) * 2, color=\"0.9\", linestyle=\"-.\")\n",
        "    ax.axhline(y=-np.sqrt(2) * 2, color=\"0.9\", linestyle=\"-.\")\n",
        "    ax.fill_between(phases / np.pi, 2, 2 * np.sqrt(2), color=\"0.6\", alpha=0.7)\n",
        "    ax.fill_between(\n",
        "        phases / np.pi, -2, -2 * np.sqrt(2), color=\"0.6\", alpha=0.7\n",
        "    )\n",
        "\n",
        "    ax.xaxis.set_major_formatter(tck.FormatStrFormatter(\"%g $\\\\pi$\"))\n",
        "    ax.xaxis.set_major_locator(tck.MultipleLocator(base=0.5))\n",
        "\n",
        "    ax.set_xlabel(r\"$\\theta$\")\n",
        "    ax.set_ylabel(\"CHSH witness\")\n",
        "    ax.set_title(title)\n",
        "    ax.legend()\n",
        "    plt.show()\n",
        "\n",
        "\n",
        "plot_chsh(\n",
        "    phases,\n",
        "    chsh1_sim,\n",
        "    chsh2_sim,\n",
        "    \"CHSH witnesses from AerSimulator (ibm_pittsburgh noise model)\",\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e9744b84",
      "metadata": {},
      "source": [
        "このシミュレータのCHSH値は、 $\\theta$ のいくつかの値において、バックエンドのノイズモデルを考慮した場合でも、すでに $\\pm 2$ という古典的な上限を超えている。 シミュレーションによるデバイスのノイズの影響により、ピーク値はツィレルソン境界値 $\\pm 2\\sqrt{2}$ にわずかに及ばない。 ワークフローの検証が完了したため、次は実際のハードウェアに移ります。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "747e948d",
      "metadata": {},
      "source": [
        "<span id=\"large-scale-hardware-example\" />\n",
        "\n",
        "## 大規模なハードウェアの例\n",
        "\n",
        "CHSHテストは本質的に *2量子ビット*の実験であるため、1つの回路を大きくしただけではスケーラビリティは向上しない。 その代わりに、 **多数のテストを並行して**実行することでスケーラビリティを確保しています。 ここでは、バックエンドの接続性が許す限り、互いに交わらないベル対をできるだけ多く配置し（結合マップの*マッチング* ）、各ペアに対して独立したCHSHサブ回路を実行します。これらすべてを単一のジョブ内で実行します。\n",
        "\n",
        "これにより、CHSHは**デバイス全体にわたるエンタングルメント品質のベンチマーク**となります。つまり、手作業で厳選された単一のペアではなく、チップの大部分にわたるエンタングルメントを一度に、すべてのペアが隣接するペアとのクロストークや並列ゲートエラーの影響を受けるという現実的な条件下で検証するのです。 すべてのペアについてこの不等式を*同時に*満たさないことは、デバイスのあらゆる場所で真の量子もつれが存在することを証明する。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "3376bc73",
      "metadata": {
        "execution": {
          "iopub.execute_input": "2026-05-19T22:38:58.286726Z",
          "iopub.status.busy": "2026-05-19T22:38:58.286656Z",
          "iopub.status.idle": "2026-05-19T22:38:59.198086Z",
          "shell.execute_reply": "2026-05-19T22:38:59.197690Z"
        }
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Tiling ibm_pittsburgh with 64 parallel Bell pairs (128 of 156 qubits)\n",
            "Job ID: d86efd5g7okc73el0rp0\n",
            "63/64 Bell pairs violated the CHSH inequality (mean peak witness 2.75, classical bound 2)\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/chsh-inequality/extracted-outputs/3376bc73-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# -------------------------Step 1: Map classical inputs to a quantum problem-------------------------\n",
        "# A CHSH test is bipartite, so we scale up by running one independent CHSH\n",
        "# experiment on every disjoint Bell pair the device can host. A greedy\n",
        "# matching of the coupling map gives a set of edges that share no qubits.\n",
        "num_qubits = backend.num_qubits\n",
        "used = set()\n",
        "pairs = []\n",
        "for qa, qb in backend.coupling_map.get_edges():\n",
        "    if qa not in used and qb not in used:\n",
        "        pairs.append((qa, qb))\n",
        "        used.update((qa, qb))\n",
        "num_pairs = len(pairs)\n",
        "print(\n",
        "    f\"Tiling {backend.name} with {num_pairs} parallel Bell pairs \"\n",
        "    f\"({2 * num_pairs} of {num_qubits} qubits)\"\n",
        ")\n",
        "\n",
        "# One parameterized CHSH sub-circuit per pair, all sharing the angle theta\n",
        "theta = Parameter(r\"$\\theta$\")\n",
        "chsh_circuit = QuantumCircuit(num_qubits)\n",
        "for qa, qb in pairs:\n",
        "    chsh_circuit.h(qa)\n",
        "    chsh_circuit.cx(qa, qb)\n",
        "    chsh_circuit.ry(theta, qa)\n",
        "\n",
        "# Embed the two CHSH observables onto each pair's qubits (identity elsewhere)\n",
        "obs1 = SparsePauliOp.from_list([(\"ZZ\", 1), (\"ZX\", -1), (\"XZ\", 1), (\"XX\", 1)])\n",
        "obs2 = SparsePauliOp.from_list([(\"ZZ\", 1), (\"ZX\", 1), (\"XZ\", -1), (\"XX\", 1)])\n",
        "observables = []\n",
        "for qa, qb in pairs:\n",
        "    observables.append([obs1.apply_layout([qa, qb], num_qubits)])\n",
        "    observables.append([obs2.apply_layout([qa, qb], num_qubits)])\n",
        "\n",
        "number_of_phases = 21\n",
        "phases = np.linspace(0, 2 * np.pi, number_of_phases)\n",
        "individual_phases = [[ph] for ph in phases]\n",
        "\n",
        "# -------------------------Step 2: Optimize problem for quantum hardware execution-------------------------\n",
        "pm = generate_preset_pass_manager(target=backend.target, optimization_level=3)\n",
        "chsh_isa_circuit = pm.run(chsh_circuit)\n",
        "isa_observables = [\n",
        "    [o[0].apply_layout(chsh_isa_circuit.layout)] for o in observables\n",
        "]\n",
        "\n",
        "# -------------------------Step 3: Execute using Qiskit primitives-------------------------\n",
        "estimator_hw = Estimator(mode=backend)\n",
        "estimator_hw.options.environment.job_tags = [\"TUT_CI\"]\n",
        "\n",
        "pub = (chsh_isa_circuit, isa_observables, individual_phases)\n",
        "job = estimator_hw.run(pubs=[pub])\n",
        "print(f\"Job ID: {job.job_id()}\")\n",
        "hw_result = job.result()\n",
        "\n",
        "# -------------------------Step 4: Post-process and return result in desired classical format-------------------------\n",
        "# evs has shape (2 * num_pairs, number_of_phases); rows alternate S1, S2\n",
        "evs = np.asarray(hw_result[0].data.evs)\n",
        "chsh1_all = evs[0::2]\n",
        "chsh2_all = evs[1::2]\n",
        "\n",
        "# A pair \"violates\" CHSH if its strongest witness exceeds the classical bound\n",
        "peak = np.maximum(\n",
        "    np.abs(chsh1_all).max(axis=1), np.abs(chsh2_all).max(axis=1)\n",
        ")\n",
        "n_violate = int(np.sum(peak > 2))\n",
        "print(\n",
        "    f\"{n_violate}/{num_pairs} Bell pairs violated the CHSH inequality \"\n",
        "    f\"(mean peak witness {peak.mean():.2f}, classical bound 2)\"\n",
        ")\n",
        "\n",
        "fig, ax = plt.subplots(figsize=(10, 6))\n",
        "\n",
        "# Faint individual per-pair curves\n",
        "for row in chsh1_all:\n",
        "    ax.plot(phases / np.pi, row, color=\"#1f77b4\", alpha=0.2, lw=1)\n",
        "for row in chsh2_all:\n",
        "    ax.plot(phases / np.pi, row, color=\"#ff7f0e\", alpha=0.2, lw=1)\n",
        "\n",
        "# Bold mean curves across all pairs\n",
        "ax.plot(\n",
        "    phases / np.pi,\n",
        "    chsh1_all.mean(axis=0),\n",
        "    color=\"#1f77b4\",\n",
        "    lw=2.5,\n",
        "    label=r\"$\\langle S_1 \\rangle$ (mean)\",\n",
        ")\n",
        "ax.plot(\n",
        "    phases / np.pi,\n",
        "    chsh2_all.mean(axis=0),\n",
        "    color=\"#ff7f0e\",\n",
        "    lw=2.5,\n",
        "    label=r\"$\\langle S_2 \\rangle$ (mean)\",\n",
        ")\n",
        "\n",
        "# classical bound +-2 and Tsirelson bound +-2*sqrt(2)\n",
        "ax.axhline(y=2, color=\"0.9\", linestyle=\"--\")\n",
        "ax.axhline(y=-2, color=\"0.9\", linestyle=\"--\")\n",
        "ax.axhline(y=np.sqrt(2) * 2, color=\"0.9\", linestyle=\"-.\")\n",
        "ax.axhline(y=-np.sqrt(2) * 2, color=\"0.9\", linestyle=\"-.\")\n",
        "ax.fill_between(phases / np.pi, 2, 2 * np.sqrt(2), color=\"0.6\", alpha=0.7)\n",
        "ax.fill_between(phases / np.pi, -2, -2 * np.sqrt(2), color=\"0.6\", alpha=0.7)\n",
        "\n",
        "ax.xaxis.set_major_formatter(tck.FormatStrFormatter(\"%g $\\\\pi$\"))\n",
        "ax.xaxis.set_major_locator(tck.MultipleLocator(base=0.5))\n",
        "ax.set_xlabel(r\"$\\theta$\")\n",
        "ax.set_ylabel(\"CHSH witness\")\n",
        "ax.set_title(\n",
        "    f\"CHSH witnesses for {num_pairs} parallel Bell pairs on {backend.name}\"\n",
        ")\n",
        "ax.legend()\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3c32f01c",
      "metadata": {},
      "source": [
        "薄い曲線は個々のベルペアを表し、太い曲線はデバイス全体におけるそれらの平均値を示しています。 どの対も、量子力学によって予測されるのと同じ正弦波を描いており、かすかな曲線間のばらつきは、対ごとに異なるノイズの変動を反映している。 曲線が灰色の帯に入る箇所はすべて、 $\\pm 2$ という古典的な境界線を越えていることを示しており、印刷された要約を見ると、実質的にすべてのペアが同時にCHSH不等式に違反していることが確認できる。\n",
        "\n",
        "ピーク値は、デバイスのノイズの影響により、ツィレルソン境界 $\\pm 2\\sqrt{2}$ には及ばないものの、結論は明白である。すなわち、バックエンドは、単一の厳選されたペアだけでなく、チップ全体にわたって同時に真のエンタングルメントを維持している。 CHSH実験が「スケールする」というのは、このような意味です。つまり、単一のより大規模な回路としてではなく、あらゆる場所で同時に量子もつれを証明する並列ベンチマークとして機能するということです。\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "86e635a3",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## 次のステップ\n",
        "\n",
        "<Admonition type=\"tip\" title=\"推奨事項\">\n",
        "  この作品に興味を持たれた方は、以下の資料もご参照ください：\n",
        "\n",
        "  * [エンタングルメントの実例](/learning/courses/basics-of-quantum-information/entanglement-in-action/chsh-game) ：ジョン・ワトラウスによるベル状態とCHSHゲームに関する講義。\n",
        "  * [「Estimatorプリミティブ」の使い方](/docs/guides/primitives) ：PUBとパラメータスイープに関するガイド。\n",
        "  * [量子ビット選択のためのリアルタイムベンチマーク](/docs/tutorials/real-time-benchmarking-for-qubit-selection) ：デバイス全体の量子ビットおよびエンタングルメントの品質を評価するもう一つの方法。\n",
        "  * [`SparsePauliOp` APIリファレンス](/docs/api/qiskit/qiskit.quantum_info.SparsePauliOp)。\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"
    },
    "hours": 1,
    "qpuSeconds": 120
  },
  "nbformat": 4,
  "nbformat_minor": 5
}