Qiskitで量子テレポーテーション！

#はじめに

IBMのQiskitを使った量子テレポーテーションの実験をしてみたいと思います。
理論的な説明は難しいので、今回は実際に回路を作ってシミュレータで動かすことを目標にします。
「理解するより、まず先にやってみよう」ということですね。
それでは、始めていきましょう。

# Qiskitとは

IBM社の量子コンピュータである「IBM Q」を実際に動かすことができるPythonのOSSです。
シミュレータ機能も含まれているため、量子プログラミングを実践できます。
[IBM Q Experience](https://www.ibm.com/quantum-computing/technology/experience/)上で、誰でもすぐに使えます。


# Qiskit Community 紹介

+ Qiskitの学習を行う場合、QiskitのCommunityに参加するとよいです。  
  + https://qiskit.org/
  + https://github.com/qiskit-community
+ 中でもSlackのコミュニティではさまざまな技術情報の交換やトラブル相談などが行われていますので、興味のある方はぜひ参加してみてください。以下のページにSlackリンクがある。
  + https://github.com/Qiskit/qiskit

#環境
Q Experience  JupyterNotebook
- Python 3.7.3
- Qiskit 0.13.0

#量子テレポーテーションとは
手元にある**量子状態がはるか彼方に一瞬で転送される**という現象です。

アインシュタインの相対性理論においては、光より速いものは存在しないとされています。
しかし、量子テレポーテーションでは光の速度を超えて相互作用を伝達することができるという**嘘みたいなことが起こる**のです。

#量子テレポーテーションで世界が変わる？
手元の量子状態をはるか彼方で再現できることから、何かしらの輸送問題が解決できそうに思います。
しかし、実際は非常に小さな世界のできごとになるため、物質輸送よりも情報通信への応用が期待されます。

でも応用が進んだら本当のテレポーテーションも夢じゃない・・・かも？

#量子テレポーテーションの量子実験

説明はそこそにして実験開始です。

##Qiskitの準備
Q Experience を利用する場合は準備不要です。
ローカル実行する場合はpipでインストールできます。

```py
pip install qiskit
```

##量子回路を作ってシミュレータで動かしてみる

まずはライブラリ準備から。

```python
# ライブラリのインポート
from qiskit import QuantumRegister, ClassicalRegister, BasicAer
```

ベースとなる回路を作ります。

```python
# 古典レジスタ（回路図の下３本）を準備
cr0 = ClassicalRegister(1)
cr1 = ClassicalRegister(1)
cr2 = ClassicalRegister(1)

# ベース回路を作る（量子レジスタ３本＋古典レジスタ３本）
circ = QuantumCircuit(QuantumRegister(3), cr0, cr1, cr2)

# 表示確認
circ.draw(output='mpl')
```

![output_2_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494282/1e4515ad-db03-0669-5186-dddb1d420ebe.png)

できました。
回路の役割は以下のとおりです。
量子レジスタ３本目、古典レジスタ３本目がはるか彼方の転送先にあるという想定です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494282/03c225c8-2a3c-d706-6a60-3efe7de9d4ee.png)

続いて回路にゲートを配置していきます。
作り方は簡単で、回路上にゲートをポチポチと置いていくだけです。

```python
# 測定までの回路を作る
circ.h(0)
circ.h(1)
circ.cx(1,2)
circ.cx(0,1)
circ.h(0)

# 表示確認
circ.draw(output='mpl')
```

![output_3_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494282/7b922288-0483-49ba-6e2c-dbf16886eaf3.png)

とても簡単ですね。
では残りの回路を作っていきます。
barrierで区切りを入れてから、またゲートをポチポチと置いていきます。
古典レジスタ（1本目と2本目）の値によって、量子レジスタ（3本目）のゲート操作が発生するため、c_ifが入ってきますが、要領は同じです。

```python
# 残りの回路を作る
circ.barrier(range(3))
circ.measure(0, 0)
circ.measure(1, 1)
circ.z(2).c_if(cr0, 1)
circ.x(2).c_if(cr1, 1)
circ.measure(2, 2)

# 表示確認
circ.draw(output='mpl')
```

![output_4_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494282/d0c90115-6ed1-e140-2545-9de822ccab7f.png)

とても簡単にできました、回路はこれで完成です。
量子テレポーテーションというと難しそうですが、回路表現ではたったこれだけです。

では、シミュレータで動かしてみましょう。

```python
# シミュレータで実行する
backend = BasicAer.get_backend('qasm_simulator')
# デフォルトで1024回実行
job = execute(circ, backend) 
result = job.result()
```

これで実行完了です。
実行結果を見てみます。

```python
# 実行結果を表示、8パターンで合計1024回になる
result.get_counts(circ)
```

出力結果は以下の通り。

```py
    {'0 0 0': 100,
     '1 1 0': 127,
     '1 0 1': 147,
     '1 0 0': 140,
     '0 0 1': 131,
     '0 1 0': 128,
     '0 1 1': 131,
     '1 1 1': 120}
```

見方は以下のとおりです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494282/8d211c0e-0c75-d116-516b-6ffbc2827bc7.png)

実際にテレポーテーションさせるときは、量子レジスタ３本目は測定せず、そのままの状態で使います。

測定をしなければ、転送元の量子レジスタ１本目と同じ状態が量子レジスタ３本目に再現（テレポーテーション）されます。
測定をすると「重ね合わせ」状態が壊れてしまうのですが、今回は実験なので測定して本当にテレポーテーションしたのかを確認しているわけです。

##あれ、ちょっと待って
できあがった回路をもう一度よく見てみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494282/9338f920-70cc-591a-8c9a-9b53b470c59f.png)

転送元である古典レジスタ１本目、２本目（量子レジスタ１本目、２本目の測定結果に該当）をもとに、転送先の量子レジスタ（３本目）のゲート操作（Z、X）をしていることが分かります。

実は、量子テレポーテーションの実現には「転送元の測定結果を転送先にお知らせする」ということが必要なんです。
どうやって伝えるのかって・・・？ LINEかな。

ともあれ、これをしないと「転送先の量子ビットは転送元とちょっとだけ違う状態になっていることがある」ということなんです。

量子テレポーテーションに落とし穴あり！！
（結局、古典通信が必要なんじゃない！というお話でした）

#おわりに
今回は解説そこそこに書いてみました。
量子コンピュータは最初の概念理解が難しいので、「まず触ってみる」というのもありだと思います。
触って学んで、理解を深めていきましょう。（と自分に言い聞かせてます、理論難しいので）

#参考
https://qiskit.org/documentation/index.html
https://github.com/Qiskit/qiskit-iqx-tutorials/blob/master/qiskit/fundamentals/1_getting_started_with_qiskit.ipynb
https://github.com/maru-labo/ibm-q-handson/blob/master/5_ibm_q.ipynb