2-4. 位相推定アルゴリズム(入門編)¶
5.2 Phase estimation
)はじめに:アダマールテストを改良する¶
2-2節と同様に、ユニタリ演算\(U\)の固有値\(e^{i\lambda}\)を求める問題を考えよう。アダマールテストでは、固有値の位相\(\lambda\)はテストの測定結果の確率分布に反映され、測定結果をたくさんサンプルすることで\(\lambda\)を推定していた。これをもう少し工夫することで、測定結果から位相の情報をより直接的に取り出すことができることを見ていこう。
下準備として、\(\lambda/2\pi\)を2進展開しよう:
\(j_k\)は0または1の値を取る(古典)ビットである。\(\lambda\)は\(e^{i\lambda}\)の形でのみ出てくるので、\(0 \leq \lambda < 2\pi\)として一般性を失わない。この2進展開を、通常の小数の表記にならって以下のように書く。
以下では簡単のため、\(\lambda/2\pi\)は小数点以下\(n\)桁で書けるものとする。
さて、アダマールテストでは制御ユニタリ演算として\(\Lambda(U)\)を用いたが、ここではそれを少し変えて\(\Lambda(U^{2^k})\)としてみよう。2-2節の前半と同様、\(|\psi\rangle\)が\(U\)の固有状態であることを仮定する。制御ユニタリ演算を行なった後の状態は
上記の2進展開を使うと、
\(e^{i(2\pi)j_1 \ldots j_k} = 1\)だから、結局、
となる。(\(|\psi\rangle\) は省略した)
まず、\(k=n-1\)のときを考えよう。このとき、
だから、アダマールゲートをかければ
である。\(j_n\)は先ほど調べてあるので、\(j_n=0\)の時は何もせず、\(j_n=1\)の時は一般位相ゲート
の\(R_2^\dagger\)をかけると、
と変換できる。そしてアダマールゲートをかければ
このように、アダマールテストを少し変形することで、固有値の位相を1桁ずつ(確定した)量子ビットの状態として取り出すことができる。この手続きを量子回路でいっぺんに行うのが、以下で説明する位相推定アルゴリズムである。
位相推定アルゴリズム:概要¶
上記のアダマールテスト改良版で出てきた式(1)は、どこかで見たことがある形ではないだろうか。そう、2-3節で学んだ量子フーリエ変換の途中式(回路の構成
セクション)と同じである。実は、上記のアルゴリズムの測定側の量子ビットを拡張し、量子フーリエ変換を組み合わせたのが、Kitaevによって提案された位相推定アルゴリズム[1]である。詳細はともかく、どのような操作ができるアルゴリズムなのかを、まず紹介しよう。
\(U\)を量子回路として構成できる一般的なユニタリ行列とする。\(U\)の固有ベクトルを\(|{\rm eigen}_l \rangle\)とし、対応する固有値を\(e^{i\lambda_l}\)とする。ある一般的な量子状態\(|\psi\rangle\)が与えられたとする。これは必ず固有ベクトルで展開できる:
もちろん具体的に係数\(c_l\)がどのような値になるかはわからなくてよい。このとき位相推定アルゴリズムは、\(n\)個の補助量子ビットを用いて、入力状態
を、
で、どれか一つの固有ベクトル\(|{\rm eigen}_l\rangle\)とその固有値\(\lambda_l\)が乱択される。このアルゴリズムは、素因数分解や量子化学アルゴリズム(分子などのエネルギー計算)、そしてその他多くのアルゴリズムのサブルーチンとして利用されていおり、量子コンピュータが従来コンピュータよりも指数的に高速に解を得られる(と期待されている)最も重要な例である。
位相推定アルゴリズム:構成¶
以下では、入力状態\(|\psi\rangle\)を固有状態\(|{\rm eigen}\rangle\)とその固有値\(\lambda\)に限定して、位相推定アルゴリズムを説明していくことにする(入力状態が固有状態の重ね合わせの場合でも全く同じ議論が使えるので、一般性は失われていない)。 アダマールテストでは1つしか測定用の量子ビットを使わなかったが、位相推定では、測定用の補助量子ビットとして\(n\)個の量子ビットを確保する。 位相推定を行う回路は以下の図のようである。
再び、ユニタリー演算\(U\)の固有値\(e^{i\lambda}\)の位相\(\lambda\)を\(n\)ビットの2進小数を用いて
と書いておく。(\(\lambda\)の2進小数表示が\(n\)桁で終わると仮定する;終わらない場合には、最後の測定の際に若干のエラーが生じるが、測定を繰り返せばこのエラーは克服できる。詳細は冒頭のNielsen-Chuangの参照箇所にあたられたい)
- まず、\(|0\rangle\)に初期化された\(n\)個の量子ビットのそれぞれに、アダマールテストと同様にアダマールゲートと制御ユニタリー演算を作用させる。ただし\(k\)番目(\(k=1,...,n\))の補助量子ビットには制御\(U^{2^{k-1}}\)演算をすることにする。\(U|{\rm eigen}\rangle = e^{i2\pi\lambda}|{\rm eigen}\rangle\)だから、\(k\)番目の補助量子ビットには\(e^{i \lambda 2^k}\)の位相が獲得される(これを位相キックバックと呼ぶ)ことになり、\[\left( \frac{|0\rangle + e^{i (2\pi)0.j_1\cdots j_n} |1\rangle }{\sqrt{2}} \right) \otimes \left( \frac{|0\rangle + e^{i (2\pi)0.j_2\cdots j_n} |1\rangle }{\sqrt{2}} \right) \otimes \cdots \otimes \left( \frac{|0\rangle + e^{i (2\pi)0.j_n} |1\rangle }{\sqrt{2}} \right) \otimes |{\rm eigen} \rangle\]という状態が得られる。つまり、固有値の位相を2進小数表示で1ビットずつシフトしたものが各補助量子ビットの位相に格納されることになる。
\(n\)個の補助量子ビットの状態は、2-3節で学んだ量子フーリエ変換の結果の式と全く同じ形をしている。よって、逆量子フーリエ変換(図の\(QFT^\dagger\))をこれらの補助量子ビットに作用させると、
\[\left( \frac{|0\rangle + e^{i (2\pi)0.j_1\cdots j_n} |1\rangle }{\sqrt{2}} \right) \otimes \left( \frac{|0\rangle + e^{i (2\pi)0.j_2\cdots j_n} |1\rangle }{\sqrt{2}} \right) \otimes \cdots \otimes \left( \frac{|0\rangle + e^{i (2\pi)0.j_n} |1\rangle }{\sqrt{2}} \right) \otimes \rangle \rightarrow |j_1...j_n\rangle\]となる。よって、この段階で補助量子ビットの測定を行えば、100%の確率で \(j_1, j_2,\cdots,j_n\) が得られ、\(U\)の固有値の位相\(\lambda\)が求められる。
まとめると、測定用の各量子ビットを制御ビットとする制御\(U^{2^k}\)演算を行なって固有値の位相の情報を補助量子ビットに移した後、逆量子フーリエ変換で位相の値を取り出すのが、位相推定アルゴリズムである。
SymPyによる具体例¶
SymPyで具体例を見ていこう。T演算とS演算を用いて以下のような4×4行列\(U\)をつくり、この行列の固有値を求めてみる。
[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
[10]:
represent(T(0)*S(1),nqubits = 2)
[10]:
CGateS
関数を用いて、\(U\)を制御化した cP_2,3,4
を定義しよう。(2,3,4が3つの補助量子ビットに対応している。0,1は\(U\)の作用する空間である。先ほどの位相推定の回路図でいうと、下から順番に0,1,2,…とビットを名付けている。)[11]:
cP_2 = CGateS(2,T(0))*CGateS(2,S(1))
cP_3 = CGateS(3,T(0))*CGateS(3,S(1))
cP_4 = CGateS(4,T(0))*CGateS(4,S(1))
[12]:
PhaEst = H(4)*H(3)*H(2)
PhaEst
[12]:
次に、制御ユニタリーをそれぞれ、1回、2回、4回と作用させていく。
[13]:
PhaEst = cP_2*cP_3*cP_3*cP_4*cP_4*cP_4*cP_4*PhaEst
[14]:
PhaEst = H(4)*PhaEst
補助量子ビット3には、まず補助量子ビット4を制御とする制御\(R_2^\dagger=S^{-1}=SZ\)演算を作用させる。
[15]:
PhaEst = CGateS(4,S(3))*PhaEst
PhaEst = CGateS(4,Z(3))*PhaEst
その後に\(H\)演算を作用させる。
[16]:
PhaEst = H(3)*PhaEst
補助量子ビット2には、
補助量子ビット3を制御とする制御\(R_2^\dagger = S^{-1} = SZ\)演算
補助量子ビット4を制御とする制御\(R_3^\dagger = TS^{-1} = TSZ\)演算
\(H\)演算
の3つを作用させる。
[17]:
PhaEst = CGateS(3,S(2))*PhaEst
PhaEst = CGateS(3,Z(2))*PhaEst
[18]:
PhaEst = CGateS(4,T(2))*PhaEst
PhaEst = CGateS(4,S(2))*PhaEst
PhaEst = CGateS(4,Z(2))*PhaEst
PhaEst = H(2)*PhaEst
このように構成した位相推定アルゴリズムを固有ベクトルに作用させてみよう。アルゴリズム自体は非常に複雑だ。
[19]:
PhaEst
[19]:
しかし実際、入力に作用させると、
[20]:
simplify(qapply(PhaEst*Qubit("00011")))
[20]:
のように設計通り単純な解が得られることが確認できる。 実際、入力\(|\psi\rangle\)は\(|11\rangle\)なので対応する固有値は\(e^{i3\pi/4}\)だが、補助量子ビット2,3,4は011となっており、固有値の位相\(\lambda=3\pi/4\)の2進小数0.011が得られている!他の入力に対しても、
[21]:
simplify(qapply(PhaEst*Qubit("00000")))
[21]:
[22]:
simplify(qapply(PhaEst*Qubit("00010")))
[22]:
[23]:
simplify(qapply(PhaEst*Qubit("00001")))
[23]:
[24]:
simplify(qapply(PhaEst*H(0)*H(1)*Qubit("00000")))
[24]:
のように、それぞれの固有ベクトルに対して、固有値の位相が3つの補助量子ビットへと重ね合わせのまま取り出されている。この状態の補助量子ビットを測定すると、確率的にどれか一つの固有ベクトルと固有値が得られる。
コラム:素因数分解と位相推定(やや難)¶
位相推定の重要な応用例として、素因数分解アルゴリズムを紹介する。 素因数分解問題は\(n\)桁の整数\(N\)が与えられた時に\(N\)の1ではない約数を 見つける問題であり、従来のコンピュータでは多項式時間で解けるアルゴリズムは 見つかっていない。現在のベストアルゴリズムの計算コストは、
であり、準指数的な計算時間がかかる。 このような素因数分解問題の難しさを利用したRSA暗号などが日常的にも使われている。
P. Shorは1994年に、 量子コンピュータを用いることによって素因数分解問題が桁数\(n\)に対して多項式時間で解くことができる ことを示した。これがいわゆるShorの素因数分解アルゴリズムである。
\(N\)を素因数分解したい整数だとしよう。まず、\(N\)と互いに素な整数\(x\)を見つけてくる。 (\(x\)はユークリッドの互除法で簡単に見つけられる。 適当に\(x\)を取ってきて、ユークリッドの互除法で\(N\)と\(x\)の最大公約数を計算し、 それが1以外の整数であれば\(N\)の非自明な約数がみつかったことになり(素)因数分解が完了するし、 1しかなければ\(x\)は\(N\)と互いに素な整数であることになる。) このとき、\(x\)の\(N\)に関する位数\(r\)を考えてみる。 位数\(r\)とは、
を満たす最小の整数であり、ランダムに\(x\)を選ぶと高い確率で\(r\)は偶数になることが知られている。 \(r\)が偶数であると、上式は
のように変形することができる。 これはつまり、\(x^{r/2} \pm 1 \equiv 0 \: (\textrm{mod} \: N)\)であるか、 \(x^{r/2} + 1\)と\(x^{r/2} - 1\)が\(N\)と非自明な公約数(\(N\)の因数)をもつかのどちらかであることを意味する。 実は、\(x\)がランダムに選ばれているとき、後者の確率が十分高いことも示すことができる。よって、\(x^{r/2} + 1\)か\(x^{r/2} - 1\)と\(N\)との公約数をユークリッドの互除法で用いることにより、最終的に非自明な\(N\)の因数が見つかることになる。 これを繰り返していくことによって、\(N\)をどんどん小さな因数へと分解していくことができ、最終的に素因数分解が達成できる。
そして、素因数分解の鍵となる位数\(r\)は、実は入力\(y\)をmod \(N\) のもとで\(x\)倍するという古典計算に対応したユニタリ行列
の固有値を求めることによって決定することができる。実際、固有状態のラベル\(0 \leq s \leq r-1\)を用いて,固有ベクトルは
と書き下すことができ、
を満たす。つまり\(U_x\)の固有値の位相推定から\(s/r\)を求めその分母として\(r\)を得ることができる(そして、その位数\(r\)から上記の手順で\(N\)の素因数分解ができる)。 これがいわゆる、ショアによる素因数分解アルゴリズム(キタエフの位相推定を利用したバージョン)である。
(詳細は Nielsen-Chuang の 5.3 Applicaitons: order-finding and factoring
を参照)
第2章のまとめ¶
第2章では、以下のことを学んだ。
量子アルゴリズムとは何か、NISQアルゴリズムとlong-termアルゴリズムとは何か
アダマールテスト
量子フーリエ変換
位相推定アルゴリズム
この章で学んだアルゴリズム、特に位相推定アルゴリズムは量子コンピュータを使いこなす上で非常に大切なもので、様々な応用がある。
素因数分解問題:上記コラムで見たように、位相推定アルゴリズムを用いて位数という数を推定することによって素因数分解を行うことができる。
量子系のエネルギー計算:量子力学において、エネルギーはハミルトニアンと呼ばれる行列の固有値によって与えられる。もっとも安定的な状態のエネルギーはもっとも小さい値の固有値、安定な状態は対応する固有ベクトルで与えられる。ハミルトニアン自体はユニタリー行列ではないものの、行列の指数関数で定義される時間発展に対応するユニタリ行列\(e^{-i H t}\)に対して位相推定を行うことによって、エネルギーを計算することができる(7-1節)。
連立一次方程式\(Ax=b\)の求解:位相推定を使って求めた固有値・固有ベクトルを用いることにより、連立一次方程式の解を求めることができる(7-2節)。また、その機械学習への応用も研究されている。