アインシュタインも驚いた現象:「量子もつれ」をプログラムする

量子コンピュータ

これまでの記事を通じて、量子プログラミングの基礎を完璧に固めてきました。
X、Hゲートでの状態操作、そして測定のランダムな仕組みや、実機に不可欠なノイズの現実を体験しました。
私たちは既に、「量子の海」を泳げる状態にあります。

とは言え、単一の量子ビットだけでは、従来のコンピュータを超えることはできません。
量子コンピュータが真に強力な力を発揮するのは、複数の量子ビットが連携し合ったときです。
そこで今回のテーマは、かのアルベルト・アインシュタインが「不気味な遠隔作用(spooky action at a distance)」と呼んで嫌悪した、量子の究極の現象、「量子もつれ(Entanglement)」です。

量子もつれ」とは、二つの量子ビットが距離に関係なく、切っても切れない強い相関を持つ状態のことです。
片方を測定すると、瞬時にもう片方の状態が決まります。

本記事では、この「もつれ」を実現するための鍵となるCNOT (制御NOT) ゲートの使い方をマスターし、量子コンピュータの歴史で最も有名で基本的なもつれ状態である「ベル状態」をコーディングすることで、その驚くべき結果を観察します。

第1章:CNOTゲートの仕組みと役割

これまでのHやXゲートの操作対象が単一の量子ビットだったのに対し、量子もつれは2つ以上の量子ビット間の関係です。

この関係を作り出す鍵となるのが、制御NOT(Controlled-NOT)ゲート、略して「CNOTゲート」です。

①CNOTゲートとは何か

CNOT ゲートは、次の2つの量子ビットを使います。

  1. 制御(Control)量子ビット
    • CNOT の操作を「実行するか、しないか」を決める量子ビット。
  2. 標的(Target)量子ビット
    • 実際に NOT 操作(ビット反転)を受ける量子ビット。

CNOT ゲートのルールは非常に単純です。

CNOTゲートのルール:

制御量子ビットが |1⟩ の状態のときのみ、標的量子ビットにXゲート(NOT操作)を適用する。

②量子回路図での表現

CNOTゲートは、量子回路図では以下のような独自のアイコンで表現されます。

  • 上の線(制御): 小さな黒丸(下図の画像では青丸)で示されます。この量子ビットの状態が 1 のとき、操作が有効になります。
  • 下の線(標的): 円と十字)で示されます。この量子ビットが NOT 操作を受けます。
ベル状態の回路図

③CNOTの動作を古典的な真理値表で確認

CNOTゲートの制御の仕組みを明確にするため、動作を古典的な入出力表(真理値表)で確認してみましょう。

制御ビット標的ビットNOT操作有無標的の出力
000
011
101
110

重要なのは、制御ビットが 1 の行だけ、標的ビットが反転している点です。

④CNOTが「量子もつれ」を生む理由

古典的なCNOT(制御NOT)はただのロジックゲートですが、量子コンピュータでは特別な役割を果たします。

  • 重ね合わせの制御
    • Hゲートなどによって、制御量子ビットが|0⟩ と |1⟩ の重ね合わせになっている状態でCNOTを適用すると、|0⟩ のロジックと |1⟩ のロジックが同時に標的量子ビットに適用されます。
  • 結果
    • 2つの量子ビットはもはや分離できなくなり、運命共同体となります。これが次章で実際にプログラミングして体験する「量子もつれ」の原理的な始まりです。

第2章:【実践】ベル状態のコーディング

量子もつれの状態のうち、最もシンプルで有名なものが「ベル状態(Bell State)」です。
ベル状態は、2つの量子ビットが最大限にもつれた、運命共同体の状態を指します。

この状態を作り出すための回路は、「Hゲート」と「CNOTゲート」を一つずつ組み合わせるだけで完成します。

①ベル状態回路を構築するプログラム

まず、2つの量子ビットと2つの古典ビットを持つ回路を定義します。

今回記事の目的は『CNOTゲートともつれ』という新しい概念の純粋な効果を体験することなので、ノイズのない理想的な結果を確認できるSamplerを使用しています。

bell_state.py
from qiskit.circuit import QuantumCircuit

# ----------------------------------
# 1. 回路の定義 (H + CNOT)
# ----------------------------------

# 2つの量子ビット(q[0], q[1])、2つの古典ビット(c[0], c[1])を作成
circuit = QuantumCircuit(2, 2)

# Hゲートの適用:インデックス0の量子ビット(q[0])を重ね合わせにする
circuit.h(0)

# CNOTゲートの適用:もつれを生成
# cxはCNOTゲートを意味するQiskitの命令
# 引数1:制御ビット(q[0])のインデックス
# 引数2:標的ビット(q[1])のインデックス
circuit.cx(0, 1)

# 測定:結果を取り出す
# q[0]をc[0]へ、q[1]をc[1]へ測定
circuit.measure([0, 1], [0, 1])

②コードの解説

  1. QuantumCircuit(2, 2):これまで 1 Qubit だったものが、初めて 2 Qubit の回路になりました。
  2. circuit.h(0):最初の量子ビット (q[0]) が |0⟩ と |1⟩ の重ね合わせ状態になります。
  3. circuit.cx(0, 1):ここが核心です。重ね合わせの状態にある q[0] を制御ビットとして、q[1] に CNOTゲートを適用します。
  4. circuit.measure([0, 1], [0, 1]):2つの量子ビットを、2つの古典ビットにそれぞれ測定し、結果を取り出します。

③実行と結果を可視化するプログラム

まずは、以下の通りインポート文を追加する必要があります。

bell_state.py
from qiskit.circuit import QuantumCircuit
# 以下の3つを追加してください
from qiskit_aer.primitives import Sampler
from qiskit.visualization import plot_histogram
import matplotlib.pyplot as plt

続いて、①で作成した回路を実行し、結果をヒストグラムで確認するためのプログラムコードです。
今回は、ノイズのない理想的な Sampler を使用します。

circuit.measure([0, 1], [0, 1]) の続きとしてコーディングしてください。

bell_state.py
# ----------------------------------
# 実行と可視化
# ----------------------------------

# Samplerクラスのインスタンスを作成(ローカルシミュレーターを準備)
sampler = Sampler()

# 回路図の描画
circuit.draw("mpl")
plt.show()

# 作成した回路をシミュレーターで実行(1000回測定)
job = sampler.run(circuit, shots=1000)
result = job.result()

# 結果の分布(counts)を取り出す
counts = result.quasi_dists[0]

# 測定結果の分布をコンソールに出力
print("\n--- ベル状態の測定結果 ---")
print(f"結果の分布(確率): {counts}")

# 取得した確率分布(counts)を基にヒストグラムを作成
plot_histogram(counts)

④プログラムコードの全文掲載

bell_state.py
from qiskit.circuit import QuantumCircuit
from qiskit_aer.primitives import Sampler
from qiskit.visualization import plot_histogram
import matplotlib.pyplot as plt

# ----------------------------------
# 1. 回路の定義 (H + CNOT)
# ----------------------------------

# 2つの量子ビット(q[0], q[1])、2つの古典ビット(c[0], c[1])を作成
circuit = QuantumCircuit(2, 2)

# Hゲートの適用:インデックス0の量子ビット(q[0])を重ね合わせにする
circuit.h(0)

# CNOTゲートの適用:もつれを生成
# cxはCNOTゲートを意味するQiskitの命令
# 引数1:制御ビット(q[0])のインデックス
# 引数2:標的ビット(q[1])のインデックス
circuit.cx(0, 1)

# 測定:結果を取り出す
# q[0]をc[0]へ、q[1]をc[1]へ測定
circuit.measure([0, 1], [0, 1])

# ----------------------------------
# 実行と可視化
# ----------------------------------

# Samplerクラスのインスタンスを作成(ローカルシミュレーターを準備)
sampler = Sampler()

# 回路図の描画
circuit.draw("mpl")
plt.show()

# 作成した回路をシミュレーターで実行(1000回測定)
job = sampler.run(circuit, shots=1000)
result = job.result()

# 結果の分布(counts)を取り出す
counts = result.quasi_dists[0]

# 測定結果の分布をコンソールに出力
print("\n--- ベル状態の測定結果 ---")
print(f"結果の分布(確率): {counts}")

# 取得した確率分布(counts)を基にヒストグラムを作成
plot_histogram(counts)
plt.show()

# 終了時の警告抑制
plt.close("all")

実行結果は、次章(第3章)で詳しく解釈しますが、コンソールの結果(counts)とヒストグラムに注目してください。
特定のパターンの結果しか出ていないことに気づくはずです。

第3章:結果の解釈

コードを実行すると、最初に回路図が表示されるはずです。
回路図を閉じると、コンソール出力とヒストグラムが表示されます。

RuntimeError: main thread is not in main loop」のエラーメッセージが表示される場合がありますが、これは主にPythonでグラフ描画に使われるライブラリ(Matplotlib)が内部で使用するGUIツールキット(Tkinter)が原因で発生する環境依存の「警告」のようなものです。

完全に無視していただいて大丈夫なエラーなので、気にせず進めてください。

①回路図の解釈

ベル状態の回路図

👆の回路図は、コードの意図通りに量子もつれの状態を作り出す「ベル状態」の回路を正確に表しています。

要素対応するコード役割
q₀ の Hゲートcircuit.h(0)q₀ を |0⟩ と |1⟩ の重ね合わせ状態にします。
q₀ の黒(青)丸 :制御circuit.cx(0, 1)q₀ が 1 のとき、操作を実行する制御ビットです。
q₁ の ⊕ :標的circuit.cx(0, 1)q₁ が NOT操作を受ける標的ビットです。
2つのメーターcircuit.measure([0, 1], [0, 1])q₀ と q₁​ の状態を測定し、下の古典ビット c に結果を記録します。

②コンソールとヒストグラムでの測定結果の確認

コンソール結果
--- ベル状態の測定結果 ---
結果の分布(確率): {3: 0.506, 0: 0.494}

コンソール結果には3(二進数で11)と0(二進数で00)の確率分布が表示されています。

ヒストグラム

ヒストグラムにも、0(00) と 3(11) の2つの棒グラフしか表示されず、その他の 1(01) や 2(10) の結果はほぼゼロになったはずです。

  • 0(00): 最初の量子ビット (q1​) と 2番目の量子ビット (q0​) の両方が 0 の状態。
  • 3(11): 両方の量子ビットが 1 の状態。

③「もつれ」の正体は「強い相関」

この結果が量子もつれの決定的な証拠であると言えます。

  1. ランダムであること:Hゲートの影響で、結果が 00 になるか 11 になるかは50/50 の確率でランダムです。
  2. 相関が完璧であること:結果が 0 になると決まった場合、もう片方も必ず 0 になります。逆に 1 になると決まった場合、もう片方も必ず 1 になります。

現実の世界、そして古典的なシステムでは、2枚の独立したコインを1000回投げて表と裏が必ず一致するようなことは起こりえません。
これが、「切っても切れない強い相関」を持つ「量子もつれ」の力なのです。

ではなぜ、H と CNOT の組み合わせでこのような状態が生まれたのでしょうか。

  1. H ゲート:最初のq0を「|0⟩のロジック」と「|1⟩ のロジック」が混ざった重ね合わせにします。
  2. CNOT ゲート
    • q0​ が |0⟩ のロジックを実行するとき → q1​ は何もしない|00⟩ の状態が生まれる。
    • q0​ が |1⟩ のロジックを実行するとき → q1​ はNOT操作で反転する👉 |11⟩の状態が生まれる。

結果として、回路は |00⟩ と |11⟩ の重ね合わせ(ベル状態)となり、もつれが完成しました。

アインシュタインはこの完璧な相関関係に非常に驚き、生涯を通じてこの現象を否定し、反証しようと試み続けました。
量子ビットがどれだけ離れていても、片方の状態が確定すると、瞬時にもう片方の状態も確定するという事実は、「局所的実在論」(物理現象は近くで起きる)という彼の信念に反していたためです。

まとめ

今回は、複数量子ビットの世界に足を踏み入れ、量子もつれという、古典物理学の常識を覆す現象をプログラムで実現しました。

  1. CNOTゲートの習得:CNOT ゲートが、制御ビットが |1⟩ のときのみ標的ビットを反転させるという、制御ロジックを持っていることを学びました。
  2. ベル状態の生成: Hゲートと CNOTゲートを組み合わせることで、|00⟩ と |11⟩ の結果しか出ないという、完璧な相関を持つベル状態を生成し、量子もつれを体験しました。

この「もつれ」こそが、量子コンピュータが古典コンピュータに対して圧倒的な優位性(量子優位性)を発揮する根本的な力です。
アインシュタインが驚いたこの現象を、私たちは今、自分で記述するコードで制御できるようになったのです。

コメント

タイトルとURLをコピーしました