この記事を読むとわかること
・量子アルゴリズムの基礎知識
・ショアのアルゴリズムでなぜ素因数分解ができるか
・ショアのアルゴリズムで21を素因数分解するやり方
量子コンピューターやアルゴリズムについて学ぶなら、東大の授業でも教科書として使われている「量子コンピュータ入門」という本がおすすめです。
量子コンピュータ入門をAmazonで購入する!
量子アルゴリズムの基礎知識
この記事ではショアのアルゴリズムを用いて21を素因数分解することを目標として、ショアのアルゴリズムに関わる部分についての量子アルゴリズムの基礎知識から説明していきます。
すでに量子アルゴリズムの基礎知識があるという方はこちら。
【量子アルゴリズムの基礎知識1】量子ビット
普通のパソコンにおいては、1ビットというのは0と1のどちらかの状態を取るものですが、量子コンピューターにおける量子ビットというのは、単位球面上の任意のベクトルを表せるものです。(実際に量子ビットがどのように実現されるかという話は抜きで、こういうものがあるという前提のもと話を進めていきます。)
1つの量子ビットの状態は、∣α∣2+∣β∣2=1を満たす複素数α,βと2つのベクトル∣0⟩,∣1⟩を用いて、
α∣0⟩+β∣1⟩
と表されます。
これらの係数は観測確率を表しています。具体的には、量子ビットを観測すると∣α∣2の確率で∣0⟩の状態、∣β∣2の確率で∣1⟩の状態だと観測されます。
複数の量子ビットを並べたもの(厳密にはエンタングル状態のもの)は、それらの積が1つのデータとなります。量子ビットの積は⊗という記号を使います。例えば、
2∣0⟩+∣1⟩,21∣0⟩+23i∣1⟩
という2つの量子ビットを並べたものは、
=2∣0⟩+∣1⟩⊗(21∣0⟩+23i∣1⟩)221∣0⟩⊗∣0⟩+223i∣0⟩⊗∣1⟩+221∣1⟩⊗∣0⟩+223i∣1⟩⊗∣1⟩
となります。
ただ、毎回∣1⟩⊗∣0⟩などと書くのは面倒ですよね。そこで、∣1⟩⊗∣0⟩を∣1⟩∣0⟩と略記したりします。
さらに、これは2進数表示した数のように見ることもできるので、これを10進数表示に直して、∣2⟩と表したりもします。
この記事では、積の記号を省略した形以外に、量子ビットの積を10進数表示した書き方も用います。例えば、∣13⟩は、∣1⟩∣1⟩∣0⟩∣1⟩を表します。
量子アルゴリズムでは、この量子ビットを用いることで、一度に複数の計算を行うことができます。
量子コンピューターでは量子ビットを用いることで複数の計算を同時に行うことができる!
あまりイメージがわかないと思いますが、記事の後半で実際に素因数分解を行うところでわかると思います。
【量子アルゴリズムの基礎知識2】アダマールゲート
量子コンピューターには、量子ビットの状態を変化させる量子ゲートというものがあります。
量子ゲートには様々な種類がありますが、ショアのアルゴリズムでは、アダマールゲートというものだけ知っていれば大丈夫です。
アダマールゲートは、∣0⟩を2∣0⟩+∣1⟩に、∣1⟩を2∣0⟩−∣1⟩に変換させるものです。
アダマールゲートの役割
∣0⟩→2∣0⟩+∣1⟩
∣1⟩→2∣0⟩−∣1⟩
【量子アルゴリズムの基礎知識3】量子離散的フーリエ変換
基本的なゲートを複数組み合わせることで、量子状態に対して量子離散的フーリエ変換というものを施すことができます。量子離散的フーリエ変換は以下のような数式で表される変換です。
量子離散的フーリエ変換は、n量子ビットあるときに、∣j⟩というベクトルに対して、
∣j⟩→2n1∑k=02n−1ei2n2πkj∣k⟩
という変換を施すものである。
また、この逆変換である逆量子離散的フーリエ変換は、∣j⟩というベクトルに対して、
∣j⟩→2n1∑k=02n−1e−i2n2πkj∣k⟩
という変換を施すものである。
フーリエ変換がどのようなものか元々知っている方であれば、これらの式は見たことがあるはずです。実際、離散的フーリエ変換と数式はほぼ変わりません。
今回のショアのアルゴリズムにおいては逆量子離散的フーリエ変換を使うことになりますが、これは、周期の検出のために用いられます。詳しいことは、実際に因数分解をしてみるときに分かるでしょう。
【量子アルゴリズムの基礎知識4】コントロールビット
最後の基礎知識はコントロールビットというものです。コントロールビットは、ある処理を制御するビットのことを指し、コントロールビットが1のときはその処理が行われ、0のときは処理が行われないようになります。
コントロールビットは量子コンピューターに限らず、普通のコンピューターにもあるものですが、量子ビットの性質から、コントロールビットが0と1の重ね合わせ状態になっているので、コントロールビットの振る舞いも重ね合わせになっています。
例えば、21(∣0⟩+∣1⟩)の状態の量子ビットがコントロールビットであり、∣0⟩と∣1⟩を反転させるという処理を制御しているとすると、
21(∣0⟩+∣1⟩)⊗∣0⟩→21(∣0⟩∣0⟩+∣1⟩∣1⟩)
というように変化します。
ショアのアルゴリズムで21を因数分解してみる
さて、ショアのアルゴリズムを実際に用いて21を因数分解してみましょう!ショアのアルゴリズムは実は因数分解をするわけではなく、「位数」という特別な数を効率的に見つけるためのアルゴリズムです。位数とは厳密には群論の中で定義される用語ですが、ここでは以下のように理解しておけばOKです。
互いに素な2つの自然数m,pに対して、
mr≡1(modp)
を満たすような最小の自然数rのことを位数という。
今回、ショアのアルゴリズムによって21を因数分解する際には、p=21であり、また今回はmとして5を採用します。
位数を見つけたあとにどうやって因数分解ができるかはあとで述べますが、実は位数が見つかれば高確率で因数分解が可能になります。
mとして5を採用した場合に、位数を発見するまでの流れは以下のようになります。
ショアのアルゴリズムの流れ(nビット使う場合)
1.アダマールゲートを用いて∣0⟩〜∣2n−1⟩までのすべてのベクトルの重ね合わせを作る
2.21と互いに素な自然数として5を選び、任意の∣y⟩に対し、
U∣y⟩=∣5y(mod21)⟩
なる演算を施す演算子Uに対応するものを作用させることによって、∣50(mod21)⟩〜∣52n−1(mod21)⟩をすべて計算する
3.逆量子離散フーリエ変換によって、位数の情報を取り出す
また、量子ビットの数は多ければ多いほどより精度よく位数を求めることができますが、多くなりすぎると手計算ではできなくなってしまうので,今回は4量子ビット(+4量子ビット)を使うことにします。
アダマールゲートで∣0⟩〜∣2n−1⟩までのすべてのベクトルを作る
ショアのアルゴリズム全体の回路図は以下のようになります。ただし、一番下のビットは4ビット分をまとめて書いており、∣0⟩〜∣31⟩の状態までを取ることできます。

まず最初にHがたくさん並んでいるのがアダマールゲートです。回路全体の入力は∣0⟩⊗∣0⟩⊗∣0⟩⊗∣0⟩⊗∣1⟩であり、これらのうち0が並んでいる方にだけアダマールゲートが施されます。
実際に計算してみると、
=21(∣0⟩+∣1⟩)⊗21(∣0⟩+∣1⟩)⊗21(∣0⟩+∣1⟩)⊗21(∣0⟩+∣1⟩)⊗∣1⟩41(∣0⟩+∣1⟩)⊗(∣0⟩+∣1⟩)⊗(∣0⟩+∣1⟩)⊗(∣0⟩+∣1⟩)⊗∣1⟩
となります。このままだと0と1がただずらっと並んだだけにしか見えませんが、前半の4ビットに対してだけ10進数表示を用いれば、
=41(∣0⟩+∣1⟩)⊗(∣0⟩+∣1⟩)⊗(∣0⟩+∣1⟩)⊗(∣0⟩+∣1⟩)41k=0∑15∣k⟩
となります。アダマールゲートのおかげで入力として∣0⟩〜∣2n−1⟩までのすべてのベクトルの重ね合わせを作り出せたことが分かると思います。この入力の工夫が次に活きてきます。
U∣y⟩=∣5y(mod21)⟩なるUを作用させる
様々な数の重ね合わせが作り出せたら、次はそれをすべて5の指数部分にして,50,51,52,⋯,515までをすべて計算します。
「そんなのどうやったらできるの?」と思いたくなりますが、U∣y⟩=∣5y(mod21)⟩という演算に対応するUを作り、それを図のように作用させると計算することができます。(ただし、UkはU2kつまり、Uを2k回作用させたものを表します。)
図の中で・がいくつも並んでいますが、これは量子アルゴリズムの基礎で説明したコントロールビットを表しています。

実際に計算して確かめてみましょう。
まず、4ビット目をコントロールビットとして、U0を施して、
41(∣0⟩+∣1⟩)⊗(∣0⟩+∣1⟩)⊗(∣0⟩+∣1⟩)⊗(∣0⟩⊗∣1⟩+∣1⟩⊗∣5⟩)
次に、3ビット目をコントロールビットとして、U1を施して、
41(∣0⟩+∣1⟩)⊗(∣0⟩+∣1⟩)⊗(∣0⟩⊗∣0⟩⊗∣1⟩+∣0⟩⊗∣1⟩⊗∣5⟩+∣1⟩⊗∣0⟩⊗∣4⟩+∣1⟩⊗∣1⟩⊗∣20⟩)
これを繰り返していって、最後に、1ビット目をコントロールビットとして、U3を施して、
41(∣0⟩+∣6⟩+∣12⟩)⊗∣1⟩+41(∣1⟩+∣7⟩+∣13⟩)⊗∣5⟩+41(∣2⟩+∣8⟩+∣14⟩)⊗∣4⟩+41(∣3⟩+∣9⟩+∣15⟩)⊗∣20⟩+41(∣4⟩+∣10⟩)⊗∣16⟩+41(∣5⟩+∣11⟩)⊗∣17⟩
これは、上の4ビットと一番下のビットの積がたくさん出てきましたが、この計算過程も考えると、例えば
∣6⟩⊗∣1⟩
であれば、56を21で割った余りが1になることを表しています。このように、Uをうまく作用させたことによって、50〜515を21で割った余りをすべて計算することができました。
よって、式から位数は6であることが分かりますが、**量子コンピューターではこの結果だけを取り出すことはできません。**これは量子コンピューターを学ぶ上で非常に重要なことです。
量子ビットというのは、係数の絶対値の2上が観測される確率に対応する事を思い出すと、この計算が終わった段階で、右の出力がどうなっているかを観測すれば、
∣0⟩⊗∣1⟩,∣6⟩⊗∣1⟩,⋯,∣5⟩⊗∣17⟩,∣11⟩⊗∣17⟩
の16個の状態を等確率で観測できるだけです。本来は因数分解するはずの合成数はとてつもなく大きな数で位数も非常に大きいですから、この状態を観測しても∣6⟩⊗∣1⟩などの位数に関する情報が得られる状態を観測できる確率はほぼ0になります。よってここから、
量子コンピューターは一度に複数の計算を実行することができるが、個別の結果をすべてを取り出すことはできない!
ということが分かると思います。
では、ショアのアルゴリズムにおいてどうやって位数の情報を取り出すのでしょうか…?そこで出てくるのが逆量子離散的フーリエ変換です。
逆量子離散的フーリエ変換で位数の情報を取り出す
逆量子離散的フーリエ変換を施してあげると実は位数の情報を取り出すことができます。まず、ざっとした理解としては、「逆量子離散的フーリエ変換は周期を検出することができる変換」だと思っておけばよいでしょう。
位数というのは5のべき乗を21で割ったあまりがどのくらいの周期で変化するかというのと一致しているので、逆量子離散的フーリエ変換をすることによってその周期の情報を取り出すことができるのです。
はじめの4ビットに逆量子離散的フーリエ変換を施していきましょう。一番下の1ビットの出力が∣1⟩のときは、∣0⟩+∣6⟩+∣12⟩に逆量子離散的フーリエ変換を施して、
∣0⟩+∣6⟩+∣12⟩→3(∣0⟩+∣8⟩)+2(2−2)(1+i)(∣1⟩+∣9⟩)+i(∣2⟩+∣10⟩)+2(2+2)(1−i)(∣3⟩+∣11⟩)+(∣4⟩+∣12⟩)+2(2+1)(1+i)(∣5⟩+∣13⟩)−i(∣6⟩+∣4⟩)+2(2−2)(1−i)(∣7⟩+∣15⟩)
よって、4ビットの出力で観測される確率が極大になるのは∣0⟩,∣3⟩,∣5⟩,∣8⟩,∣11⟩,∣13⟩の近くです。同様にして、一番下の1ビットの出力が∣5⟩や∣17⟩のときなどの別の場合でも観測される確率が極大になるのは∣0⟩,∣3⟩,∣5⟩,∣8⟩,∣11⟩,∣13⟩の近くです。
実は、観測される確率が極大になるような∣m⟩は、n量子ビットを使ったとき、求めたい位数をrとすればm2n≃kr(kは整数)を満たすものです。
今回で言えば、
m16≃k6(kは整数)
となるような∣m⟩が観測される確率が極大になります。今回は、使っている量子ビットの数が少ないため、近似の精度が低くなってしまっていますが、もっと量子ビットを増やせばかなり精度の良い近似が得られて、rの情報が得やすくなります。
今回のように4量子ビットを使った場合には、
316,516,816,1116,1316≃kr
となるので、何度も観測を繰り返して観測確率が極大になっているところを求めていけば、r=6ではないかということがわかります。
これで晴れて位数を求めることができました!これは巨大な合成数についても全く同じようにできますよね。
逆量子離散的フーリエ変換によってなぜ位数がわかるのか
位数を見つけてあとは因数分解に繋げるだけですが、どうして先ほどのように
m2n≃kr(kは整数)
を満たす時に観測確率が極大になるのでしょうか?
この点について、数学的な背景に少し踏み込んで説明していきます。興味のない方は読み飛ばしてもらって大丈夫です。
先ほどのように、演算子Uを作用させていったあとには、位数rより小さい0以上の整数をbとして
∣b⟩+∣b+r⟩+∣b+2r⟩⋯
という形のベクトルが出てきます。これを逆量子離散的フーリエ変換するとどうなるかみてみましょう。
逆量子離散的フーリエ変換は、
∣j⟩→2n1∑k=02n−1e−i2n2πkj∣k⟩
という変換でしたから、
∣b⟩→2n1k=0∑2n−1e−i2n2πkb∣k⟩∣b+r⟩→2n1k=0∑2n−1e−i2n2πk(b+r)∣k⟩⋮
というように変換されていきます。
変換されたあとのベクトルを重ねていくと∣0⟩〜∣2n−1⟩のベクトルの中で弱め合うベクトルと強め合うベクトルが出てくることに注目してください。強め合うベクトルというのはどのような条件を満たすものでしょうか?
強め合うようなベクトル∣m⟩は、同じ方向のベクトルが多数重なり合えばよいので、
2n2πmr≃2kπ
を満たすようなある整数qが存在しているものです。
これを整理すると、
r2n≃km
となり、先ほど出てきた条件式が得られました。十分大きなnについて実験を行えば強め合いがよりはっきり現れることになります。
位数が求まったあとの因数分解のやり方
位数が求まってから、これを因数分解に応用します!ここからは、量子アルゴリズムは関係なく、ただの数学ですね。ポイントは3つあります。
量子アルゴリズムで位数が求まったあとの手順!
1.位数が偶数でなければやり直し
2.m偶数≡1⇔(m2偶数−1)(m2偶数+1)≡0とユークリッドの互除法を用いる
3.うまくいかなければやり直し
これらについてそれぞれ説明していきます。
位数が偶数でなければやり直し
量子アルゴリズムを用いて計算してみたものの、位数として偶数でないものが出てきてしまった場合にはやり直しをすることになります。これは、次の項で説明するような合同式の変形が位数が偶数のときしかできないことが理由になります。
最初に、位数を求めることが目的だと言いましたが、正確には「偶数の位数を求めることが目的」ということになります。
上の例では21に互いに素な数として5を適当に選びましたが、たまたま6という偶数の位数が求まったのでラッキーですね!
m偶数≡1⇔(m2偶数−1)(m2偶数+1)≡0と互除法を利用
中学校の数学で、
x2−1=(x+1)(x−1)
という因数分解を習ったことがあると思いますが、それと同じく、
m偶数≡1⇔(m2偶数−1)(m2偶数+1)≡0
が成り立ちますよね。
そこで、偶数の位数が求まったら、位数の定義から、因数分解をしたい合成数を法として、
m位数≡1⇔(m2位数−1)(m2位数+1)≡0
が言えます。そこで、
m2位数−1,m2位数+1
の2つの数と元の合成数とでそれぞれユークリッドの互除法を使ってあげれば、元の合成数の素因数がこれらの2つの整数に散らばっている可能性があります。あくまでこれは可能性であって、本当に素因数が2つの数に散らばったかどうかがわからないところが注意点です。
21の場合は、
56≡1⇔(53−1)(53+1)≡0
となるので、124と126という数についてそれぞれ21とユークリッドの互除法をおこなってあげればOKです。
しかしながら、
126=21×6
124=21×5+19
となるので、「21の倍数」と「21に互いに素な数」の積が出てきただけでした…
というわけで、このままだと因数分解ができません!
ではこういう場合にはどうするんでしょうか…?
うまくいかなければやり直し
5を選んだ場合のように上手く行かなければ、素因数分解したい数字に互いに素な自然数を改めて選び直して、再びショアのアルゴリズムを実行することになります。
「こんなに長々と説明してきたのに結局やり直しなの!」と思ってしまいますが、これはしょうがないことですね。
例えば、21に互いに素な数として2を選び直すと、位数として6が求まり、
(23−1)(23+1)≡0
となるので、7,9が得られます。それぞれについて21とユークリッドの互除法を用いると、約数として3,7が求まるので晴れて因数分解ができました!
ショアのアルゴリズムではこのようにして、
因数分解したい合成数と互いに素な数を選んでから位数を計算→**偶数の位数が求まったら合同式を変形してユークリッドの互除法を用いてみる→**うまくいけば約数が求まる!(うまくいかなければ数字の選び直し!)
という流れになっていることがわかったと思います。
まとめ
・ショアのアルゴリズムは偶数の位数を効率的に求めるためのアルゴリズム
・量子ビットを用いることによってあらゆる整数乗の計算を一気に行うことができる
・逆量子離散的フーリエ変換を行って確率の強め合いを起こして位数の情報を取り出す
・偶数の位数が求まったら合同式の変形とユークリッドの互除法を用いて上手く行けば約数が分かる
・うまくいかなければ何度も計算をし直さないといけない!