\def\bra#1{\mathinner{\left\langle{#1}\right|}}
\def\ket#1{\mathinner{\left|{#1}\right\rangle}}
\def\braket#1#2{\mathinner{\left\langle{#1}\middle|#2\right\rangle}}
量子コンピュータの学習の基本となる「量子ビットの数学的取り扱い」について簡単にまとめておく。なお今回は量子ゲートにはスポットを当てずに、量子ビットの数学的体系にのみ焦点を当てていく。
##1量子ビットについて
1量子ビットはブラケット記号を使用し、
$$
\begin{align}
\ket{Q} &= \alpha\ket{0} + \beta\ket{1} \
\end{align}
$$
のように記述できる。通常のビットの0、1状態($\ket{0},\ket{1}$)の重ね合わせ状態を表しており、規格化定数(α、β)倍の線形結合状態となっている。なお、これは確率振幅として解釈されるため、以下の条件を満たす。
$$
\begin{align}
|\alpha|^{2} + |\beta|^{2} = 1
\end{align}
$$
また、$\ket{0}、\ket{1}$はそれぞれ独立した状態であるため、状態ベクトルとして記述する際に正規直行基底として以下のように記載すると便利である。
$$
\begin{align}
\ket{0} = \binom{1}{0},\ket{1} = \binom{0}{1}
\end{align}
$$
従って、$\ket{0}、\ket{1}$は以下の式を満たす。
$$
\braket{i}{j} = \delta_{ij}
$$
$\delta_{ij}$は、クロネッカーデルタである。うーん、線形台数って感じですね。
複数量子ビットの場合
今回は話を簡単にするために2量子ビットの場合について考える。
古典的なビットの場合、2ビットで格納されるデータの組み合わせは00、01、10、11($\ket{00}、\ket{01}、\ket{10}、\ket{11}$)の4パターンとなる。先程と同様に一般的な量子状態は重ね合わせで記述できるので、2量子ビットの状態は、
$$
\ket{Q} = \alpha_{00}\ket{00} + \alpha_{01}\ket{01} + \alpha_{10}\ket{10} + \alpha_{11}\ket{11}
$$
となり、これも確率振幅と解釈されるので、
$$
\sum _{ij} |\alpha _{ij} | ^{2} = 1
$$
を満たす。また、1量子ビットの状態のテンソル積を2量子ビット用の新しい状態ベクトルとして導入する。
$$
\ket{00} = \ket{0}\otimes\ket{0} =
\begin{pmatrix}
1
\begin{pmatrix}
1 \
0
\end{pmatrix} \
0
\begin{pmatrix}
1 \
0
\end{pmatrix}
\end{pmatrix}
=\begin{pmatrix}
1 \
0 \
0 \
0
\end{pmatrix}, \
\ket{01} = \ket{0}\otimes\ket{1} =
\begin{pmatrix}
1
\begin{pmatrix}
0 \
1
\end{pmatrix} \
0
\begin{pmatrix}
0 \
1
\end{pmatrix}
\end{pmatrix}
=\begin{pmatrix}
0 \
1 \
0 \
0
\end{pmatrix}, \
\ket{10} = \ket{1}\otimes\ket{0} =
\begin{pmatrix}
0
\begin{pmatrix}
1 \
0
\end{pmatrix} \
1
\begin{pmatrix}
1 \
0
\end{pmatrix}
\end{pmatrix}
=\begin{pmatrix}
0 \
0 \
1 \
0
\end{pmatrix}, \
\ket{11} = \ket{1}\otimes\ket{1} =
\begin{pmatrix}
0
\begin{pmatrix}
0 \
1
\end{pmatrix} \
1
\begin{pmatrix}
0 \
1
\end{pmatrix}
\end{pmatrix}
=\begin{pmatrix}
0 \
0 \
0 \
1
\end{pmatrix} .
$$
結果を見て分かる通り、正規直行基底のテンソル積は正規直行基底を作る。3量子ビット、4量子ビットについても2量子ビットと同様に拡張していく。うーん、線形台数って感じですね( ´艸`)
現実的な問題を解ける量子コンピュータの状態を考えると、行列の次元がエグイことになるな・・・(;^ω^)
シミュレータで確かめてみた
Blueqatを利用して実際に今までの説明をおさらいしてみた。Blueqat自体の詳しい説明はMDR社の出しているチュートリアルを参照してほしい。
###1量子ビットの場合
#ライブラリインポート
from blueqat import Circuit
#1量子ビットの回路を定義
c = Circuit(1)
c.m[:].run()
これは、1量子ビットをなにもゲート操作しなかった場合の状態ベクトルを表示するプログラムである。Blueqatでは量子ビットの初期状態は「0」となっているため、(1,0)の状態ベクトルが表示されるはずだ。実行結果は以下の通り。
array([1.+0.j, 0.+0.j])
先程の説明と一致した。
次は状態が「1」の時のプログラムを出力する。
#ライブラリインポート
from blueqat import Circuit
#1量子ビットの回路を定義
c = Circuit(1)
c.x[0].m[:].run()
これは先ほどのものにXゲートを作用させたものである。Xゲートは量子状態を反転させる作用がある。従って、(0,1)の状態ベクトルが表示されるはずだ。実行結果は以下の通り。
array([0.+0.j, 1.+0.j])
これも先程の説明と一致した。
2量子ビットの場合
これも1量子ビットのときと同様に、$\ket{00}、\ket{01}、\ket{10}、\ket{11}$について状態ベクトルをみていく。
- $\ket{00}$の場合
プログラム
#ライブラリインポート
from blueqat import Circuit
#2量子ビットの回路を定義
c = Circuit(2)
c.m[:].run()
実行結果
array([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j])
- $\ket{01}$の場合
プログラム
#ライブラリインポート
from blueqat import Circuit
#2量子ビットの回路を定義
c = Circuit(2)
c.x[0].m[:].run()
実行結果
array([0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j])
- $\ket{10}$の場合
プログラム
#ライブラリインポート
from blueqat import Circuit
#2量子ビットの回路を定義
c = Circuit(2)
c.x[1].m[:].run()
実行結果
array([0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j])
- $\ket{11}$の場合
プログラム
#ライブラリインポート
from blueqat import Circuit
#1量子ビットの回路を定義
c = Circuit(2)
c.x[0].x[1].m[:].run()
実行結果
array([0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j])
どれも先程の説明と一致しました。
最後に
次回は量子ゲートの数学体系について、シミュレーションを踏まえて説明してきたいと思います。それではまた次回の投稿で!