2-3. 量子フーリエ変換¶
The quantum Fourier transform
)※なお、最後のコラムでも多少述べるが、回路が少し複雑である・入力状態を用意することが難しいといった理由から、いわゆるNISQデバイスでの量子フーリエ変換の実行は難しいと考えられている。
定義¶
まず、\(2^n\)成分の配列 \(\{x_j\}\) に対して\((j=0,\cdots,2^n-1)\)、その離散フーリエ変換である配列\(\{ y_k \}\)を
で定義する\((k=0, \cdots 2^n-1)\)。配列 \(\{x_j\}\) は\(\sum_{j=0}^{2^n-1} |x_j|^2 = 1\) と規格化されているものとする。
量子フーリエ変換アルゴリズムは、入力の量子状態
を、
となるように変換する量子アルゴリズムである。ここで、\(|i \rangle\)は、整数\(i\)の二進数での表示\(i_1 \cdots i_n\) (\(i_m = 0,1\))に対応する量子状態\(|i_1 \cdots i_n \rangle\)の略記である。(例えば、\(|2 \rangle = |0\cdots0 10 \rangle, |7 \rangle = |0\cdots0111 \rangle\)となる)
ここで、式(1)を(2)に代入してみると、
となる。よって、量子フーリエ変換では、
となる。ここで、
は2進小数であり、\(e^{i 2\pi j/2^{-l} } = e^{i 2\pi j_1 \cdots j_l . j_{l-1}\cdots j_n } = e^{i 2\pi 0. j_{l-1}\cdots j_n }\)となることを用いた。(\(e^{i2\pi}=1\)なので、整数部分は関係ない)
まとめると、量子フーリエ変換では、
という変換ができればよい。
回路の構成¶
と、角度 \(2\pi/2^l\) の一般位相ゲート
を多用する。
まず、状態\(\left( |0\rangle + e^{i 2\pi 0.j_1j_2\cdots j_n} |1\rangle \right)\)の部分をつくる。1番目の量子ビット\(|j_1\rangle\)にアダマールゲートをかけると
\[|j_1 \cdots j_n \rangle \to \frac{1}{\sqrt{2}} \left( |0\rangle + e^{i2\pi 0.j_1} |1\rangle \right) |j_2 \cdots j_n \rangle\]となるが、ここで、2番目のビット\(|j_2\rangle\)を制御ビットとする一般位相ゲート\(R_2\)を1番目の量子ビットにかけると、\(j_2=0\)の時は何もせず、\(j_2=1\)の時のみ1番目の量子ビットの\(|1\rangle\)部分に位相 \(2\pi/2^2 = 0.01\)(二進小数)がつくから、
\[ \frac{1}{\sqrt{2}} \left( |0\rangle + e^{i2\pi 0.j_1} |1\rangle \right) |j_2 \cdots j_n \rangle \to \frac{1}{\sqrt{2}} \left( |0\rangle + e^{i2\pi 0.j_1j_2} |1\rangle \right) |j_2 \cdots j_n \rangle\]となる。以下、\(l\)番目の量子ビット\(|j_l\rangle\)を制御ビットとする一般位相ゲート\(R_l\)をかければ(\(l=3,\cdots n\))、最終的に
\[\frac{1}{\sqrt{2}} \left( |0\rangle + e^{i2\pi 0.j_1\cdots j_n} |1\rangle \right) |j_2 \cdots j_n \rangle\]が得られる。
次に、状態\(\left( |0\rangle + e^{i2\pi 0.j_2\cdots j_n} |1\rangle\right)\)の部分をつくる。先ほどと同様に、2番目のビット\(|j_2\rangle\)にアダマールゲートをかければ
\[\frac{1}{\sqrt{2}} \left( |0\rangle + e^{i2\pi 0.j_1\cdots j_n}|1\rangle \right) \frac{1}{\sqrt{2}} \left( |0\rangle + e^{i2\pi 0.j_2} |1\rangle \right) |j_3 \cdots j_n \rangle\]ができる。再び、3番目の量子ビットを制御ビット\(|j_3\rangle\)とする位相ゲート\(R_2\)をかければ
\[\frac{1}{\sqrt{2}} \left( |0\rangle + e^{i2\pi 0.j_1\cdots j_n}|1\rangle \right) \frac{1}{\sqrt{2}} \left( |0\rangle + e^{i2\pi 0.j_2j_3}|1\rangle \right) |j_3 \cdots j_n \rangle\]となり、これを繰り返して
\[\frac{1}{\sqrt{2}} \left( |0\rangle + e^{i2\pi 0.j_1\cdots j_n}|1\rangle \right) \frac{1}{\sqrt{2}} \left( |0\rangle + e^{i2\pi 0.j_2\cdots j_n}|1\rangle \right) |j_3 \cdots j_n \rangle\]を得る。
1,2と同様の手順で、\(l\)番目の量子ビット\(|j_l\rangle\)にアダマールゲート・制御位相ゲート\(R_l, R_{l+1},\cdots\)をかけていく(\(l=3,\cdots,n\))。すると最終的に
\[|j_1 \cdots j_n \rangle \to \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)\]が得られるので、最後にビットの順番をSWAPゲートで反転させてあげれば、量子フーリエ変換を実行する回路が構成できたことになる(式(\(*\))とはビットの順番が逆になっていることに注意)。SWAPを除いた部分を回路図で書くと以下のようである。
SymPyを用いた実装¶
量子フーリエ変換への理解を深めるために、SymPyを用いて\(n=3\)の場合の回路を実装してみよう。
[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
まず、フーリエ変換される入力\(|x\rangle\)として、
という全ての状態の重ね合わせ状態を考える(\(x_0 = \cdots = x_7 = 1/\sqrt{8}\))。
[3]:
input = 1/sqrt(8) *( Qubit("000")+Qubit("001")+Qubit("010")+Qubit("011")+Qubit("100")+Qubit("101")+Qubit("110")+Qubit("111"))
input
[3]:
この状態に対応する配列をnumpyでフーリエ変換すると
[4]:
import numpy as np
input_np_array = 1/np.sqrt(8)*np.ones(8)
print( input_np_array ) ## 入力
print( np.fft.ifft(input_np_array) * np.sqrt(8) ) ## 出力. ここでのフーリエ変換の定義とnumpyのifftの定義を合わせるため、sqrt(2^3)をかける
[0.35355339 0.35355339 0.35355339 0.35355339 0.35355339 0.35355339
0.35355339 0.35355339]
[1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]
となり、フーリエ変換すると \(y_0=1,y_1=\cdots=y_7=0\) という簡単な配列になることが分かる。これを量子フーリエ変換で確かめてみよう。
まず、\(R_1, R_2, R_3\)ゲートはそれぞれ\(Z, S, T\)ゲートに等しいことに注意する(\(e^{i\pi}=-1, e^{i\pi/2}=i\))。
[5]:
represent(Z(0),nqubits=1), represent(S(0),nqubits=1), represent(T(0),nqubits=1)
[5]:
[6]:
QFT_gate = H(2)
QFT_gate = CGateS(1, S(2)) * QFT_gate
QFT_gate = CGateS(0, T(2)) * QFT_gate
2番目(SymPyでは1番目)の量子ビットにもアダマールゲートと制御\(R_2\)演算を施す。
[7]:
QFT_gate = H(1) * QFT_gate
QFT_gate = CGateS(0, S(1)) * QFT_gate
3番目(SymPyでは0番目)の量子ビットにはアダマールゲートのみをかければ良い。
[8]:
QFT_gate = H(0) * QFT_gate
最後に、ビットの順番を合わせるためにSWAPゲートをかける。
[9]:
QFT_gate = SWAP(0, 2) * QFT_gate
これで\(n=3\)の時の量子フーリエ変換の回路を構成できた。回路自体はやや複雑である。
[10]:
QFT_gate
[10]:
入力ベクトル\(|x\rangle\) にこの回路を作用させると、以下のようになり、正しくフーリエ変換された状態が出力されていることが分かる。(\(y_0=1,y_1=\cdots=y_7=0\))
[11]:
simplify( qapply( QFT_gate * input) )
[11]:
読者は是非、入力を様々に変えてこの回路を実行し、フーリエ変換が正しく行われていることを確認してみてほしい。
コラム:計算量について¶
「量子コンピュータは計算を高速に行える」とは、どういうことだろうか。本節で学んだ量子フーリエ変換を例にとって考えてみる。
一体どのような問題で量子コンピュータが高速だと思われているのか、理論的にはどのように扱われているのかなど、詳しく学びたい方はQmediaの記事「量子計算機が古典計算機より優れている」とはどういうことか(竹嵜智之)を参照されたい。
オーダー記法\(\mathcal{O}\)についての註¶
そもそも、アルゴリズムの性能はどのように定量評価できるのだろうか。ここでは、アルゴリズムの実行に必要な資源、主に時間をその基準として考える。とくに問題のサイズを\(n\)としたとき、計算ステップ数(時間)や消費メモリなど、必要な計算資源が\(n\)の関数としてどう振る舞うかを考える。(問題のサイズとは、例えばソートするデータの件数、あるいは素因数分解したい数の二進数表現の桁数などである。)
例えば、問題のサイズ\(n\)に対し、アルゴリズムの要求する計算資源が次の\(f(n)\)で与えられるとする。
\(n\)が十分大きいとき(例えば\(n=10^{10}\))、\(2n^2\)に比べて\(5n\)や\(6\)は十分に小さい。したがって、このアルゴリズムの評価という観点では\(5n+8\)という因子は重要ではない。また、\(n^2\)の係数が\(2\)であるという情報も、\(n\)が十分大きいときの振る舞いには影響を与えない。こうして、計算時間\(f(n)\)の一番「強い」項の情報が重要であると考えることができる。このような考え方を漸近的評価といい、計算量のオーダー記法では次の式で表す。
一般に\(f(n) = \mathcal{O}(g(n))\)とは、ある正の数\(n_0, c\)が存在して、任意の\(n > n_0\)に対して
が成り立つことである。上の例では、\(n_0=7, c=3\)とすればこの定義の通りである(グラフを描画してみよ)。練習として、\(f(n) = 6n^3 +5n\)のオーダー記法\(f(n) = \mathcal{O}(n^3)\)を与える\(n_0, c\)の組を考えてみよ。
アルゴリズムの性能評価では、その入力のサイズを\(n\)としたときに必要な計算資源を\(n\)の関数として表す。特にオーダー記法による漸近評価は、入力のサイズが大きくなったときの振る舞いを把握するときに便利である。そして、こうした漸近評価に基づいた計算量理論というものを用いて、様々なアルゴリズムの分類が行われている。詳細は上記のQmedia記事を参照されたい。