はじめに
これまで研究での活用がメインであった量子情報や量子コンピュータがいよいよ実用化に向けて民間利用が進んできました。その中で量子コンピュータの機能を活用してできることを模索するのはとても大事です。
量子コンピュータが期待される理由として、
1、既存コンピュータが性能限界にきている
2、既存コンピュータの問題点を解決するためにサイズを小さくすると量子力学を考慮する必要があり、量子力学に基づいて計算原理を組み直すとデータの使い方が変わる。
3、量子力学の原理を使うとこれまでのコンピュータと異なることができる。
などです。今回はその中でも特に特徴的な波動関数や状態ベクトルと呼ばれる既存計算機では持っていない仕組みを簡単に理解して、計算機科学としてどのように活用すれば良いかを確認してみたいと思います。やってみて思うのは波動関数とか、状態ベクトルとか名前が物理っぽくなっていますが、実際には物理記号を使わなくてもほぼ数学の行列演算だけに落とし込むことができるので、先入観をなくせば理解しやすいと思います。
基本的演算
量子コンピュータのかなめとなる要素は、「状態ベクトル」と「ゲート演算」になります。この2つを把握して早速使いこなしに進みましょう。
状態ベクトル
量子コンピュータではデータの持ち方がこれまでのコンピュータと異なり、「状態ベクトル」と呼ばれるデータの01の組み合わせの配列を持ちます。これまでのコンピュータは01110101011001...010101のように、操作した結果としてのッビット配列を持ちますが、量子コンピュータではこれを拡張し、すべてのビットの組み合わせの配列を情報として持ちます。それを状態ベクトル(まはた波動関数)と呼びます。
全てのビットの組み合わせ配列は二進数で表され、それぞれの組みあわせは確率振幅と呼ばれるそれぞれの状態の出現確率の平方根で情報が格納されます。この状態ベクトルを操作し、把握することで計算を行います。状態ベクトルはビットの組み合わせに対応するので、スペックとしてある量子ビット数
その中でももっとも有名なのが素因数分解を実行するshorのアルゴリズムで、現在のスパコンで何万年もかかるような計算を数時間で解いてしまうことができると言われています。現在はまだ量子コンピュータのサイズが小さいため実質的に解くことができません。
状態ベクトルは、
のように縦ベクトルで表現され、上から順番にビットの配列の組み合わせの出現確率の平方根が格納されます。例えば上記が6量子ビットの場合、
のように、
上から順番に計算結果が最終的に000000になる確率が
最終的な計算結果は1回の演算で1つしか取り出せませんので、なんども計算をする必要が出ることがあります。
量子ゲート
上記の状態ベクトルを操作するために必要なのが量子ゲートです。量子ゲートは、
のように行列演算の形で表現され、1量子ビットの演算と2量子ビットの演算との2種類があります。基本的に1量子ビットを操作するだけで、複数の状態ベクトルの要素に影響を与えるところが特徴です。量子ゲート演算を使いことなすことで、ビットそのものを操作するだけでなく、ビットの組み合わせそのものを操作できます。これらを使ってできることを確認したいと思います。
基本的には行列の演算ですので、状態ベクトルにゲート演算をかけることによって状態ベクトルを操作することができます。
量子位相推定による固有値・固有ベクトル問題
量子コンピュータは現在のコンピュータのデジタル01計算の上位互換と呼ばれています。特徴的な機能として、現在のコンピュータでは性能的に難しいと言われているサイズの行列の固有値・固有ベクトルの問題を期待値を元に解くというのが期待されています。
具体的には
今回、量子ゲートで行列を構成し、その固有ベクトルを状態ベクトルで表現すると、固有値を求めることができるアルゴリズムの量子位相推定に関してみてみたいと思います。
行列の固有値を求める
wikipediaによると、
有限次元線形空間V上の線形変換Aに対して、次の方程式
を満たす零でないベクトル x とスカラー λ が存在するとき、x を A の固有ベクトル(右固有ベクトル)、λ を A の固有値と呼ぶ。
ということです。将来的にAのサイズが大きくなっても効率的に固有値がもとまると様々な問題が解けるようになります。
行列の固有値を状態ベクトルとゲート演算で求める
行列の固有値は、線形変換Aとベクトルxでスカラーλを求めるのでした。
ですので、Aに「ゲート演算」、xに「状態ベクトル」を利用することでAの固有値であるλを求める手法があれば良いことになります。状態ベクトルは
とできればOKです。Hはハミルトニアンと呼ばれる演算子で、ゲートの塊=行列と考えれば大丈夫です。
Hの行列は求めたい行列で固定になりますので、あとは
量子状態の時間発展
シュレディンガー方程式の式変形から下記の時間発展が導き出されます。
こちらは時間t=0の状態にあるハミルトニアンを作用されると量子状態を変化させることができるというものです。これを断続的に行い状態ベクトルの
となります。初期状態から少しずつ状態を変化させて
行列指数関数と量子ゲートによる対角化、トロッタ展開による近似
時間発展は、指数の計算を量子ゲートのユニタリ演算に落とし込むことができます。基本的には対角行列のZゲートを使って、それ以外はZゲートを使って対角化を行います。それらを組み合わせて計算をしますが、指数の肩のハミルトニアンHがユニタリでない場合には、トロッター展開を使ってステップ数nを利用して近似計算で処理をします。
上記のような展開方法を使って時間発展のシミュレーションをします。時間発展のパラメータとしてトロッタ展開のnと時間発展の時間tがありますが、状態ベクトルは最終的に固有ベクトルとして固有値の期待値を求める際に重要になりますが、簡単にもとまるわけではなく調整に苦労しそうです。
量子位相推定アルゴリズム(Quantum Phase Estimation)
(注意)最初に注意しておくのは、この位相推定アルゴリズムは現在の量子コンピュータではエラーが多すぎて実際の実行が難しいことがあります。VQEというアルゴリズムの方が現在のエラーの多いマシンでは実用的なのでその点を理解した上で読んでいただくことをお勧めします。
量子位相推定アルゴリズムは固有値
固有値
位相推定アルゴリズムの全体を見る前にこの量子位相推定アルゴリズムの要である「量子フーリエ変換」を先に見ます。量子フーリエ変換は入力を01ビットの配列から、その配列に対応する位相(角度)をもつ量子状態の形に変形をすることができます。
のようになります。既存の計算機の高速フーリエ変換とほぼ同じなので、詳しく勉強したい方は高速フーリエ変換から学ぶと良いと思います。
量子フーリエ変換は数学的な処理なので、みて覚えてしまっていいと思いますが、
出力された量子状態はそれぞれの量子ビットは位相の角度の精度に対応された形に出力されますが、それぞれの位相に対応する係数は量子ビットから見ると絶対値はすべて1なので、測定しただけでは0と1が完全に50%ずつ出てしまうのが特徴です。
位相は小数点の形で取り出されます。
量子フーリエ変換はフーリエ変換できますが、結果を測定することができません。今回はこの量子フーリエ変換を逆から利用し、逆量子フーリエ変換を使って、量子状態から逆に位相のビット表記を取り出します。
量子コンピュータは可逆回路といって回路を逆向きに実行すると計算結果を戻すことができます。量子フーリエ変換の逆である逆量子フーリエ変換は、フーリエ変換の回路を逆向きに実行するだけで実現できます。
つまり上記量子位相推定では、作った状態ベクトル
量子位相推定アルゴリズムの実装回路をみてみる
量子位相推定アルゴリズムの全体像は下記の通りです。
まず①の重ね合わせですが、Hゲートを最終的に位相を取り出すビットにかけます。仕組みはあとで確認します。次に②の量子状態の作成を行います。こちらは求めたいHに対応する量子状態を作成します。
(すみません、①と③をセットにした方がよかったです。。。今後そうします。)
まず量子状態を作成するには時間発展シミュレーションをすればいいのでした。これ上記でざっくりと概要が書いてありますので、それにそってあとでもう少し詳しくみてみたいと思います。
位相情報を移す
量子状態が時間発展で準備できて、最終的に位相をビット配列の形で逆量子フーリエ変換で取り出す下準備ができたところで、量子状態から位相を取り出す操作である位相推定のアルゴリズムを見てみたいと思います。
こちらが大変参考になりました。
「量子位相推定アルゴリズム (Quantum Phase Estimation) とは」
上記の量子フーリエ変換に関して、任意の精度でのビットの出力に関して式をまとめると、
となります。こちらを量子フーリエ変換すればいいのでした。まずは最初に準備した
が準備できます。量子フーリエ変換する前と比較すると、係数
となりますが、
位相キックバック
基本的には固有値固有ベクトル問題を利用し、ハミルトニアンHを導入したユニタリ回路を制御付きにすることにより、固有ベクトル
対応するハミルトニアンに対する固有値固有ベクトルは、
で書くことができます。量子状態
まず初期状態からアダマールゲートを使って結果を取り出したい方の量子ビットを重ね合わせ状態にします。
次に制御付きのユニタリ回路(ハミルトニアンに対応した形)を導入することで、制御付きなので量子ビットが
そして、これは固有値に対応しているので、
このようになりました。これによって、固有値をかけることができます。あとは、
のように、取り出したい桁に対応するkを導入すれば良いですが、これは回転角に対応しており、固有値をk回かけるということをすると、自然と対応することができます。つまり
これにより、対応する桁kに対してk回の制御付きユニタリゲートをかけることで実行が終了します。
素材は揃ったのであとは実行
これですべての回路が揃いました。
①位相キックバックのための重ね合わせの準備
②時間発展による量子状態の準備
③位相キックバックによる固有値固有ベクトルによる位相の反映
④逆量子フーリエ変換により準備された量子状態の位相をビットの配列で取り出す
これによって初期にときたい行列をハミルトニアンとして準備し、時間発展によって量子状態を準備。量子状態が準備できれば、今度はハミルトニアンをユニタリ操作として制御付きで反映し、固有値固有ベクトルで量子状態を作成。逆量子フーリエ変換によって位相情報のビット配列を取り出す。
これによって量子ビットが増えれば将来的に大きな行列の固有値を効率的(?)に求めることができそうです。shorのアルゴリズムでも、この量子位相推定を利用してうまく位相を取り出すことで素因数分解に役立てることができています。
blueqatで実装
量子コンピュータを使った固有値固有ベクトル問題を解くためのアルゴリズムである位相推定アルゴリズムを実装してみます。ときたい行列をハミルトニアンの形にして、量子状態を準備し、それに対する固有値を推定します。早速実装してみましょう。
簡単な位相推定
まずは少ない量子ビットでやってみます。回路は主に、
1、固有ベクトルとしての量子状態の準備(時間発展・今回省略)
2、固有値を量子状態として取り出す(位相キックバック)
3、固有値の量子状態をビットに変換(量子フーリエ変換)
の3つからなります。
Zゲートの位相を推定する
ひたすら例題をやってみます。まずはハミルトニアンとしてZゲートを用意してみます。
まずは手計算で答えを確認してみると、固有値は、
を計算して、
こうなるはずです。早速確かめてみます。
0、回路の全体概要
今回の回路の全体概要です。
|0> ----H--*--iQFT--M
|
|0> -------Z--------
まず2量子ビット準備します。0番目、1番目と名前をつけます。どちらも量子ビットは0からスタートします。
1、今回は最初っから量子状態を準備します。
2、次に0番目の量子ビットを重ね合わせ状態にして、CZゲートで制御付きのハミルトニアンを実行して位相を0番目の量子ビットにキックバックします。
3、最後に出来上がった量子状態から位相をビット表記で取り出すための逆量子フーリエ変換を実行し、測定して終わりです。
1、量子状態の準備
固有ベクトルを|0>にして計算しますので、何もしないで大丈夫そうです。
2、位相キックバック
次に量子状態から位相をキックバックします。
|0> --H--*--iQFT--M
|
|0> -----Z--------
量子状態が準備できました。0番目の量子ビットを重ね合わせにして、量子状態を固有ベクトルとして、固有値を0番目の方に情報としてうつします。
from blueqat import Circuit
Circuit().h[0].cz[0,1].run()
#array([ 0.70710678+0.j, 0.70710678+0.j, 0. +0.j, -0. +0.j])
array([ 0.70710678+0.j, 0.70710678+0.j, 0. +0.j, -0. +0.j])
となりました。
3、最後量子フーリエ変換
1量子ビットのフーリエ変換はアダマールゲートHと同じですので、Hを適用すると、
Circuit().h[0].cz[0,1].h[0].run()
#array([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j])
array([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j])
となりますので、求める固有値は、
となり、固有ベクトルと固有値は、
となりました。
続きまして固有状態を|1>に
最初の量子状態を|1>にしてみます。
|0> --H--*--iQFT--M
|
|0> --X--Z--------
Circuit().x[1].h[0].cz[0,1].h[0].run()
#array([0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j])
array([0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j])
こちらは11となりました。0番目の量子ビットが1となるので、
となりましたので、固有値
続きましてXゲート
Xゲートは、
となります。固有ベクトルとしてまずは、
を考えると、
|0> --H--*--H--M
|
|0> --H--X-----
を実行してみます。
Circuit(2).h[:].cx[0,1].h[0].m[0].run(shots=100)
#Counter({'00': 100})
Counter({'00': 100})
こちらは、
となりました。続いて固有ベクトルが、
を考えます。
|0> --H---*--H--M
|
|0> --HZ--X-----
HZゲートで量子状態を準備します。
Circuit(2).h[:].z[1].cx[0,1].h[0].m[0].run(shots=100)
#Counter({'10': 100})
Counter({'10': 100})
これより、
となりました。
考察
今回の量子位相推定は汎用量子コンピュータの実現を待つ必要があり、数十年かかると言われています。現在使われているVQEと言われる既存計算機とのハイブリッド方式も今後使い方を見てみたいと思います。