物理量の期待値
前回の射影測定で状態がわかると物理量(演算子)の値がわかります。
また、一般に状態は重ね合わせのため、多数回測定したときには期待値が得られますのでその計算方法を紹介します。
量子力学では頻繁に登場する概念ですが、量子計算は状態を測定できればいいので物理量を意識することはほとんどありません。
ただ、VQEなど一部のアルゴリズムでは物理量(といっても)の期待値が必要になる場合ばありますので量子コンピュータを用いた場合の期待値計算もご紹介します。
対象とする読者
- 量子プログラミングに興味を持ち始めたばかりのエンジニア
- 量子計算に興味を持ち始めたばかりの高校生・大学生 など
対象でない読者
- 量子情報処理の研究室ご出身の方
など
※もちろん読んでいただける分には嬉しいですが、
特に前半部分は電子回路の授業で扱われていたり教科書にも載っている内容となりますので
いまさらと感じさせてしまうかもしれません。
前提とする知識
バージョン情報
- Python 3.7.3
- Qiskit 0.23.1
目次
物理量の演算子
物理量
物理量とは可観測量(Observable)とも呼ばれ、量子力学で実際に何らかの値として測定されうる量のことです。
例えば下記があります。(太字はベクトル量です。)
- 位置
- 速度 (もしくは運動量 )
- 粒子数
- 位相
- エネルギー
- スピン
量子計算で一番馴染みがありそうなのはエネルギーだと思います。
エネルギーの演算子がハミルトニアンで、エネルギー固有値がその状態が持つエネルギーで、その一番小さいエネルギーを持つ状態をとし、その1つ上のエネルギーを持つ状態をとしたのが超伝導量子ビットです。
下図は初期の超伝導磁束量子ビットでRabi振動(量子状態のマイクロ波制御)を観測した論文に掲載されている図です。
超伝導磁束量子ビットのエネルギーは超伝導リングを貫く磁束(磁場)で変化します(右図A)。
一番下の曲線が基底状態(量子計算でいうところの状態)のエネルギーの変化を、またその一つ上の曲線が第一励起状態()のエネルギーの変化の理論計算値を示しています。
図Bは飛ばして図Cが基底状態に置いた超伝導量子ビットにある磁場(横軸)をかけたあと、様々な周波数のマイクロ波を照射した結果、吸収された周波数(縦軸)を示します。
図Cの実線が基底状態と第一励起状態のエネルギーの理論値の差で、点が測定された周波数です。
マイクロ波フォトンのエネルギーは (はPlank定数で、が周波数)で計算されるので、周波数を測定することでその状態における系のエネルギーを測定できたことに相当します。
引用した論文はこちら arxiv.org
演算子の定義
物理量の概念や物理学における実体が以上で理解いただけたとして、数学上の物理量の定義は一般に下記です。
ここでは物理量の固有ベクトル(状態ベクトル)でがその固有ベクトルに対応する固有値です。
量子計算では状態ベクトルは基本的に (とその組み合わせ)しか用いません。
これはスピンが上()を向いているか、下()を向いているかに相当します。
パウリ行列の固有ベクトルを量子計算で使うに対応しており、下記のように表せます。
量子ビットがなら「1」でZ軸上向き、そしてなら「-1」でZ軸下向きを表します。
測定値に中間の値はなく、同一の状態として生成した量子ビットを複数回測定した場合に、の測定値はの確率で「1」となりの確率で「-1」となります。
また後述しますが、この時の期待値は通常の統計における期待値と同様に±1にそれぞれの重みを乗じたものの和になります。
パウリ行列
代表的な物理量としてパウリ行列をブラケット記法でご紹介します。
ここで
ここで
それぞれのパウリ行列に対応する基底に変換すると、いずれについてもになるのが面白いところですね。
それぞれの軸について量子ビットがどちらを向いているかが確かに表されています。
余談ですが、物理学ではパウリ行列単独で物理量となることはなく、スピン()が物理量となります。
物理量の期待値の計算方法
物理量の期待値は任意の量子状態を用いて
例えば、について、状態がの場合における期待値は下記です。
期待値計算の例題
単一の物理量
- 量子状態がの場合
量子コンピュータ(IBMQ)上では測定の基底変換はできないので等価になるように状態を回転させます。
qr = QuantumRegister(1) cr = ClassicalRegister(1) circuit = QuantumCircuit(qr, cr) circuit.h(qr) circuit.barrier() circuit.measure(qr, cr) backend = provider.get_backend('ibmq_armonk') job = execute(circuit, backend=backend, shots=8192) job_monitor(job, interval = 2) result = job.result() count = result.get_counts() plot_histogram(count)
ヒストグラム上ではと表記されているが、の分布を観察しているのと等価である。
そして得られた分布から
num_sampling = sum([dist for dist in count.values()]) print(f'サンプリング数: {num_sampling}') >> サンプリング数: 8192 observable = [1, -1] exp_val = sum([(cnt / num_sampling) * val for cnt, val in zip(observable, count.values())]) print(f'期待値: {exp_val}') >> 期待値: 0.01953125
となり、代数計算した場合とほぼ同じくゼロとなった。
- 量子状態がの場合
で量子コンピュータ(IBMQ)上では先ほどと同じ計算過程によって
qr = QuantumRegister(1) cr = ClassicalRegister(1) circuit = QuantumCircuit(qr, cr) circuit.h(qr) circuit.barrier() circuit.h(qr) circuit.measure(qr, cr) backend = provider.get_backend('ibmq_armonk') job = execute(circuit, backend=backend, shots=8192) job_monitor(job, interval = 2) result = job.result() count = result.get_counts() plot_histogram(count)
num_sampling = sum([dist for dist in count.values()]) print(f'サンプリング数: {num_sampling}') >> サンプリング数: 8192 observable = [1, -1] exp_val = sum([(cnt / num_sampling) * val for cnt, val in zip(observable, count.values())]) print(f'期待値: {exp_val}') >> 期待値: 0.818603515625
である。
物理量の積
量子ビットが2つの場合の
(1つ目の量子ビットのと2つ目の量子ビットのの積の期待値)
全体の物理量は2状態かける2状態の総当たり(直積)となり、
- 量子状態がの場合
で、量子コンピュータ(IBMQ)を用いた場合もこれまで通り下記です。
qr = QuantumRegister(2) cr = ClassicalRegister(2) circuit = QuantumCircuit(qr, cr) circuit.h(qr[1]) circuit.rz(np.pi / 2, qr[1]) circuit.barrier() circuit.rz(-np.pi / 2, qr[1]) circuit.h(qr[1]) circuit.barrier() circuit.measure(qr, cr) circuit.draw(output='mpl') backend = provider.get_backend('ibmq_quito') job = execute(circuit, backend=backend, shots=8192) job_monitor(job, interval = 2) result = job.result() count = result.get_counts() num_sampling = sum([dist for dist in count.values()]) print(f'サンプリング数: {num_sampling}') >> サンプリング数: 8192 observable = [1, -1, -1, 1] exp_val = sum([(cnt / num_sampling) * val for cnt, val in zip(observable, count.values())]) print(f'期待値: {exp_val}') >> 期待値: 0.9560546875
- 量子状態がの場合
で、量子コンピュータ(IBMQ)を用いた場合もこれまで通り下記です。
qr = QuantumRegister(2) cr = ClassicalRegister(2) circuit = QuantumCircuit(qr, cr) circuit.h(qr) circuit.rz(np.pi / 2, qr[1]) circuit.cz(qr[0], qr[1]) circuit.barrier() circuit.rz(-np.pi / 2, qr[1]) circuit.h(qr[1]) circuit.barrier() circuit.measure(qr, cr) circuit.draw(output='mpl') backend = provider.get_backend('ibmq_quito') job = execute(circuit, backend=backend, shots=8192) job_monitor(job, interval = 2) result = job.result() count = result.get_counts() plot_histogram(count) num_sampling = sum([dist for dist in count.values()]) print(f'サンプリング数: {num_sampling}') >> サンプリング数: 8192 observable = [1, -1, -1, 1] exp_val = sum([(cnt / num_sampling) * val for cnt, val in zip(observable, count.values())]) print(f'期待値: {exp_val}') >> 期待値: 0.74365234375
わかりにくいですが、この重ね合わせ状態はグラフの両端に対応します。