qiskit.visualizationの関数まとめ

# はじめに
qiskitで処理結果の可視化に利用するqiskit.visualizationパッケージ
何ができるか、まとめてみたいと思います。（作業メモです）
なお今回は、実行結果の可視化を担う（**Counts and State Visualizations**）をまとめてみたいと思います。

https://qiskit.org/documentation/apidoc/visualization.html#module-qiskit.visualization

また、他の量子コンピュータ関係の他の記事は、下記で紹介しています。

https://qiita.com/shnchr/items/41fa7fd1284d74007a7c

```math
% basic braket 
\newcommand{\bra}[1]{\left\langle #1 \right|}
\newcommand{\ket}[1]{\left| #1 \right\rangle}
\newcommand{\bracket}[2]{\left\langle #1 \middle| #2 \right\rangle}
\newcommand{\ketbra}[2]{\left| #1 \right\rangle \left\langle #2 \right|}
\newcommand{\ketbraket}[3]{\left| #1 \right\rangle \left\langle #2 \middle| #3 \right\rangle}
% small-size
\newcommand{\bras}[1]{\left\langle {\scriptsize #1}  \right|}
\newcommand{\kets}[1]{\left| {\scriptsize #1}  \right\rangle}
\newcommand{\brackets}[2]{\left\langle {\scriptsize #1} \middle| {\scriptsize #2} \right\rangle}
\newcommand{\ketbras}[2]{\left| {\scriptsize #1} \right\rangle \left\langle {\scriptsize #2} \right|}
\newcommand{\ketbrakets}[3]{\left| {\scriptsize #1} \right\rangle \left\langle {\scriptsize #2} \middle| {\scriptsize #3} \right\rangle}
% Matrix
\newcommand{\tate}[2]{\begin{bmatrix} #1 \\ #2 \end{bmatrix}}
\newcommand{\yoko}[2]{\begin{bmatrix} #1 & #2 \end{bmatrix}}
\newcommand{\mtrx}[4]{\begin{bmatrix} #1 & #2 \\ #3 & #4 \end{bmatrix}}
% Matrix largesize
\newcommand{\tateL}[4]{\begin{bmatrix} #1 \\ #2 \\ #3 \\ #4 \end{bmatrix}}
\newcommand{\yokoL}[4]{\begin{bmatrix} #1 & #2 & #3 & #4 \end{bmatrix}}
```

# はじめに関数一覧
上記URLにて確認できる、**Counts and State Visualizations**の関数は下記の通りです。
大きく分けると引数で分類することができ、

* シミュレータの実行結果(data)を受け取るもの
* ブロッホ球の座標(bloch)を受け取るもの
* シミュレータでの量子状態の表現である状態ベクトル(state)を受け取るもの

|#|関数|引数|表示するもの|備考|
|:--:|:--:|:--:|:--:|:--:|
|1|plot_histogram|data|ヒストグラム|主に測定結果表示で利用|
|2|plot_bloch_vector|bloch|ブロッホ球|単一ビット、座標指定|
|3|plot_bloch_multivector|state|ブロッホ球|複数ビット、状態ベクトル指定|
|4|plot_state_qsphere|state|qshere(球表示)|同上|
|5|plot_state_city|state|密度行列|同上|
|6|plot_state_hinton|state|密度行列|同上|
|7|plot_state_paulivec|state|密度行列|同上<br/>※パウリ行列で分解し表示|

では、下記にまとめていきます。
なお、サンプルコードは、qiskitのリファレンスを引用・一部加筆しています。

# 実行結果(data)を受け取るもの
## plot_histogram
実行結果として、ヒストグラムを表示します。
このサンプルでは、Bell状態（$\ket{00}$と$\ket{11}$が50%で重なり合った状態）を使っているのですが、利用している「qasm_simulator」が実機を意識し、ノイズを含む結果を返す仕様となっているので、00、11ともにおおよそ50%で結果が帰ってきている状況です。

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/eec11bbd-2bdd-6e80-0c87-e4b8db49fc3b.png)

<details><summary>サンプルコード</summary><div>

```python
# https://qiskit.org/documentation/stubs/qiskit.visualization.plot_histogram.htmlより引用
from qiskit import QuantumCircuit, BasicAer, execute
from qiskit.visualization import plot_histogram
%matplotlib inline

qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])

backend = BasicAer.get_backend('qasm_simulator')
job = execute(qc, backend)
plot_histogram(job.result().get_counts(), color='midnightblue', title="New Histogram")
```

</div></details>


# 座標(bloch)を受け取るもの
## plot_bloch_vector

ブロッホ球を用いた量子状態の描画を行います。
引数として、

* [X, Y, Z]　：　座標を直接指定する方法と
* [r, theta, phi] ：ラジアン（角度）で指定する方法があります

下記サンプルでは、[0,1,0]と指定しているので、$Y$基底の$\ket{i}$が表示されます

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/00b3ffad-1996-73dc-7ab6-5174c2280c70.png)

<details><summary>サンプルコード</summary><div>

```python
# https://qiskit.org/documentation/stubs/qiskit.visualization.plot_bloch_vector.htmlより引用
from qiskit.visualization import plot_bloch_vector
%matplotlib inline

plot_bloch_vector([0,1,0], title="New Bloch Sphere")
```

</div></details>

# 状態ベクトル(state)を受け取り球を表示
## plot_bloch_multivector
### エンタングルなし
シミュレータでの量子状態（状態ベクトル）を受け取りブロッホ球を表示します。
1量子系であれば１つ、複数量子系であれば複数個のブロッホ球が表示されます。
下記は、両ビットともに$H$ゲートで、$\ket{+}$状態にした状態で表示をしています。

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/abba0db5-c952-4338-c81a-dbc72c08e262.png)


<details><summary>サンプルコード</summary><div>

```python
# https://qiskit.org/documentation/stubs/qiskit.visualization.plot_bloch_multivector.htmlに加筆
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_bloch_multivector
%matplotlib inline

qc = QuantumCircuit(2)
qc.h(0)
qc.h(1)

state = Statevector.from_instruction(qc)
plot_bloch_multivector(state, title="New Bloch Multivector")
```

</div></details>

なお、複数量子系でエンタングルが発生している場合は、単一量子ビットで状態を表現ができないので、下記の様な表示となります。

### エンタングルあり
下記の様に、３量子のエンタングルが発生する$GHZ$状態では、表示ができなくなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/290aa3a6-143a-b71a-703c-1a574e2112c8.png)

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/e41e38c5-c7d2-7f2a-252b-afccedd81531.png)


<details><summary>サンプルコード</summary><div>

```python
# https://qiskit.org/documentation/stubs/qiskit.visualization.plot_bloch_multivector.htmlに加筆
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_bloch_multivector
%matplotlib inline

qc = QuantumCircuit(3)
qc.h(0)
qc.cx(0,1)
qc.cx(0,2)

state = Statevector.from_instruction(qc)
plot_bloch_multivector(state, title="New Bloch Multivector")
```

</div></details>

## plot_state_qsphere
### 確率振幅、位相が同一
qsphereという表現形式で、状態ベクトルが表示されます。
ブロッホ球は、エンタングル状態の量子状態を表示出来ませんが、qshpereでは下記の様に表示できます。

* ポインタ（◯）のサイズが、その状態（項）の出現確率を表し
* ポインタの色が、その状態（項）の位相を表現します。

Bell状態は、確率振幅も位相も同一なので、下記の様に表示されます。

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/7894d983-6eec-cabe-8752-ebfcc0a524d4.png)

<details><summary>サンプルコード</summary><div>

```python
# https://qiskit.org/documentation/stubs/qiskit.visualization.plot_state_qsphere.htmlより引用
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_state_qsphere
%matplotlib inline

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)

state = Statevector.from_instruction(qc)
plot_state_qsphere(state)
```
</div></details>


### ある項の位相を反転
一方で、下記の様に均等な重ね合わせに対して、１つの状態（項）だけ位相反転させると、
下記のような表示となります。

```math
\displaylines{
\ket{00}
\xrightarrow{H_1,H_2}
\frac{1}{2}\ket{00} + \frac{1}{2}\ket{01} + \frac{1}{2}\ket{10} + \frac{1}{2}\ket{11}
\\
\xrightarrow{CZ_{12}}
\frac{1}{2}\ket{00} + \frac{1}{2}\ket{01} + \frac{1}{2}\ket{10} \color{red}{-\frac{1}{2}}\ket{11}
}
```

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/01f6143c-6d6f-0e76-26ed-323f3aedc5fd.png)

$\ket{11}$の位相だけ反転しているので、色が異なります。


<details><summary>サンプルコード</summary><div>

```python
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_state_qsphere
%matplotlib inline

qc = QuantumCircuit(2)
qc.h([0,1])
qc.cz(0,1)

state = Statevector.from_instruction(qc)
print(state)

plot_state_qsphere(state)
```
</div></details>


# 状態ベクトル(state)を受け取り密度行列を表示
状態ベクトル$\ket{\psi}$に対し、演算子$\rho=\ketbra{\psi}{\psi}$を計算することで密度行列という状態ベクトルの行列表現を得ることができます。

https://qiita.com/shnchr/items/59a4956e352993122455

計算過程は、上記で紹介しているのですが、$Bell$状態の計算だけ抜粋して紹介すると、

```math
\ket{\psi} = \frac{1}{\sqrt{2}}(\ket{00} + \ket{11})
 =
\frac{1}{\sqrt{2}}
\left(
\tateL{1}{0}{0}{0} + 
\tateL{0}{0}{0}{1}
\right) = 
\frac{1}{\sqrt{2}}\tateL{1}{0}{0}{1}
```

上記に対して、密度行列を得る演算子$\rho=\ketbra{\psi}{\psi}$を計算すると

```math
\rho =\ketbra{\psi}{\psi} =　\frac{1}{\sqrt{2}}\frac{1}{\sqrt{2}}\tateL{1}{0}{0}{1}\yokoL{1}{0}{0}{1}
=
\frac{1}{2}
\begin{bmatrix} 
   1 & 0 & 0 & 1 \\ 
   0 & 0 & 0 & 0 \\ 
   0 & 0 & 0 & 0 \\
   1 & 0 & 0 & 1
\end{bmatrix}
```

となります。
なお、密度行列の詳細は、下記で詳しく解説されていますので、リンクさせていただきます。

https://qiita.com/snuffkin/items/356758d5c2c915154f20#%E5%AF%86%E5%BA%A6%E8%A1%8C%E5%88%97%E3%81%A7%E8%A1%A8%E7%8F%BE%E3%81%99%E3%82%8B


## plot_state_city
上記の演算子$\rho=\ketbra{\psi}{\psi}$で計算した4x4の密度行列を実部虚部分けて表示します。

### 虚部なし（Bell状態）

状態ベクトルを３次元ヒストグラムで、確率振幅（複素数）の実部・虚部分けて表示します
下記はBell状態を表示しており、Bell状態は、

```math
\ket{Bell} = \frac{1}{\sqrt{2}}\ket{00} + \frac{1}{\sqrt{2}}\ket{11}
```

ですので、確率振幅（複素数）の虚部がないのでImの方は表示されていません

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/92fd53ab-3f09-f9d9-6ee7-b42f81e16b2a.png)


<details><summary>サンプルコード</summary><div>

```python
# https://qiskit.org/documentation/stubs/qiskit.visualization.plot_state_city.html より引用
from qiskit import QuantumCircuit
from qiskit.quantum_info import DensityMatrix
from qiskit.visualization import plot_state_city
%matplotlib inline

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)

state = DensityMatrix.from_instruction(qc)
plot_state_city(state, color=['midnightblue', 'midnightblue'],
     title="New State City")
```

</div></details>

### 虚部あり（位相回転）
確率振幅（複素数）の虚部が表示されるように、1ビット目を$S$ゲートで位相回転すると、下記のようにImも表示されます

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/0ca5de69-c9d6-37b6-72a3-b6fb19519a1b.png)

<details><summary>サンプルコード</summary><div>

```python
# https://qiskit.org/documentation/stubs/qiskit.visualization.plot_state_city.html より引用
from qiskit import QuantumCircuit
from qiskit.quantum_info import DensityMatrix
from qiskit.visualization import plot_state_city
%matplotlib inline

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0,1)
qc.s(0)

state = DensityMatrix.from_instruction(qc)
plot_state_city(state, color=['midnightblue', 'midnightblue'],
     title="New State City")
```

</div></details>


## plot_state_hinton
下記のようなhinton diagramを表示します。
上記のplot_state_cityと同じ様に、実部と虚部を分けて表示しますが、
Bell状態は確率振幅（複素数）の虚部がないので、Reのみ表示されている状況です。

https://matplotlib.org/3.1.1/gallery/specialty_plots/hinton_demo.html

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/e5e610d2-4e53-6dff-f3c9-c85811df733a.png)


<details><summary>サンプルコード</summary><div>

```python
# https://qiskit.org/documentation/stubs/qiskit.visualization.plot_state_hinton.html より引用
from qiskit import QuantumCircuit
from qiskit.quantum_info import DensityMatrix
from qiskit.visualization import plot_state_hinton
%matplotlib inline

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)

state = DensityMatrix.from_instruction(qc)
plot_state_hinton(state, title="New Hinton Plot")
```

</div></details>

## plot_state_paulivec

下記は、$Bell$状態で、説明にテンソルの計算等が必要なので、1量子系で説明したいと思います。
なお、このbell状態のテンソル計算にご興味ある方はこちらを参照ください。

https://qiita.com/shnchr/items/59a4956e352993122455

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/a1ced834-51f7-53f4-d544-1684a0a58e98.png)

<details><summary>サンプルコード</summary><div>

```python
# https://qiskit.org/documentation/stubs/qiskit.visualization.plot_state_paulivec.html より引用
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_state_paulivec
%matplotlib inline

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)

state = Statevector.from_instruction(qc)
plot_state_paulivec(state, color='midnightblue',
     title="New PauliVec plot")
```

</div></details>

下記は、$H\ket{0} = \ket{+}$を表示した結果となります。

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183826/c4e1b78c-6cad-7588-802b-1f66ae455b41.png)

<details><summary>サンプルコード</summary><div>

```python
# https://qiskit.org/documentation/stubs/qiskit.visualization.plot_state_paulivec.html より引用
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_state_paulivec
%matplotlib inline

qc = QuantumCircuit(1)
qc.h(0)

state = Statevector.from_instruction(qc)
plot_state_paulivec(state, color='midnightblue',
     title="New PauliVec plot")
```

</div></details>

状態ベクトル$\ket{\psi}=\ket{+}$に対して、密度行列を得る演算子$\rho=\ketbra{\psi}{\psi}$を計算すると。

```math
\rho =\ketbra{\psi}{\psi} = \ketbra{+}{+}
= \frac{1}{\sqrt{2}}\frac{1}{\sqrt{2}}\tate{1}{1}\yoko{1}{1} = \frac{1}{2}\mtrx{1}{1}{1}{1}
```

この行列をパウリ行列で表現すると、

```math
\frac{1}{2}\mtrx{1}{1}{1}{1} = \frac{1}{2}\mtrx{1}{0}{0}{1} + \frac{1}{2}\mtrx{0}{1}{1}{0} = 0.5I + 0.5X
```

よって、

```math
\therefore \rho =0.5I + 0.5X
```

となり、上記のグラフは、演算子$\rho=\ketbra{\psi}{\psi}$のパウリ行列での成分分解の結果を表しています。



# まとめ
ということで、Qiskitの結果や状態ベクトルの可視化についてまとめてみました。
コメント、補足等あれば、よろしければ、**LGTM**頂ければ嬉しいです。