2-2. アダマールテスト¶
最も簡単な量子アルゴリズムとして、アダマールテストとよばれる以下のような量子回路(図1)を考える。つまり、第1ビットは\(|0\rangle\)に、第2ビット以降は状態\(|\psi\rangle\)に初期化されていて、まず第1ビットにアダマールゲートをかける。そして、全体に制御ユニタリ演算子\(\Lambda(U)\)(後述)を作用させ、再び第1ビットにアダマールゲートをかけて、最後にその第1ビットを測定する。
ここで制御ユニタリ演算子\(\Lambda(U)\)というのは、第1量子ビットが\(|0\rangle\)の場合にはなにもせず、\(|1\rangle\)の場合には\(U\)を作用させるユニタリ演算である。
つまり、1つ目の量子ビットが\(|0\rangle\)か\(|1\rangle\)かによって条件分岐して、「なにもしない」または「\(U\)を作用させる」という演算が実行される。従来のコンピュータでは条件分岐は同時に実行することができないが、量子コンピュータでは状態の重ね合わせを利用して、条件分岐を同時並列的に実行することができる。
このアダマールテストの動作について考えていく。最初は簡単のために、量子状態\(|\psi \rangle\)が ユニタリー演算(行列)\(U\)の固有値\(e^{i \lambda}\)の固有状態(固有ベクトル)である場合を考える:
1つ目の量子ビットにアダマール演算\(H\)を作用させることで
が得られる。 その後、制御\(U\)演算を作用させることによって、 固有値\(e^{i\lambda}\)が1つめの量子ビットの相対位相として得られる(このことを位相キックバックと呼ぶ):
最後に、1つ目の量子ビットに再度アダマール演算を行い
が得られる。 1つ目の量子ビットを測定すると測定結果\(m=0,1\)を得る確率は
となる。 \(|\psi \rangle\)、\(U\)、\(\langle \psi |\)は それぞれ\(2^n\)次元の列ベクトル、\(2^n \times 2^n\)行列、 \(2^n\)次元の行ベクトルなので、 このアダマールテストを古典コンピュータ上で愚直に計算すると 指数的に大きなメモリーの確保と演算回数が必要になる。 一方で、量子コンピューターでは、 確率分布\(p_m\)のもとで\(m\)がサンプルされる。 \(\cos \lambda\)を ある誤差\(\epsilon\)で推定したい場合は、 その逆数\(1/\epsilon\)の多項式回程度サンプルすればよいことになる。
同じ計算を、必ずしも固有ベクトルとは限らない、一般の入力に対して行うと、測定前の状態は、
となり、0もしくは1が得られる確率は、
となる。つまり、量子コンピュータ上でアダマールテストを実行すれば、その測定結果のサンプル平均をとることでベクトル\(|\psi \rangle\)でユニタリ行列\(U\)を挟んだ値を推定することができる。同じ値を古典コンピュータで求めようとした場合、量子ビット数\(n\)が大きくなるにつれベクトルや行列の次元は指数的に大きくなるので、指数的な時間を要する。
なお、1つ目の量子ビットを測定した後の、2つ目の量子ビットの状態は、測定結果\(m = 0, 1\)に応じて以下の状態になる(規格化因子は省略):
ここで、\(U\)が1量子ビットのユニタリ演算で、かつその固有値が\(\pm 1\)であるような場合を考える。固有値\(\pm 1\)に対応する固有ベクトル\(|u_1\rangle\), \(|u_{-1}\rangle\)を使って\(|\psi\rangle = c_1|u_1\rangle + c_{-1}|u_{-1}\rangle\)と展開し代入することで、測定後の状態\(|\psi_0\rangle\), \(|\psi_1\rangle\)はそれぞれ固有値\(\pm 1\)に対応する固有状態であることが分かる。固有値が\(\pm 1\)ではない場合も、アダマールテストの出力を入力として繰り返すと\(U\)の固有状態に状態が収束していく(興味のある人は、以下の例を参考にして試してもらいたい)。
SymPyでの実装¶
具体的な例として、\(U=H\)(アダマールゲート)の場合を考えてみよう。補助量子ビットを\(|0\rangle\)、アダマールテストの入力\(|\psi\rangle\)も\(|0\rangle\)とする。
[1]:
from sympy import *
from sympy.physics.quantum import *
from sympy.physics.quantum.qubit import Qubit,QubitBra
init_printing() # ベクトルや行列を綺麗に表示するため
from sympy.physics.quantum.gate import X,Y,Z,H,S,T,CNOT,SWAP,CPHASE,CGateS
[3]:
state = Qubit('00')
制御H演算は、CGateS()
を用いて
[4]:
ctrlH = CGateS(1,H(0))
represent(ctrlH,nqubits=2)
[4]:
と行列表示される。 測定前の状態は、
[5]:
H(1)*ctrlH*H(1)*state
[5]:
とかけるが、SymPyに計算させてみると
[6]:
qapply(H(1)*ctrlH*H(1)*state)
[6]:
となる。第1章で紹介したSymPyのmeasure_partial
関数を用いて、1つ目の量子ビットの測定結果が0だった場合の量子状態と確率を求めると、
[7]:
from sympy.physics.quantum.qubit import measure_all, measure_partial, measure_all_oneshot, measure_partial_oneshot
measured_state_and_probability_zero = measure_partial(qapply(H(1)*ctrlH*H(1)*state),(1,))[0]
simplify(measured_state_and_probability_zero)
[7]:
[8]:
measured_state_zero = measured_state_and_probability_zero[0]
simplify(qapply(H(0)*measured_state_zero))
[8]:
同様に1の測定結果を得た場合は、固有値−1の固有状態であることも確認できるので試してもらいたい。
[9]:
measured_state_one = measure_partial(qapply(H(1)*ctrlH*H(1)*state),(1,))[1][0]
simplify(qapply(H(0)*measured_state_one))
[9]: