科学しよう

量子計算のプログラミングの解説をメインに、データサイエンス・機械学習について勉強したことをご紹介します

MENU

射影測定

変分分類器の解説をした時に計算結果を取り出すのに最後測定をするという話をしました。
量子機械学習に限った話ではありませんが、量子回路での計算(演算)結果を取り出すには適した量子ビットを適した方法で測定することが必要になります。
古典コンピュータではANDとかOR回路で演算した結果の電圧値を読み出すような行為に相当します。
量子ビットの場合はどの量子ビットをどのような方法で読み出すかで取り出せる情報が異なります。
将来的にこういうハードウェアを理解しないといけないようなことはソフトウェア工学的には無くなるべきと思いますが、現状ではまだこのような原始的なレベルの理解が必要なので勉強しておきましょう。

対象とする読者

  • 量子プログラミングに興味を持ち始めたばかりのエンジニア
  • 量子計算に興味を持ち始めたばかりの高校生・大学生
  • 数学・論理演算・電子回路に慣れていない方
    など

前提とする知識

  • 2~3次元のベクトル・行列を計算できること
  • Dirac記法(ブラ \langle \cdot |とケット | \cdot \rangleを使った量子状態・演算子の表現)を用いた計算式を読めること
  • 基本的な量子ゲート(X, Y, Z)が分かること

バージョン情報

目次

測定理論

量子測定の仮定

量子力学にはいくつかの仮定(postulate)があり、その一つに測定についての項目があります。
様々な本で解説されており、本によって具体的な文は異なりますが、主旨は同一です。
ここではNielsen-Chuangの2.2.3節にある文を引用します。

Postulate3: Quantum measurements are described by a collection  \left\{ M_m \right\} of measurement operators. These are operators acting on the state space of the system being measured. The index m refers to the measurement outcomes that may occur in the experiment. If the state of the quantum system is  | \psi \rangle immediately before the measurement then the probability that result m occurs is given by
\displaystyle{
p(m) = \langle \psi | M^{\dagger}_m M_m | \psi \rangle , \tag{$2.92$}
}
and the state of the system after the measurement is
\displaystyle{
\frac{M_m | \psi \rangle}{\sqrt{\langle \psi | M^{\dagger}_m M_m | \psi \rangle}} . \tag{$2.93$}
}
The measurement operators satisfy the completeness equation,
\displaystyle{
\sum_m{M^{\dagger}_m M_m} = I. \tag{$2.94$}
}

手元に英語版しかなくすみません、、

これはコペンハーゲン解釈ではいわゆる「波束の収縮」に当たる文言ですが、その哲学的な話には立ち入らず、量子計算に用いることができる数学的なエッセンスだけ取り出して解釈します。

この仮定から量子状態とその測定について理解できることは次の3点です。

  • ある測定値(に対応するインデックス) mが得られる測定演算子(行列)を M_mとする
  • 測定前の量子状態 | \psi \rangleにおいて測定値 mが得られる確率 p(m)は(2.92)式で得られる
  • 測定後の量子状態は(2.93)式で得られる状態に変化する

測定というのは対象となる量子系(ここでは量子ビット)に対して測定器と結合させることによって測定値が得られるのですが、この際には何らかの物理現象を介しています。
超伝導量子ビットでは初期では電荷計や磁気センサーを、また最近ではマイクロ波の透過・吸収・反射などを利用して読み出しています。
これらの測定器との結合時に起こる物理現象によってそれまで純粋に他と相互作用することなくユニタリー発展していた量子系はその測定後に何らかの状態に遷移してしまうということです。
この遷移するプロセスも厳密には何らかの時間発展なのだと思いますが、ここでは不連続な変化が起きることとします。

一般の量子測定

今回のテーマは「射影測定」なのですが、それ以外の測定もありますので「量子測定」の全体像を整理しますと下記のベン図になります。

f:id:sakumadaisuke32:20210711102958p:plain
図1. 量子測定の全体像

この図の通り、まず一般的な測定があって、その特別な場合として射影測定があります。
まずは一般的な測定から解説します。

測定とは

具体的な方法としては先の電荷計や磁気センサーなどで、量子系から物理量を得て、それに対応する情報を得るということです。

測定演算子

ある測定値  mが得られる測定演算子 \hat{M}_{m} で、その集合を \{ \hat{M}_m \}と表します。
この時に具体的にどのような測定器でどのような測定をするかは考慮していません。
先の(2.94)式

\displaystyle{
\sum_m{M^{\dagger}_m M_m} = I \tag{$2.94$}
}

を満たしていればよいです。

測定前の状態を | \psi \rangleとし、測定後の状態を | \psi ' \rangleとした場合に、測定後の状態は測定前の状態と測定演算子を用いて下記で表します。

\displaystyle{
| \psi ' \rangle = \frac{M_m | \psi \rangle}{\sqrt{\langle \psi | M^{\dagger}_m M_m | \psi \rangle}}
}

射影測定

量子計算でよく使うのは射影測定で、主に3種類あります。

  • X測定( \sigma_x測定)
    • 量子状態が | + \rangle | - \rangleかを測定
  • Y測定( \sigma_y測定)
    • 光の偏光が | \nearrow \rangle | \swarrow \rangleかを測定(本当は両矢印なのですが、tex記号に無い、、)
      (一般の量子状態で簡潔に表せる状態はなく、光の偏光状態くらいが特別な表現があります。)
  • Z測定( \sigma_z測定)
    • 量子状態が | 0 \rangle | 1 \rangleかを測定

通常は | 0 \rangle | 1 \rangleかを求めるZ測定がほとんどだと思います。
ただ、論文とかで式を追っていったときに \langle \sigma_x \rangle, \langle \sigma_y \rangle, \langle \sigma_z \rangleが出てきたらやってることは射影測定だということを思い出していただければと思います。

ここでは簡単のために3種類紹介しましたが、一般に正規直交基底となる軸に射影する演算子を用いていれば、軸はX, Y, Zでなくとも良いですが量子計算ではまず使われないと思います。

それぞれの測定がハードウェア的に何をしているかは物理系によります。
偏光であれば | 0 \rangleは右回り円偏光、 | 1 \rangleは左回り円偏光に対応し、偏光板などを用いて光が通過する/しないを観測します。
超伝導量子ビット(トランズモン)の場合は | 0 \rangle基底状態に、 | 1 \rangleは第一励起状態に対応しており、マイクロ波の反射・透過・吸収を計測して、どちらの量子状態にいるかを観測します。

arxiv.org

arxiv.org

その他色々ありますが、量子回路に落とし込んでいるため、プログラミングする際にどのような物理系かは意識しなくて良くなっています。

計算基底(Computational Basis)

1量子ビットの場合、具体的には | 0 \rangle, | 1 \rangle, | + \rangle, | - \rangleなど、 x, y, z軸上の基底そのものです。
複数量子ビットの場合、具体的には | 00 \rangle, | 01 \rangle, | 10 \rangle, | 11 \rangleなど、1量子ビットの計算基底の組み合わせです。

射影測定とは

基底の軸上で測定で、射影演算子 \hat{P}_mを用いた測定です。
具体的に \hat{P}_mが満たすべき条件は下記です。

  1.  \sum_m \hat{P}_m = \hat{I}
  2.  \hat{P}_m \hat{P}_{m'} = \delta_{mm'} \hat{P}_m ( \delta_{mm'}はKroneckerのdelta)

これらを満たせれば何でも良いのですが、通常は測定値 mに対応した状態 | m \rangleを用いて

\displaystyle{
\hat{P}_m = | m \rangle \langle m |
}

が用いられます。

Z測定であれば m = 0, 1(エネルギー固有値 E_mのインデックス mに対応)であり、対応する状態は | 0 \rangle = ( \ 1 \ 0 \ )^T, | 1 \rangle = ( \ 0 \ 1 \ )^Tで、射影演算子 | 0 \rangle \langle 0 |, | 1 \rangle \langle 1 |です。
ちゃんと1, 2を満たしていますので行列計算してみてください。

量子回路での対応

実際にそれぞれの基底で測定するにはどのようにプログラミングしてどのような量子回路を構成するのかを確認します。
以下のコードでcircuit.barrier()の上までが状態生成で、circuit.barrier()の下で測定方法を指定します。

Z測定

 | 0 \rangle, | 1 \rangle, | + \rangle, | - \rangleの4状態を実機を使ってZ基底で測定してみます。

| 0 >を測定

qr = QuantumRegister(1)
cr = ClassicalRegister(1)
circuit = QuantumCircuit(qr, cr)

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()

f:id:sakumadaisuke32:20210822231441p:plain
図2.  | 0 \rangleをZ基底で測定する場合.
(左) 測定対象の状態を示すBloch球. (中) 測定まで含めた量子回路. (右) 測定結果.

| 1 >を測定

qr = QuantumRegister(1)
cr = ClassicalRegister(1)
circuit = QuantumCircuit(qr, cr)

circuit.x(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()

f:id:sakumadaisuke32:20210822232001p:plain
図3.  | 1 \rangleをZ基底で測定する場合.
(左) 測定対象の状態を示すBloch球. (中) 測定まで含めた量子回路. (右) 測定結果.

Z基底による測定によって | 0 \rangle | 1 \rangleを見分けられています。

| + >を測定

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()

f:id:sakumadaisuke32:20210822232415p:plain
図4.  | + \rangleをZ基底で測定する場合.
(左) 測定対象の状態を示すBloch球. (中) 測定まで含めた量子回路. (右) 測定結果.

図4右のグラフで | 0 \rangleと表示されている状態が | + \rangleに相当し、 | 1 \rangle | - \rangleに相当します。

| - >を測定

qr = QuantumRegister(1)
cr = ClassicalRegister(1)
circuit = QuantumCircuit(qr, cr)

circuit.h(qr)
circuit.z(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()

f:id:sakumadaisuke32:20210822232846p:plain
図5.  | - \rangleをZ基底で測定する場合.
(左) 測定対象の状態を示すBloch球. (中) 測定まで含めた量子回路. (右) 測定結果.

 |+ \rangle, | - \rangle状態はBloch球上では明らか別の状態なのですが、Z基底による測定上では見分けることができません。
下記のX測定で改めて確認しますが、X測定では見分けることが可能です。

X測定

 | 0 \rangle, | 1 \rangle, | + \rangle, | - \rangleの4状態を実機を使ってX基底で測定してみます。

| 0 >を測定

qr = QuantumRegister(1)
cr = ClassicalRegister(1)
circuit = QuantumCircuit(qr, cr)

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()

f:id:sakumadaisuke32:20210825212015p:plain
図6.  | 0 \rangleをX基底で測定する場合.
(左) 測定対象の状態を示すBloch球. (中) 測定まで含めた量子回路. (右) 測定結果.

| 1 >を測定

qr = QuantumRegister(1)
cr = ClassicalRegister(1)
circuit = QuantumCircuit(qr, cr)

circuit.x(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()

f:id:sakumadaisuke32:20210825212543p:plain
図7.  | 1 \rangleをX基底で測定する場合.
(左) 測定対象の状態を示すBloch球. (中) 測定まで含めた量子回路. (右) 測定結果.

X基底の場合は | 0 \rangle状態と | 1 \rangle状態の見分けがつかなくなりました。

| + >を測定

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()

f:id:sakumadaisuke32:20210825213059p:plain
図8.  | + \rangleをX基底で測定する場合.
(左) 測定対象の状態を示すBloch球. (中) 測定まで含めた量子回路. (右) 測定結果.

| - >を測定

qr = QuantumRegister(1)
cr = ClassicalRegister(1)
circuit = QuantumCircuit(qr, cr)

circuit.h(qr)
circuit.z(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()

f:id:sakumadaisuke32:20210825213504p:plain
図9.  | - \rangleをX基底で測定する場合.
(左) 測定対象の状態を示すBloch球. (中) 測定まで含めた量子回路. (右) 測定結果.

X測定の場合は | + \rangle | - \rangleを見分けることができています。

測定したい状態に合わせて基底を変えましょう!

また、ここでは測定したい状態の方を回転させましたが、偏光を量子ビットとした場合は量子状態はそのままに、偏光板の向きや位相など測定の方を変えることができます。
超伝導量子ビットの場合は状態の方を変えるしかない、、、と思います。
間違ってたらすみません、どなたか教えてください。

Y測定

 | + \rangle + | - \rangle, | + \rangle - | - \rangleの2状態を実機を使ってY基底で測定してみます。

Y軸上を向いた状態を見分けられ、X測定・Z測定では見分けられず、Y測定で見分けられます。 まずはX, Z測定してみます。

| + > + | - >をX基底で測定

import numpy as np

qr = QuantumRegister(1)
cr = ClassicalRegister(1)
circuit = QuantumCircuit(qr, cr)

circuit.h(qr)
circuit.rz(np.pi / 2, 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()

f:id:sakumadaisuke32:20210825223634p:plain
図10.  | + \rangle + | - \rangleをX基底で測定する場合.
(左) 測定対象の状態を示すBloch球. (中) 測定まで含めた量子回路. (右) 測定結果.

| + > + | - >をZ基底で測定

qr = QuantumRegister(1)
cr = ClassicalRegister(1)
circuit = QuantumCircuit(qr, cr)

circuit.h(qr)
circuit.rz(np.pi / 2, 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()

f:id:sakumadaisuke32:20210825224737p:plain
図11.  | + \rangle + | - \rangleをZ基底で測定する場合.
(左) 測定対象の状態を示すBloch球. (中) 測定まで含めた量子回路. (右) 測定結果.

| + > + | - >をY基底で測定

qr = QuantumRegister(1)
cr = ClassicalRegister(1)
circuit = QuantumCircuit(qr, cr)

circuit.h(qr)
circuit.rz(np.pi / 2, qr)
circuit.barrier()

circuit.rz(-np.pi / 2, qr)
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()

f:id:sakumadaisuke32:20210825225441p:plain
図12.  | + \rangle + | - \rangleをY基底で測定する場合.
(左) 測定対象の状態を示すBloch球. (中) 測定まで含めた量子回路. (右) 測定結果.

| + > - | - >をY基底で測定

qr = QuantumRegister(1)
cr = ClassicalRegister(1)
circuit = QuantumCircuit(qr, cr)

circuit.h(qr)
circuit.rz(-np.pi / 2, qr)
circuit.barrier()

circuit.rz(-np.pi / 2, qr)
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()

f:id:sakumadaisuke32:20210825225645p:plain
図13.  | + \rangle - | - \rangleをY基底で測定する場合.
(左) 測定対象の状態を示すBloch球. (中) 測定まで含めた量子回路. (右) 測定結果.

量子測定をもっと知りたい方へ

量子計算する上では計測・観測というのは状態を読み出して終わりですが、量子力学としては重要な理論の一つです。
理論をちゃんと勉強しようとするのは大学・大学院での研究になってしまいますが、一般向けの読み物として下記のようなものがあります。

   

まとめ

量子測定とは何か、数学的な定義、物理系との対応、そして実際に実機で測定する際の量子回路とコーディングをまとめました。

  • 量子計算で主に使うのはX測定・Y測定・Z測定
  • Z測定はそのままで、X測定はHゲートの後にZ測定、Y測定は R_z(- \pi / 2)ゲート・Hゲートの後にZ測定

今回扱ったのは基本的な状態の観測だけなので、任意の状態をそれぞの基底で観測した時にどういう確率分布になるか試してみてください。

量子計測理論についてもNielsen & Chuangにあります。