QiskitでW状態のフォン・ノイマンエントロピー，コンカレンス，生成エンタングルメント，相互情報量を計算する．

### やること: 

- タイトルにある物理量を，W状態に対してQiskitで計算

### やらないこと: 
- それぞれの物理量の意味，使い分け
- W状態の意味
- 回路の作り方
- トモグラフィーとは

# installとimport
```python
!pip install qiskit
!pip install qiskit-aer-gpu
```

```python
import qiskit
# Needed for functions
import numpy as np
import time
from copy import deepcopy

# Import Qiskit classes
import qiskit
from qiskit import QuantumRegister, QuantumCircuit, ClassicalRegister, Aer
from qiskit.quantum_info import state_fidelity, process_fidelity
from qiskit.providers.aer import noise
from qiskit.compiler import assemble

# Tomography functions
from qiskit.ignis.verification.tomography import state_tomography_circuits, StateTomographyFitter
from qiskit.ignis.verification.tomography import process_tomography_circuits, ProcessTomographyFitter
from qiskit.ignis.verification.tomography import gateset_tomography_circuits, GatesetTomographyFitter
import qiskit.ignis.mitigation.measurement as mc

# Auxiliary methods
from qiskit.quantum_info import Choi, Kraus
from qiskit.extensions import HGate, XGate
```

# 環境
Google colab上で実行

```python
!Python -V
# 3.6.9
```
```python
qiskit.__version__
# 0.16.0
```

```python
qiskit.__qiskit_version__
#{'qiskit': None,
# 'qiskit-aer': '0.7.0',
# 'qiskit-aqua': '0.8.0',
# 'qiskit-ibmq-provider': '0.11.0',
# 'qiskit-ignis': '0.5.0',
# 'qiskit-terra': '0.16.0'}
```

# W状態を作る
すごく丁寧に書かれたW状態の作り方の資料を見つけたので，ここから引用します．
https://github.com/qiskit-community/qiskit-community-tutorials/blob/master/awards/teach_me_qiskit_2018/w_state/W%20State%201%20-%20Multi-Qubit%20Systems.ipynb

ヘルパー関数を定義

```python
# Here, two useful routine
# Define a F_gate
def F_gate(circ,q,i,j,n,k) :
  theta = np.arccos(np.sqrt(1/(n-k+1)))
  circ.ry(-theta,q[j])       
  circ.cz(q[i],q[j])
  circ.ry(theta,q[j])
  circ.barrier(q[i])
# Define the cxrv gate which uses reverse CNOT instead of CNOT
def  cxrv(circ,q,i,j) :
  circ.h(q[i])
  circ.h(q[j])
  circ.cx(q[j],q[i])
  circ.h(q[i])
  circ.h(q[j])
  circ.barrier(q[i],q[j])
```

3-qubitの場合を考えてみる

```python
# 3-qubit W state
flag_qx2 = True

n = 3
q_w = QuantumRegister(n) 

W_states = QuantumCircuit(q_w) 

W_states.x(q_w[2]) #start is |100>
F_gate(W_states,q_w,2,1,3,1) # Applying F12
F_gate(W_states,q_w,1,0,3,2) # Applying F23

if flag_qx2 : # option ibmqx2 
    W_states.cx(q_w[1],q_w[2]) # cNOT 21
    W_states.cx(q_w[0],q_w[1]) # cNOT 32
    
else :        # option ibmqx4  
    cxrv(W_states,q_w,1,2)
    cxrv(W_states,q_w,0,1)
print(W_states)
```
上記のコードのより以下のような回路が作られる．
![ScreenShot 2020-10-27 22.11.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164411/9383bdf5-0954-e5ae-f242-75f74dac0b9c.png)

# トモグラフィー測定する．
それぞれの物理量を計算するためには，2量子ビットの密度行列が必要なので，トモグラフィー測定を行う．
その際，`state_tomography_circuits`と`StateTomographyFitter`を利用する．

まず，W状態の状態ベクトルを準備

```python
backend = Aer.get_backend('statevector_simulator')
# backend_options = {"method": "statevector_gpu"}
backend_options = {"method": "statevector"}
job = execute(W_states, backend)
result = job.result()
outputstate = result.get_statevector(W_states, decimals=3)
```

次に，2量子ビットを3つ作成. 3量子ビットから2量子ビットの作り方は3通り．

```python
for iis in [[0,1], [0,2], [1,2]]:
  print(iis)
  qst_w = state_tomography_circuits(W_states, [q_w[iis[0]],q_w[iis[1]]])
  job = qiskit.execute(qst_w, Aer.get_backend('qasm_simulator'), shots=5000)

  tomo_w = StateTomographyFitter(job.result(), qst_w)
  rho_w = tomo_w.fit()
  print(" entropy: {0:1.2f}".format(entropy(rho_w)))
  print(" concurrence: {0:1.2f}".format(concurrence(rho_w)))
  print(" entanglemment_of_formation: {0:1.2f}".format(entanglement_of_formation(rho_w)))
  print(" mutual_infomation: {0:1.2f}".format(mutual_information(rho_w)))
```

#　結果
|Tomog\W state| VN entropy | concurrence | entanglement_of_formation | mutual_information |
| --- | --- | --- | --- | --- |
| [0,1]   | 0.91   | 0.67   | 0.55   | 0.93   |
| [0,2]   | 0.91   | 0.66   | 0.54   | 0.93   |
| [1,2]   | 0.94   | 0.65   | 0.53   | 0.89   |

#追記 backend_optionsは使えなくなった
参照: https://zenn.dev/nucl_quantum/articles/5312ddd558793572919c