【量子コンピュータ】量子ゲートについてまとめてみた。【Sympy】

皆さん、初めまして！

量子コンピュータに入門して、Sympyという代数計算ライブラリの中にある量子シュミレーターを使っていて、疑問に思ったのでまとめてみました。

# 1. 量子ゲートとは？
量子ゲートとは、量子力学的な言葉で書くと、孤立系の量子状態に作用するユニタリー演算子のことである。少し専門的な言い回しになってしまったが、要するに古典コンピュータの二値状態に対して作用する論理ゲートの代わりに、量子状態(qubitのことと思えば良い)に作用して、別の量子状態を作る操作である。

# 2. パウリ(Pauli)の演算子
まず、最初に恒等演算子。
```math
\begin{eqnarray}
I = \left(
\begin{array}{cccc}
1 & 0 \\
0 & 1 \\
\end{array}
\right)
\end{eqnarray}
```
これは量子状態$\ket\psi$に作用して、$I\ket\psi=\ket\psi$を返す恒等変換である。つまり、何も変化がない変換で記号的に導入しておくと、数学的な体系が綺麗に書けるというだけである。

次に、X, Y, Z演算子
```math
\begin{eqnarray}
X = \left(
\begin{array}{cccc}
0 & 1 \\
1 & 0 \\
\end{array}
\right)
\end{eqnarray}
```
```math
\begin{eqnarray}
Y = \left(
\begin{array}{cccc}
0 & -i \\
i & 0 \\
\end{array}
\right)
\end{eqnarray}
```
```math
\begin{eqnarray}
Z = \left(
\begin{array}{cccc}
1 & 0 \\
0 & -1 \\
\end{array}
\right)
\end{eqnarray}
```
$I$, $X$,$Y$,$Z$の4つの演算子を合わせて、パウリの演算子と呼ばれ、量子力学的に有用な演算子である。

Z軸方向、2準位系の量子状態(1-qubit)
```math
\ket0 = {\left(\array{1 \\ 0}\right)}
```
```math
\ket1 = {\left(\array{1 \\ 0}\right)}
```
を用意し、$Z$演算子に作用させると
```math
Z\ket0 = {\left(\array{1 \\ 0}\right)} = \ket0
```
```math
Z\ket1 = -{\left(\array{0 \\ 1}\right)} = -\ket1
```
と状態が変わる。$Y$演算子に作用させると、
```math
Y\ket0 = i{\left(\array{0 \\ 1}\right)} = i\ket1
```
```math
Y\ket1 = -i{\left(\array{1 \\ 0}\right)} = -i\ket0
```
となり、X演算子を作用させると
```math
X\ket0 = {\left(\array{0 \\ 1}\right)} = \ket1
```
```math
X\ket1 = {\left(\array{1 \\ 0}\right)} = \ket0
```
のようになる。

# 3. Sympyによる量子ゲート(パウリ演算子)
ここまでで、早速、Sympyを使ってみよう。以後、Jupyter Notebookでの使用を想定している。まず、必要なライブラリをインポートする。
```python
from sympy import symbols, init_printing
from sympy.physics.quantum import represent
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
```
Z演算子について調べてみる。()の中には、n個Qubitを用意した時に、Z演算子が0~n-1番目のどのQubitに作用するかを指定できる。X, Y演算子についても同様。
``` python
Z(0)
```
結果
```math
Z_0
```
行列成分で表現してみる。なお、nqubitsで作用させるQubitの数を指定しないとエラーになる。
```python
represent(Z(0), nqubits=1)
```
結果
```math
\begin{bmatrix}
1 & 0 \\
0 & -1 \\
\end{bmatrix}
```
他の場合も試してみると
```python
represent(Z(0), nqubits=2)
```
結果
```math
\begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & -1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & -1 \\
\end{bmatrix}
```
今の場合は、Qubitが2つで、演算子としては、$I \otimes Z$である。
```python
represent(Z(1), nqubits=2)
```
結果
```math
\begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & -1 & 0 \\
0 & 0 & 0 & -1 \\
\end{bmatrix}
```
今の場合は、Qubitが2つで、演算子としては、$Z \otimes I$である。
気をつけなければ、いけないのは、()で指定する番号は、$\ket\alpha \otimes \ket\beta \otimes \ket\gamma$のようなテンソル積があった時、右から0番, 1番, 2番である。

# 4. その他の量子ゲート
## 4.1 アダマールゲート(Hadamard Gate)
```math
\begin{eqnarray}
H = \frac{1}{\sqrt{2}}\left(
\begin{array}{cccc}
1 & 1 \\
1 & -1 \\
\end{array}
\right)
\end{eqnarray}
```
これもパウリ演算子と同様にユニタリー演算子である。$HH=I$の成分計算により、すぐに確認できる。
```math
H\ket0 = \frac{1}{\sqrt{2}}\ket0 + \frac{1}{\sqrt{2}}\ket1
```
```math
H\ket1 = \frac{1}{\sqrt{2}}\ket0 - \frac{1}{\sqrt{2}}\ket1
```
のように、作用する。
なお、$\ket{x} \in {0, 1}$つまり、$x=0$ or $x=1$とならば
```math
H\ket{x} = \frac{1}{\sqrt{2}}(\ket0 + (-1)^x\ket1)
```
と書ける。
Sympyで確かめる。

```python
represent(H(0), nqubits=1)
```
結果
```math
\begin{bmatrix}
\frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\
\frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}} \\
\end{bmatrix}
```
```python
represent(H(0), nqubits=2)
```
結果

```math
\begin{bmatrix}
\frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} & 0 & 0\\
\frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}} & 0 & 0\\
0 & 0 & \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}}\\
0 & 0 & \frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}}\\
\end{bmatrix}
```
つまり、$ I \otimes H$である。
```python
represent(H(1), nqubits=2)
```
結果

```math
\begin{bmatrix}
\frac{1}{\sqrt{2}} & 0 & \frac{1}{\sqrt{2}} & 0\\
0 & \frac{1}{\sqrt{2}} & 0 & \frac{1}{\sqrt{2}}\\
\frac{1}{\sqrt{2}} & 0 & -\frac{1}{\sqrt{2}} & 0\\
0 & \frac{1}{\sqrt{2}} & 0 & -\frac{1}{\sqrt{2}}\\
\end{bmatrix}
```
つまり、$H \otimes I$である。

## 4.2 位相ゲート(Phase Gate)、π/8ゲート
位相ゲートは
```math
\begin{eqnarray}
S = \left(
\begin{array}{cccc}
1 & 0 \\
0 & -i \\
\end{array}
\right)
\end{eqnarray}
```
と表現できる。
また、$\frac{\pi}{8}$ゲートは
```math
\begin{eqnarray}
T = \left(
\begin{array}{cccc}
1 & 0 \\
0 & exp(i\pi/4) \\
\end{array}
\right)
\end{eqnarray}
```
と表現できる。

## 4.3 CNOTゲート(controlled-NOT)
control-qubitと、target-qubit二つ以上のqubitを必要とするゲートである。$2 \times 2$の行列の積ではかけない。
```math
\begin{eqnarray}
CNOT(1, 0) = \left(
\begin{array}{cccc}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0  \\
0 & 0 & 0 & 1 \\
0 & 0 & 1 & 0 \\
\end{array}
\right)
\end{eqnarray}
```
$CNOT(1, 0)\ket{00} = \ket{00}$
$CNOT(1, 0)\ket{01} = \ket{01}$
$CNOT(1, 0)\ket{10} = \ket{11}$
$CNOT(1, 0)\ket{11} = \ket{10}$
となるので、$CNOT(\ket{c} \otimes \ket{t}) = \ket{c} \otimes \ket{t \oplus s}$と書けるつまり、左のcontrol-qubitが右のtarget-qubitの変換を制御している。control-qubitの条件に応じて、target-qubitを変換するかを決めている。ちなみに、CNOT(a, b)とした時、左がcontrol-qubit、右がtarget-qubit
```python
represent(CNOT(1, 0), nqubits=2)
```
結果
```math
\begin{bmatrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & 1 \\
0 & 0 & 1 & 0 \\
\end{bmatrix}
```
```python
represent(CNOT(0, 1), nqubits=2)
```
結果
```math
\begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 \\
0 & 0 & 1 & 0 \\
0 & 1 & 0 & 0 \\
\end{bmatrix}
```
```python
represent(CNOT(1, 0), nqubits=3)
```
結果
```math
\begin{bmatrix}
1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\
0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\
\end{bmatrix}
```


## 4.4 SWAPゲート
2つ以上のQubitを必要とするゲート、2つのqubitが互いに反対の状態にあった時、それぞれ交換する。
```math
\begin{eqnarray}
SWAP(1, 0) =  SWAP(0, 1) = \left(
\begin{array}{cccc}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0  \\
0 & 0 & 0 & 1 \\
0 & 0 & 1 & 0 \\
\end{array}
\right)
\end{eqnarray}
```
## 4.5 CPHASEゲート
2つ以上のQubitを必要とするゲート。
```math
\begin{eqnarray}
CPHASE(1, 0) = CPHASE(0, 1) = \left(
\begin{array}{cccc}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0  \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & -1 \\
\end{array}
\right)
\end{eqnarray}
```

## 4.6 CGateSゲート
やや、複雑なので、実装した方が早い。
``` python
represent(CGateS(1, Z(0)), nqubits=2)
```
結果
```math
\begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
0 & 0 & 0 & -1 \\
\end{bmatrix}
```
のように使う。２番目に引数に演算子を挟んで使う。

# 5 最後に
以上で、Sympyに実装されている量子ゲートについて解説しました。この記事を書いたことで、自分の中でも量子ゲートの理解が深まったと思います。
これから、もっと量子コンピュータの実装力をつけて行きたいです。


# 6. 参考文献
1. Quantum Native Dojo!
https://dojo.qulacs.org/ja/latest/
2. Qiita 「【Python】SymPy の symbol の基本と応用」https://qiita.com/Krypf/items/07649b62af34b6491a1e
3. ほぼ無職のエンジニアのブログ 「[sympy] 量子演算」　https://wayama.io/article/library/sympy/qc/
4. SymPy 1.12.1rc1 documentation
https://docs.sympy.org/latest/modules/physics/quantum/represent.html
5. Qunatum Computation and Quantum Information - M.Nielsen and I.Chuang - CAMBRIDGE
6. 量子情報科学入門 - 石坂智, 小川朋宏, 河内亮周, 木村元, 林正人 - 共立出版