blueqatで量子テレポーテーション

## この記事に関して
ここではpythonライブラリのblueqatを用いて量子プログラミングを行っていこうと思います。
内容は[公式のチュートリアル](https://github.com/Blueqat/Blueqat-tutorials/tree/master/tutorial-ja)を元に作成しています。
今回は量子テレポーテーションを実装していきます。

## 量子テレポーテーション
量子テレポーテーションは[量子もつれ](https://qiita.com/KeiichiroHiga/items/8e4051c0797d8e9d92e2)を用いて作られます。
その名の通り情報を瞬間移動のように相手に送ることができます。
量子もつれを用いるためにまずは Bell基底について説明します。

### Bell 基底
2量子ビットのもつれ状態は、以下の4種類で表せます。

``` math
\left|\Phi^+\right> = \frac{1}{\sqrt2}(\left|00\right>+\left|11\right>),\ 
\left|\Phi^-\right> = \frac{1}{\sqrt2}(\left|00\right>-\left|11\right>) \\
\left|\Psi^+\right> = \frac{1}{\sqrt2}(\left|01\right>+\left|10\right>),\ 
\left|\Psi^-\right> = \frac{1}{\sqrt2}(\left|01\right>-\left|10\right>)

```
参考： https://ja.wikipedia.org/wiki/%E9%87%8F%E5%AD%90%E3%83%86%E3%83%AC%E3%83%9D%E3%83%BC%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3

これらをBell基底と言います。
量子テレポーテーションはこの基底を使って計算します。

### 回路の作成
まずは送る情報ともつれの生成・復元に関して、
送る情報は自由なのでbloch球上の純粋状態を考えて $\left|\psi\right>$ と置きます。
$\left|\psi\right> = a\left|0\right>+b\left|1\right>$ とします。 $(|a|^2+|b|^2 = 1)$

2量子ビットのもつれの生成は[前回](https://qiita.com/KeiichiroHiga/items/8e4051c0797d8e9d92e2)説明した通り、片方に Hゲートを施してその後 CXゲートを施します。
すなわち 00 の場合

``` math
\left|00\right> \xrightarrow{H\  \& \ CX} \left|\Phi^+\right>
```
逆にもつれ状態から戻すのには上と逆の操作をすればいいので
Bell 状態は

``` math
\left|\Phi^+\right> \xrightarrow{CX\  \& \ H} \left|00\right>,
\left|\Phi^-\right> \xrightarrow{CX\  \& \ H} \left|10\right> \\
\left|\Psi^+\right> \xrightarrow{CX\  \& \ H} \left|01\right>,
\left|\Psi^-\right> \xrightarrow{CX\  \& \ H} \left|11\right>
```
となります。

量子テレポーテーションは $\left|\psi\right> \otimes \left|\Phi^+\right>$ と上記のことを考えます。

回路は以下のようになります。

``` math
\begin{array}{ccccccccc}
\left|\psi\right> &-&-&-&-&*&H&-&-&*&-&H&- \\
&&&&&|&&&&|& \\
\left|0\right> &-&H&*&-&X&-&-&*&|&-&H&- \\
&&&|&&&&&|&|&& \\
\left|0\right> &-&-&X&-&-&-&-&X&Z&-&-&-&←出力 \\
&&&&↑&&&↑&&&↑&&↑\\
&&&&\left|\psi_1\right>&&&\left|\psi_2\right>&&&\left|\psi_3\right>&&\left|\psi_4\right>
\end{array}
```

$\left|\psi_1\right>$ について
$\left|\psi_1\right> = \left|\psi\right> \otimes \left|\Phi^+\right>$ となるが、この 0, 1番目のビットを Bell 基底で書き直すと以下のようになります。

``` math
\begin{align}
\left|\psi_1\right> = \left|\psi\right> \otimes \left|\Phi^+\right> = &\frac{1}{2}\left|\Phi^+\right> \otimes (a\left|0\right>+b\left|1\right>) +
\frac{1}{2}\left|\Phi^-\right> \otimes (a\left|0\right>-b\left|1\right>) \\
+&\frac{1}{2}\left|\Psi^+\right> \otimes (b\left|0\right>+a\left|1\right>) +
\frac{1}{2}\left|\Psi^-\right> \otimes (b\left|0\right>-a\left|1\right>)
\end{align}
```
Bell 基底が4つ表示されたことがわかります。
また 3ビット目に $\left|\psi\right>$ らしきものが見えるので情報が移動してるのがわかります。
このように一瞬で情報が移動しているのでテレポーテーションと呼ばれています。

次に $\left|\psi_2\right>$ に関して
上のもつれを戻す操作から $\left|\psi_2\right>$ は以下のように考えられます。

``` math
\begin{align}
\left|\psi_2\right> = 
&\frac{1}{2}\left|00\right> \otimes (a\left|0\right>+b\left|1\right>) +
\frac{1}{2}\left|10\right> \otimes (a\left|0\right>-b\left|1\right>) \\
+&\frac{1}{2}\left|01\right> \otimes (b\left|0\right>+a\left|1\right>) +
\frac{1}{2}\left|11\right> \otimes (b\left|0\right>-a\left|1\right>)
\end{align}
```

以上から $\left|\psi_3\right>, \left|\psi_4\right>$ は

``` math
\left|\psi_3\right> = H\left|0\right> \otimes H\left|0\right> \otimes \left|\psi\right> \\
\left|\psi_4\right> = \left|0\right> \otimes \left|0\right> \otimes \left|\psi\right>
```
となります。

#### 実装 1
以上の内容を実装します。
今回は簡単に送りたい情報を $\left|\psi\right> = \left|1\right>$ とします。
これをテレポートさせます。

``` python:sample.ipynb
from blueqat import Circuit

c = Circuit().x[0]
c.h[1].cx[1,2].cx[0,1].h[0].cx[1,2].cz[0,2].h[0,1]
c.m[:].run(shots=1000)

出力
Counter({'001': 1000})
```
0番目が1だったはずが2番目にテレポートしてます。

#### 実装 2
次は一般の状態を考えます。
今回は送りたい情報を $\left|\psi\right> = U_3(\pi/2,\pi/3,\pi)\left|0\right>$ とします。

``` python:sample.ipynb
from blueqat import Circuit
import math

c = Circuit().u3(math.pi/2,math.pi/3,math.pi)[0]
c.run()

出力
array([0.70710678+0.j        , 0.35355339+0.61237244j])
```
$\left|\psi\right>$ は上の状態ベクトルとなります。

この $\left|\psi\right>$ を上の回路でテレポートさせます。

``` python:sample.ipynb
from blueqat import Circuit
import math

c = Circuit().u3(math.pi/2,math.pi/3,math.pi)[0]
c.h[1].cx[1,2].cx[0,1].h[0].cx[1,2].cz[0,2].h[0,1]
c_array = c.run()

# 要素が0の部分を削除
print(c_array[c_array != 0])

出力
[0.70710678+0.j         0.35355339+0.61237244j]
```
実際の出力は3ビットの状態なので上のコードではいらない部分を落としています。
きちんと出力されたことがわかります。

## まとめ
今回はblueqatを用いて量子テレポーテーションを実装しました。
次回は量子フーリエ変換(QFT)をblueqatで実装してみます。