CHSH不等式
推定所要時間:Heron r3 プロセッサで 2 分(注:これはあくまで目安です。 (実行時間は異なる場合があります。)
学習成果
このチュートリアルを修了すると、以下の内容を理解できるようになります:
- パラメータ化されたベル状態CHSH回路を構築し、CHSH証人を構成する4つの期待値を測定する方法。
- プリミティブを
EstimatorV21 回呼び出すだけで、パラメータスイープにおける複数の観測量の期待値を計算する方法。 - ハードウェアに送信する前に、
AerSimulator.from_backendノイズの多いローカルシミュレータ上で量子ワークフローを検証する方法。 - IBM Quantum® ハードウェア上で多数の独立したベル対を並列に実行することにより、CHSH実験をデバイス全体のエンタングルメントベンチマークへと拡張する方法。
前提条件
以下のトピックについて、あらかじめ理解しておくことをお勧めします:
- 「 エンタングルメントの実演 」――ベル状態とCHSHゲームに関する講義。
SparsePauliOpそして、『 Qiskit primitives 』 の紹介。
背景
このチュートリアルでは、量子コンピューター上で実験を行い、Estimatorプリミティブを用いたCHSH不等式の違反を実証します。
クラウザー、ホーン、シモニー、ホルトにちなんで名付けられたCHSH不等式は、ベルの定理(1969年)を実験的に検証するために用いられる。 この定理は、局所的な隠れ変数理論では、量子力学における量子もつれの一部の帰結を説明できないと主張している。 CHSH不等式の違反を実証することは、量子力学が局所隠変数理論と両立しないことを示しており、この実験は量子力学の理解における基礎となるものである。
2022年のノーベル物理学賞は、アラン・アスペクト、ジョン・クラウザー、アントン・ツァイリンガーの3名に授与された。これは、量子情報科学における先駆的な研究、とりわけ、もつれ合った光子を用いた実験によりベルの不等式の破れを実証した功績などが評価されたものである。
この実験では、もつれ状態のペアを作り出し、それぞれの量子ビットについて2つの異なる基底で測定を行います。 第1の量子ビットの基底を および 、第2の量子ビットの基底を および と表記する。これにより、CHSH量 を計算することができる:
各観測値は、 または のいずれかである。明らかに、 の項のうち一方は でなければならず、もう一方は でなければならない。したがって、 となる。 の平均値は、次の不等式を満たさなければならない:
を、 、 、 、および を用いて展開すると、次のようになります:
別の CHSH 量を定義することができる :
これにより、別の不等式が導かれる:
もし量子力学が局所隠変数理論によって記述できるのであれば、これらの不等式は常に成り立つことになる。 このチュートリアルで示されたように、量子コンピュータ上ではこれらの条件が破られる可能性があるため、量子力学は局所隠変数理論とは両立しない。
我々は、ベル状態 を準備することで、もつれ対を生成する。Estimatorプリミティブを用いることで、生カウント値から再構築することなく、期待値 および を直接求めることができる。 および の基底において、2番目の量子ビットを測定する。 最初の量子ビットも直交基底で測定されますが、回転角 を と の間で掃引します。Estimatorプリミティブは、このパラメータ掃引を単一のプリミティブ統合ブロック( PUB ) で評価します。
要件
このチュートリアルを始める前に、以下のものがインストールされていることを確認してください:
- Qiskit SDK v2.0 またはそれ以降のバージョンで、 可視化機能をサポートしたもの
- Qiskit Runtime v0.40 またはそれ以降 (
pip install qiskit-ibm-runtime) - Qiskit Aer v0.17 以降 (
pip install qiskit-aer)
セットアップ
# General
import numpy as np
# Qiskit imports
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
# `qiskit-ibm-runtime` imports
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import EstimatorV2 as Estimator
# Qiskit Aer for local noisy simulation
from qiskit_aer import AerSimulator
# Plotting routines
import matplotlib.pyplot as plt
import matplotlib.ticker as tck# Select an IBM Quantum backend.
service = QiskitRuntimeService()
backend = service.least_busy(
min_num_qubits=127, operational=True, simulator=False
)
backend.nameOutput:
'ibm_pittsburgh'
小規模シミュレータの例
ハードウェアジョブを送信する前に、ローカルのノイズを含むシミュレータ上でワークフロー全体を検証します。 これを使用して AerSimulator.from_backend(backend) 、選択したバックエンドのノイズモデルとカップリングマップを継承するシミュレータを構築します。これにより、シミュレータの応答は、ハードウェアから予想される応答と質的に類似したものとなります。
ステップ1:古典的な入力を量子問題にマッピングする
CHSH回路は、第1の量子ビットの測定基底を掃引する単一のパラメータ を用いて記述する。 このプリミティブは Estimator 解析を簡素化します。観測量の期待値を直接返すほか、1回の呼び出しで、パラメータ化された回路を多くのパラメータ値について評価することができます。
theta = Parameter(r"$\theta$")
chsh_circuit = QuantumCircuit(2)
chsh_circuit.h(0)
chsh_circuit.cx(0, 1)
chsh_circuit.ry(theta, 0)
chsh_circuit.draw(output="mpl", idle_wires=False, style="iqp")Output:
次に、パラメータ化された回路を評価するための、 から までの 21 個の位相値のリストを作成します( 、 、 、...、 、 )。
number_of_phases = 21
phases = np.linspace(0, 2 * np.pi, number_of_phases)
# Phases need to be expressed as a list of lists for the Estimator PUB
individual_phases = [[ph] for ph in phases]最後に、観測量について定義する。 最初の量子ビットは、 だけ回転した軸に沿って測定され、2番目の量子ビットは および で測定される。これらの選択により、4つのCHSH相関関数は、パウリ演算子 、 、 、および に対応する:
# <S_1> = <ZZ> - <ZX> + <XZ> + <XX>
observable1 = SparsePauliOp.from_list(
[("ZZ", 1), ("ZX", -1), ("XZ", 1), ("XX", 1)]
)
# <S_2> = <ZZ> + <ZX> - <XZ> + <XX>
observable2 = SparsePauliOp.from_list(
[("ZZ", 1), ("ZX", 1), ("XZ", -1), ("XX", 1)]
)ステップ2:量子ハードウェア実行に向けた問題の最適化
V2 プリミティブは、ターゲットシステムがサポートする命令および接続性(命令セットアーキテクチャ、すなわちISA、回路およびオブザーバブル)に準拠した回路およびオブザーバブルのみを受け入れます。 バックエンドからを AerSimulator 構築し、シミュレータのターゲットに合わせてトランスパイルを行うことで、同じパスマネージャーがエンドツーエンドで実行されるようにしています。
# Build a noisy simulator from the ibm_pittsburgh backend
aer_sim = AerSimulator.from_backend(backend)
pm = generate_preset_pass_manager(target=aer_sim.target, optimization_level=3)
chsh_isa_circuit = pm.run(chsh_circuit)
chsh_isa_circuit.draw(output="mpl", idle_wires=False, style="iqp")Output:
SparsePauliOp.apply_layoutまた、. を使用して、トランスパイルされた回路の量子ビット配置に合わせて観測可能量を変換します。
isa_observable1 = observable1.apply_layout(layout=chsh_isa_circuit.layout)
isa_observable2 = observable2.apply_layout(layout=chsh_isa_circuit.layout)ステップ3: Qiskit primitivesを使用して実行する
モードで aer_sim``EstimatorV2 パラメータスイープを実行します。 Estimator run() メソッドは、PUB の反復可能オブジェクトを受け取ります。 (circuit, observables, parameter_values, precision)各 PUB は、以下の形式をとります。 両方のオブザーバブルを一緒に渡すことで、同じパラメータスイープを共有するようにします。
# Use the AerSimulator-backed Estimator to validate the workflow locally
estimator_sim = Estimator(mode=aer_sim)
pub = (
chsh_isa_circuit, # ISA circuit
[[isa_observable1], [isa_observable2]], # ISA observables
individual_phases, # Parameter values
)
sim_result = estimator_sim.run(pubs=[pub]).result()ステップ4:後処理を行い、結果を希望の古典形式で返す
Estimator は、両方の観測変数について期待値を返します。 これらを に対して、従来の境界値( )およびツィレルソン境界値( )とともにプロットした。灰色の塗りつぶし部分は、この2つの間の差を示している。 これらの帯域内に位置する点は、CHSH不等式に反する。
chsh1_sim = sim_result[0].data.evs[0]
chsh2_sim = sim_result[0].data.evs[1]
def plot_chsh(phases, chsh1, chsh2, title):
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(
phases / np.pi, chsh1, "o-", label=r"$\langle S_1 \rangle$", zorder=3
)
ax.plot(
phases / np.pi, chsh2, "o-", label=r"$\langle S_2 \rangle$", zorder=3
)
# classical bound +-2
ax.axhline(y=2, color="0.9", linestyle="--")
ax.axhline(y=-2, color="0.9", linestyle="--")
# quantum bound, +-2*sqrt(2)
ax.axhline(y=np.sqrt(2) * 2, color="0.9", linestyle="-.")
ax.axhline(y=-np.sqrt(2) * 2, color="0.9", linestyle="-.")
ax.fill_between(phases / np.pi, 2, 2 * np.sqrt(2), color="0.6", alpha=0.7)
ax.fill_between(
phases / np.pi, -2, -2 * np.sqrt(2), color="0.6", alpha=0.7
)
ax.xaxis.set_major_formatter(tck.FormatStrFormatter("%g $\\pi$"))
ax.xaxis.set_major_locator(tck.MultipleLocator(base=0.5))
ax.set_xlabel(r"$\theta$")
ax.set_ylabel("CHSH witness")
ax.set_title(title)
ax.legend()
plt.show()
plot_chsh(
phases,
chsh1_sim,
chsh2_sim,
"CHSH witnesses from AerSimulator (ibm_pittsburgh noise model)",
)Output:
このシミュレータのCHSH値は、 のいくつかの値において、バックエンドのノイズモデルを考慮した場合でも、すでに という古典的な上限を超えている。 シミュレーションによるデバイスのノイズの影響により、ピーク値はツィレルソン境界値 にわずかに及ばない。 ワークフローの検証が完了したため、次は実際のハードウェアに移ります。
大規模なハードウェアの例
CHSHテストは本質的に 2量子ビットの実験であるため、1つの回路を大きくしただけではスケーラビリティは向上しない。 その代わりに、 多数のテストを並行して実行することでスケーラビリティを確保しています。 ここでは、バックエンドの接続性が許す限り、互いに交わらないベル対をできるだけ多く配置し(結合マップのマッチング )、各ペアに対して独立したCHSHサブ回路を実行します。これらすべてを単一のジョブ内で実行します。
これにより、CHSHはデバイス全体にわたるエンタングルメント品質のベンチマークとなります。つまり、手作業で厳選された単一のペアではなく、チップの大部分にわたるエンタングルメントを一度に、すべてのペアが隣接するペアとのクロストークや並列ゲートエラーの影響を受けるという現実的な条件下で検証するのです。 すべてのペアについてこの不等式を同時に満たさないことは、デバイスのあらゆる場所で真の量子もつれが存在することを証明する。
# -------------------------Step 1: Map classical inputs to a quantum problem-------------------------
# A CHSH test is bipartite, so we scale up by running one independent CHSH
# experiment on every disjoint Bell pair the device can host. A greedy
# matching of the coupling map gives a set of edges that share no qubits.
num_qubits = backend.num_qubits
used = set()
pairs = []
for qa, qb in backend.coupling_map.get_edges():
if qa not in used and qb not in used:
pairs.append((qa, qb))
used.update((qa, qb))
num_pairs = len(pairs)
print(
f"Tiling {backend.name} with {num_pairs} parallel Bell pairs "
f"({2 * num_pairs} of {num_qubits} qubits)"
)
# One parameterized CHSH sub-circuit per pair, all sharing the angle theta
theta = Parameter(r"$\theta$")
chsh_circuit = QuantumCircuit(num_qubits)
for qa, qb in pairs:
chsh_circuit.h(qa)
chsh_circuit.cx(qa, qb)
chsh_circuit.ry(theta, qa)
# Embed the two CHSH observables onto each pair's qubits (identity elsewhere)
obs1 = SparsePauliOp.from_list([("ZZ", 1), ("ZX", -1), ("XZ", 1), ("XX", 1)])
obs2 = SparsePauliOp.from_list([("ZZ", 1), ("ZX", 1), ("XZ", -1), ("XX", 1)])
observables = []
for qa, qb in pairs:
observables.append([obs1.apply_layout([qa, qb], num_qubits)])
observables.append([obs2.apply_layout([qa, qb], num_qubits)])
number_of_phases = 21
phases = np.linspace(0, 2 * np.pi, number_of_phases)
individual_phases = [[ph] for ph in phases]
# -------------------------Step 2: Optimize problem for quantum hardware execution-------------------------
pm = generate_preset_pass_manager(target=backend.target, optimization_level=3)
chsh_isa_circuit = pm.run(chsh_circuit)
isa_observables = [
[o[0].apply_layout(chsh_isa_circuit.layout)] for o in observables
]
# -------------------------Step 3: Execute using Qiskit primitives-------------------------
estimator_hw = Estimator(mode=backend)
estimator_hw.options.environment.job_tags = ["TUT_CI"]
pub = (chsh_isa_circuit, isa_observables, individual_phases)
job = estimator_hw.run(pubs=[pub])
print(f"Job ID: {job.job_id()}")
hw_result = job.result()
# -------------------------Step 4: Post-process and return result in desired classical format-------------------------
# evs has shape (2 * num_pairs, number_of_phases); rows alternate S1, S2
evs = np.asarray(hw_result[0].data.evs)
chsh1_all = evs[0::2]
chsh2_all = evs[1::2]
# A pair "violates" CHSH if its strongest witness exceeds the classical bound
peak = np.maximum(
np.abs(chsh1_all).max(axis=1), np.abs(chsh2_all).max(axis=1)
)
n_violate = int(np.sum(peak > 2))
print(
f"{n_violate}/{num_pairs} Bell pairs violated the CHSH inequality "
f"(mean peak witness {peak.mean():.2f}, classical bound 2)"
)
fig, ax = plt.subplots(figsize=(10, 6))
# Faint individual per-pair curves
for row in chsh1_all:
ax.plot(phases / np.pi, row, color="#1f77b4", alpha=0.2, lw=1)
for row in chsh2_all:
ax.plot(phases / np.pi, row, color="#ff7f0e", alpha=0.2, lw=1)
# Bold mean curves across all pairs
ax.plot(
phases / np.pi,
chsh1_all.mean(axis=0),
color="#1f77b4",
lw=2.5,
label=r"$\langle S_1 \rangle$ (mean)",
)
ax.plot(
phases / np.pi,
chsh2_all.mean(axis=0),
color="#ff7f0e",
lw=2.5,
label=r"$\langle S_2 \rangle$ (mean)",
)
# classical bound +-2 and Tsirelson bound +-2*sqrt(2)
ax.axhline(y=2, color="0.9", linestyle="--")
ax.axhline(y=-2, color="0.9", linestyle="--")
ax.axhline(y=np.sqrt(2) * 2, color="0.9", linestyle="-.")
ax.axhline(y=-np.sqrt(2) * 2, color="0.9", linestyle="-.")
ax.fill_between(phases / np.pi, 2, 2 * np.sqrt(2), color="0.6", alpha=0.7)
ax.fill_between(phases / np.pi, -2, -2 * np.sqrt(2), color="0.6", alpha=0.7)
ax.xaxis.set_major_formatter(tck.FormatStrFormatter("%g $\\pi$"))
ax.xaxis.set_major_locator(tck.MultipleLocator(base=0.5))
ax.set_xlabel(r"$\theta$")
ax.set_ylabel("CHSH witness")
ax.set_title(
f"CHSH witnesses for {num_pairs} parallel Bell pairs on {backend.name}"
)
ax.legend()
plt.show()Output:
Tiling ibm_pittsburgh with 64 parallel Bell pairs (128 of 156 qubits)
Job ID: d86efd5g7okc73el0rp0
63/64 Bell pairs violated the CHSH inequality (mean peak witness 2.75, classical bound 2)
薄い曲線は個々のベルペアを表し、太い曲線はデバイス全体におけるそれらの平均値を示しています。 どの対も、量子力学によって予測されるのと同じ正弦波を描いており、かすかな曲線間のばらつきは、対ごとに異なるノイズの変動を反映している。 曲線が灰色の帯に入る箇所はすべて、 という古典的な境界線を越えていることを示しており、印刷された要約を見ると、実質的にすべてのペアが同時にCHSH不等式に違反していることが確認できる。
ピーク値は、デバイスのノイズの影響により、ツィレルソン境界 には及ばないものの、結論は明白である。すなわち、バックエンドは、単一の厳選されたペアだけでなく、チップ全体にわたって同時に真のエンタングルメントを維持している。 CHSH実験が「スケールする」というのは、このような意味です。つまり、単一のより大規模な回路としてではなく、あらゆる場所で同時に量子もつれを証明する並列ベンチマークとして機能するということです。
次のステップ
この作品に興味を持たれた方は、以下の資料もご参照ください:
- エンタングルメントの実例 :ジョン・ワトラウスによるベル状態とCHSHゲームに関する講義。
- 「Estimatorプリミティブ」の使い方 :PUBとパラメータスイープに関するガイド。
- 量子ビット選択のためのリアルタイムベンチマーク :デバイス全体の量子ビットおよびエンタングルメントの品質を評価するもう一つの方法。
SparsePauliOpAPIリファレンス。