量子情報理論の基本：フィデリティ

$$
\def\bra#1{\mathinner{\left\langle{#1}\right|}}
\def\ket#1{\mathinner{\left|{#1}\right\rangle}}
\def\braket#1#2{\mathinner{\left\langle{#1}\middle|#2\right\rangle}}
$$

## はじめに

量子情報理論の基本の基として、おさえておくべき事項の中で、２つの量子状態の違いについてのお話が残っていました。よく使われる指標として「フィデリティ(fidelity)」と「トレース距離(trace distance)」というものがあります。今回は、フィデリティについて勉強してみます。どのように定義されるのか、また、どんな性質があるのかということを説明した後で、量子計算シミュレータ[qlazy](https://github.com/samn33/qlazy)を使って、その重要な性質について、実際に計算して実感してみたいと思います。

参考にさせていただいたのは、以下の文献です。

1. [ニールセン、チャン「量子コンピュータと量子通信（３）」オーム社（2005年）](https://www.ohmsha.co.jp/book/9784274200090/)
2. [石坂、小川、河内、木村、林「量子情報科学入門」共立出版（2012年）](https://www.kyoritsu-pub.co.jp/bookdetail/9784320122994)
3. [富田「量子情報工学」森北出版（2017年）](https://www.morikita.co.jp/books/book/3109)

## フィデリティの定義

### 内積の絶対値

フィデリティ(fidelity)は、日本語では「忠実度」と訳されますが、要は２つの状態の類似度を表す指標です。純粋状態の類似度として、直感的にわかりやすいのは内積です。２つの純粋状態を各々$\ket{\phi},\ket{\psi}$とすると、内積の絶対値は以下のように表現でき、これをフィデリティ$F(\rho,\sigma)$の定義とします。

```math
F(\ket{\phi},\ket{\psi}) = |\braket{\phi}{\psi}|  \tag{1}
```

通常、純粋状態はノルム１に正規化されているので、純粋状態のフィデリティはヒルベルト空間上の２つのベクトルのなす角のコサインの絶対値であると解釈できます。したがって、両者直交している場合は０（最小値）となり、平行の場合は１（最大値）となります。

混合状態のフィデリティは、これの拡張版として定義されます。[前回の記事](https://qiita.com/SamN/items/afb800bc7574f2211220)で説明した「純粋化」をここで登場させます。任意の混合状態は適当な参照系をアンシラとして追加することで、形式的に純粋状態にすることができるというお話でした。いま、２つの混合状態を$\rho,\sigma$とし、各々を純粋化した状態を$\ket{\phi},\ket{\psi}$とします。その内積の絶対値$|\braket{\phi}{\psi}|$をフィデリティと定義します、と単純に言えれば良いのですが、そう簡単にはいきません。純粋化で得られる状態には参照系に関するユニタリの自由度があり、一意には決まらないのでした。そこで、あり得る純粋状態のすべてを考えて、その最大値をフィデリティの定義とします。つまり、フィデリティ$F(\rho,\sigma)$を

```math
F(\rho,\sigma) = \max_{\ket{\phi},\ket{\psi}} |\braket{\phi}{\psi}|  \tag{2}
```

のように定義してみます。しかし、$max$が含まれている表式では使い勝手がよろしくないので、何とかしたいと思うわけです。そのため、ちょっと回り道をして、以下の２つのことを確認しておきます。

* ユニタリの自由度を含んだ純粋化の表現
* 演算子のトレースノルム

### ユニタリの自由度を含んだ純粋化の表現

まず、純粋化の結果として得られる純粋状態を、ユニタリの自由度を含んだ形に表現し直します。[
前回の記事](https://qiita.com/SamN/items/afb800bc7574f2211220)で見たように、注目系Aにおける混合状態、

```math
\rho_{A} = \sum_{k=1}^{d} \lambda_{k} \ket{k}_{A} \bra{k}_{A}  \tag{3}
```

の純粋化は、参照系Rにおける適当な正規直交基底$\\{ \ket{k}_{R} \\}$を使って、

```math
\ket{\phi} = \sum_{k=1}^{d} \sqrt{\lambda_{k}} \ket{k}_{A} \ket{k}_{R}  \tag{4}
```

のように表すことができます。これは、以下のように書くこともできます[^1]。

[^1]: $\rho=\sum_{k} \lambda_{k} \ket{k}^{A} \bra{k}^{A}$から、容易にわかると思います。

```math
\ket{\phi} = (\sqrt{\rho} \otimes I_{R}) \sum_{k=1}^{d} \ket{k}_{A} \ket{k}_{R}  \tag{5}
```

ところが、ユニタリの自由度があるので、参照系R上で定義されるユニタリ演算子$U_{R}$を用いて、

```math
\ket{\tilde{\phi}} = (\sqrt{\rho} \otimes I_{R}) \sum_{k=1}^{d} \ket{k}_{A} U_{R} \ket{k}_{R}  \tag{6}
```

と書くこともできます[^2]。

この式は、行列$U_{R}^{T}$を行列$U_{A}$とおき、$U_{A}$を注目系Aでのユニタリ演算子と同一視することで、以下のようにも表現できます。

[^2]: これは大丈夫ですよね。ユニタリの自由度があるということを素直に表しているだけです。

```math
\ket{\tilde{\phi}} = (\sqrt{\rho} \otimes I_{R}) \sum_{k=1}^{d} U_{A} \ket{k}_{A} \ket{k}_{R}  \tag{7}
```

これはそれほど自明ではないので、以下で証明してみます。

【証明】

```math
\begin{align}
& \sum_{k=1}^{d} \ket{k}_{A} U_{R} \ket{k}_{R} \\
&= \sum_{k=1}^{d} \sum_{i=1}^{d} \ket{k}_{A} \ket{i}_{R} \bra{i}_{R} U_{R} \ket{k}_{R} \\
&= \sum_{k=1}^{d} \sum_{i=1}^{d} (U_{R})_{ik} \ket{k}_{A} \ket{i}_{R} \\
&= \sum_{k=1}^{d} \sum_{i=1}^{d} (U_{R}^{T})_{ki} \ket{k}_{A} \ket{i}_{R} \\
&= \sum_{i=1}^{d} \sum_{k=1}^{d} (U_{R}^{T})_{ik} \ket{i}_{A} \ket{k}_{R} \\
&= \sum_{i=1}^{d} \sum_{k=1}^{d} \bra{i}_{A} U_{A} \ket{k}_{A} \ket{i}_{A} \ket{k}_{R} \\
&= \sum_{k=1}^{d} U_{A} \ket{k}_{A} \ket{k}_{R}  \tag{8}
\end{align}
```

したがって、

```math
\begin{align}
\ket{\tilde{\phi}} &= (\sqrt{\rho} \otimes I_{R}) \sum_{k=1}^{d} \ket{k}_{A} U_{R} \ket{k}_{R}  \\
&= (\sqrt{\rho} \otimes I_{R}) \sum_{k=1}^{d} U_{A} \ket{k}_{A} \ket{k}_{R}  \tag{9}
\end{align}
```

となります。（証明終）


### 演算子のトレースノルム

次に、回り道の２つ目です。「演算子のトレースノルム」を定義したいのですが、その前に「演算子のノルム（または絶対値）」を定義します。線形演算子$A$のノルム$|A|$は、

```math
|A| \equiv \sqrt{A^{\dagger} A}  \tag{10}
```

と定義されます。$|A|$と書きますが、行列式ではありません。演算子のノルムは数値ではなく演算子ですので、ご注意ください。$A^{\dagger} A$のスペクトル分解を

```math
A^{\dagger} A = \sum_{i} |\lambda_{i}|^{2} \ket{i} \bra{i}  \tag{11}
```

とすると、式(10)は、

```math
|A| = \sqrt{A^{\dagger} A} = \sum_{i} |\lambda_{i}| \ket{i} \bra{i}  \tag{12}
```

と書くことができます。演算子のトレースノルム$||A||$は、これのトレースと定義されます。すなわち、

```math
||A|| \equiv Tr |A| = Tr \sqrt{A^{\dagger} A} = \sum_{i} |\lambda_{i}|  \tag{13}
```

です。

$A$のトレースノルムは、ユニタリ演算子$V$を用いて、実は、

```math
||A|| = \max_{V} |Tr(AV)|  \tag{14}
```

のように表すこともできます。以下で証明します。

【証明】

まず、$A$をユニタリ演算子$U$を使って、

```math
A = U|A|  \tag{15}
```

のように極分解します[^3]。

[^3]: 任意の線形演算子$A$に対して、あるユニタリ演算子（正確には等距離演算子）$U$があって、$A = U|A|$と表すことができるという定理があります。詳細は[量子情報科学入門](https://www.kyoritsu-pub.co.jp/bookdetail/9784320122994)の付録をご参照ください。直感的には、$A^{\dagger} A$を計算してみれば、確かにそうだということがわかると思います。任意の複素数$z$を$z=|z|e^{i\theta}$と表すことができますが、それに少し似ています。


```math
\begin{align}
Tr(AV) &= Tr(U|A|V) = Tr(|A|VU) \\
&= \sum_{i} \bra{i} \sum_{j} |\lambda_{j}| \ket{j} \bra{j} VU \ket{i} \\
&= \sum_{i} \sum_{j} |\lambda_{j}| \delta_{ij} \bra{j} VU \ket{i} \\
&= \sum_{i} |\lambda_{i}| \bra{i} VU \ket{i} \tag{16}
\end{align}
```

において、$VU$はユニタリ（つまり、ベクトルの長さを変えない演算）なので、

```math
|\bra{i} VU \ket{i}| \leq 1  \tag{17}
```

が成り立ちます。したがって、式(16)は、

```math
Tr(AV) \leq \sum_{i} |\lambda_{i}| = ||A||  \tag{18}
```

となり、

```math
||A|| = \max_{V} |Tr(AV)|  \tag{14}
```

が証明されました。ちなみに、式(17)からわかるように、$VU = I$のときに最大値になります。（証明終）


### Uhlmannの定理

さて、それでは、式(2)の$max$を使わない表式を導出する準備が整いました。注目系Aにおける２つの混合状態を$\rho,\sigma$とし、参照系Rを使った純粋化を各々、以下のように書くことにします。ここで、式(7)の表現を使います。

```math
\begin{align}
\ket{\tilde{\phi}} &= (\sqrt{\rho} \otimes I_{R}) \sum_{k} U_{A} \ket{k}_{A} \ket{k}_{R} \\
\ket{\tilde{\psi}} &= (\sqrt{\sigma} \otimes I_{R}) \sum_{k} U_{A} \ket{k}_{A} \ket{k}_{R} \tag{19}
\end{align}
```

これを使って、式(2)のフィデリティを計算します。

```math
\begin{align}
F(\rho,\sigma) &= \max_{U_{A},V_{A}} |\braket{\tilde{\phi}}{\tilde{\psi}}| \\
&= \max_{U_{A},V_{A}} |\sum_{k,l} \bra{k}_{A} \bra{k}_{R} U_{A}^{\dagger} \sqrt{\rho} \sqrt{\sigma} V_{A} \ket{l}_{A} \ket{l}_{R}| \\
&= \max_{U_{A},V_{A}} |\sum_{k} \bra{k}_{A} U_{A}^{\dagger} \sqrt{\rho} \sqrt{\sigma} V_{A} \ket{k}_{A}| \\
&= \max_{U_{A},V_{A}} |Tr(U_{A}^{\dagger} \sqrt{\rho} \sqrt{\sigma} V_{A})| \\
&= \max_{U_{A},V_{A}} |\sqrt{\rho} \sqrt{\sigma} W)| \tag{20}
\end{align}
```

ここで、$W=V_{A} U_{A}^{\dagger}$とおきました。式(14)を使うと、

```math
F(\rho,\sigma) = ||\sqrt{\rho} \sqrt{\sigma}||  \tag{21}
```

となります。これで、maxを使わないフィデリティの表式が得られました。これを「Uhlmannの定理」と言います[^4]。


[^4]: [ニールセン、チャン](https://www.ohmsha.co.jp/book/9784274200090/)と[量子情報科学入門](https://www.kyoritsu-pub.co.jp/bookdetail/9784320122994)では、式(21)をフィデリティの定義として式(2)が成り立つことをもって「Uhlmannの定理」という説明がされていました。今回の記事では、[量子情報工学](https://www.morikita.co.jp/books/book/3109)の議論進行に従い、逆の流れで証明しました。その方が直感的にわかりやすいと思ったからです。


## フィデリティの性質

フィデリティの定義がわかったので、次にいくつかの重要な性質について説明します。

### (1) 交換について対称

```math
F(\rho,\sigma) = F(\sigma,\rho)  \tag{22}
```

が成り立ちます。定義より明らかです。

### (2) 同じ状態に対するフィデリティは１

```math
\rho = \sigma \Leftrightarrow F(\rho,\sigma) = 1  \tag{23}
```

が成り立ちます。密度演算子がエルミートでトレースが１という性質を使えば、簡単にわかります。

【証明】

```math
F(\rho,\rho) = ||\sqrt{\rho} \sqrt{\rho}|| = ||\rho|| = Tr|\rho| = Tr(\rho) = 1 \tag{24}
```

（証明終）

### (3) 直交している状態のフィデリティは０

```math
\rho \sigma = 0 \Leftrightarrow F(\rho,\sigma) = 0  \tag{25}
```

が成り立ちます。定義より明らかです。

### (4) フィデリティの取りうる値は０から１

式(2)の右辺の内積の絶対値は、

$0 \leq |\braket{\phi}{\psi}| \leq 1$なので、フィデリティの取りうる値は０から１です。

### (5) 直積状態のフィデリティは積

```math
F(\rho_{1} \otimes \rho_{2},\sigma_{1} \otimes \sigma_{2}) = F(\rho_{1},\sigma_{1}) F(\rho_{2},\sigma_{2})  \tag{26}
```

が成り立ちます。

【証明】

```math
\begin{align}
F(\rho_{1} \otimes \rho_{2},\sigma_{1} \otimes \sigma_{2})
&= ||(\sqrt{\rho_{1}} \otimes \sqrt{\rho_{2}}) (\sqrt{\sigma_{1}} \otimes \sqrt{\sigma_{2}})|| \\
&= ||\sqrt{\rho_{1}} \sqrt{\sigma_{1}} \otimes \sqrt{\rho_{2}} \sqrt{\sigma_{2}}|| \\
&= Tr |\sqrt{\rho_{1}} \sqrt{\sigma_{1}} \otimes \sqrt{\rho_{2}} \sqrt{\sigma_{2}}| \\
&= Tr (\sqrt{\rho_{1}} \sqrt{\sigma_{1}} \otimes \sqrt{\rho_{2}} \sqrt{\sigma_{2}}) \\
&= Tr (\sqrt{\rho_{1}} \sqrt{\sigma_{1}}) Tr(\sqrt{\rho_{2}} \sqrt{\sigma_{2}}) \\
&= Tr |\sqrt{\rho_{1}} \sqrt{\sigma_{1}}| Tr|\sqrt{\rho_{2}} \sqrt{\sigma_{2}}| \\
&= F(\rho_{1},\sigma_{1}) F(\rho_{2},\sigma_{2})  \tag{27}
\end{align}
```

（証明終）

### (6) あらゆる物理過程でフィデリティは減少しない（単調性または非減少性）

ある物理過程を表す量子チャネルを$\Gamma$とすると、

```math
F(\rho,\sigma) \leq F(\Gamma(\rho),\Gamma(\sigma))  \tag{28}
```

が成り立ちます[^5]。

[^5]: 最初にあった識別可能な特徴をもった２つの状態が、環境系と相互作用しながら次第に平衡状態に達して識別不能になっていくという風に考えれば良いと思います。一瞬、大小関係が逆じゃね？と思った方は速攻誤解を正しましょう（自分のことです、汗）。

【証明】

$\rho,\sigma$の純粋化を各々$\ket{\phi},\ket{\psi}$とします。環境系Eの適当な状態として$\ket{0}_{E}$をもってきて追加し（テンソル積をとり）、$U$でユニタリ変換して、環境系をトレースアウトしたものが量子チャネルです。全体系の純粋状態に対する変化は、

```math
\begin{align}
\ket{\phi} \ket{0}_{E} & \rightarrow U \ket{\phi} \ket{0}_{E} \\
\ket{\psi} \ket{0}_{E} & \rightarrow U \ket{\psi} \ket{0}_{E} \tag{29}
\end{align}
```

であり、フィデリティは純粋化した状態の内積の絶対値の最大値だったので、

```math
\begin{align}
F(\Gamma(\rho), \Gamma(\sigma)) &\geq |\bra{\phi} \bra{0}_{E} U^{\dagger} U \ket{\psi} \ket{0}_{E} | \\
&= |\braket{\phi}{\psi}| = F(\rho,\sigma) \tag{30}
\end{align}
```

です。（証明終）

### (7) フィデリティの強凹性

```math
F(\sum_{i} p_{i} \rho_{i}, \sum_{i} q_{i} \sigma_{i}) \geq \sum_{i} \sqrt{p_{i} q_{i}} F(\rho_{i},\sigma_{i})  \tag{31}
```

が成り立ちます[^6]。

[^6]: なぜこれを「凹性」というのか？$\space 0 \leq p \leq 1$となる$p$に対し、関数$f(x)$が$f(px_{1} + (1-p)x_{2}) \leq pf(x_{1}) + (1-p)f(x_{2})$という性質を満たすとき、その関数$f$を凸関数と言い（関数のカーブを思い描くと上に凸ですよね）、不等号が逆の場合、凹関数と言います（こっちは逆に下に凸ですね、すなわち上に凹）。このアナロジーで理解しておけば良いと思います。ここでは「強凹性」のみを取り上げましたが、「強」がつかない「凹性」もあります。[ニールセン、チャン](https://www.ohmsha.co.jp/book/9784274200090/)にいくつかのバリエーションが紹介されています。

【証明】

$\ket{\phi_i},\ket{\psi_i}$は、$F(\rho_{i},\sigma_{i})=\braket{\phi_{i}}{\psi_{i}}$を満たすように選んだ$\rho_{i},\\sigma_{i}$の純粋化とします。適当な正規直交系$\\{ \ket{i} \\}$をもってきて、以下の状態を定義します。

```math
\begin{align}
\ket{\phi} &= \sum_{i} \sqrt{p_{i}} \ket{\phi_{i}} \ket{i} \\
\ket{\psi} &= \sum_{i} \sqrt{q_{i}} \ket{\psi_{i}} \ket{i} \tag{32}
\end{align}
```

ここで、$\ket{\phi},\ket{\psi}$は各々$\sum_{i} p_{i} \rho_{i}$および$\sum_{i} q_{i} \sigma_{i}$の純粋化なので、

```math
\begin{align}
F(\sum_{i} p_{i} \rho_{i}, \sum_{i} q_{i} \sigma_{i}) &\geq |\braket{\phi}{\psi}| \\
&= \sum_{i} \sqrt{p_{i} q_{i}} \braket{\phi}{\psi} \\
&= \sum_{i} \sqrt{p_{i} q_{i}} F(\rho_{i},\sigma_{i})  \tag{33}
\end{align}
```

です。（証明終）


## シミュレータで確認

それでは、上で示したフィデリティの性質のうち、６番目の「あらゆる物理過程で減少しない」という性質に注目し、それが本当なのかどうかをシミュレータで確認してみます。具体的には、２つの密度演算子をランダムに作成して、ランダムに作った量子チャネル（参照系＋環境系を追加して純粋化した状態に対してランダムなユニタリ変換を実施し最後にトレースアウトする、というやり方で定義しました）を通した結果、フィデリティが確かに減少しない（＝増加する）ということを見てみます。

全体のPythonコードは以下です。

【2021.9.5追記】[qlazy](https://github.com/samn33/qlazy)最新版でのソースコードは[ここ](https://github.com/samn33/qlazy/blob/master/example/py/Fidelity)に置いてあります。

```python
import random
import numpy as np
from scipy.stats import unitary_group
from qlazypy import QState, DensOp

def random_densop(qnum_tar,qnum_ref,qnum_env):

    dim_pur = 2**(qnum_tar+qnum_ref)
    vec_pur = np.array([0.0]*dim_pur)
    vec_pur[0] = 1.0
    mat_pur = unitary_group.rvs(dim_pur)
    vec_pur = np.dot(mat_pur, vec_pur)

    dim_env = 2**qnum_env
    vec_env = np.array([0.0]*dim_env)
    vec_env[0] = 1.0

    vec_whole = np.kron(vec_pur,vec_env)

    qs = QState(vector=vec_whole)
    de = DensOp(qstate=[qs],prob=[1.0])

    qs.free()
    return de

def random_unitary(qnum):

    dim = 2**qnum
    mat = unitary_group.rvs(dim)
    
    return mat
    
if __name__ == '__main__':

    # settings
    qnum_tar = 2  # system A : target system
    qnum_ref = 2  # system R : reference system
    qnum_env = 2  # system E : environment system
    qnum_whole = qnum_tar + qnum_ref + qnum_env

    # two random states in system A+R+E (A+R:set randomly, E:set |0> initialy)
    de1_whole = random_densop(qnum_tar,qnum_ref,qnum_env)
    de2_whole = random_densop(qnum_tar,qnum_ref,qnum_env)

    # two states in system A (trace out R+E)
    de1_ini = de1_whole.partial(id=list(range(qnum_tar)))
    de2_ini = de2_whole.partial(id=list(range(qnum_tar)))

    # fidelity for initial states
    fid_ini = de1_ini.fidelity(de2_ini)

    # unitary transformation for whole system
    U = random_unitary(qnum_whole)
    de1_whole.apply(U)
    de2_whole.apply(U)

    # two states in system A (trace out R+E)
    de1_fin = de1_whole.partial(id=list(range(qnum_tar)))
    de2_fin = de2_whole.partial(id=list(range(qnum_tar)))
    
    # fidelity for final states
    fid_fin = de1_fin.fidelity(de2_fin)

    # result
    print("* fidelity(ini) =", fid_ini)
    print("* fidelity(fin) =", fid_fin)

    if fid_ini < fid_fin:
        print("OK!")
    else:
        print("NG!")

    # free memory
    de1_whole.free()
    de2_whole.free()
    de1_ini.free()
    de2_ini.free()
    de1_fin.free()
    de2_fin.free()
```

何をやっているか、順に説明します。

```python
# settings
qnum_tar = 2  # system A : target system
qnum_ref = 2  # system R : reference system
qnum_env = 2  # system E : environment system
qnum_whole = qnum_tar + qnum_ref + qnum_env
```

まず、量子ビット数を適当に設定します。密度演算子が定義されている注目系Aの量子ビット数を２、それを純粋化するための参照系Rの量子ビットを２、注目系Aの周囲を取り巻く環境系Eの量子ビットを２とします。

```python
# two random states in system A+R+E (A+R:set randomly, E:set |0> initialy)
de1_whole = random_densop(qnum_tar,qnum_ref,qnum_env)
de2_whole = random_densop(qnum_tar,qnum_ref,qnum_env)
```

全体系に対する純粋状態をランダムに作ります。random_densop関数で実行しています。その中身を見てみます。

```python
dim_pur = 2**(qnum_tar+qnum_ref)
vec_pur = np.array([0.0]*dim_pur)
vec_pur[0] = 1.0
mat_pur = unitary_group.rvs(dim_pur)
vec_pur = np.dot(mat_pur, vec_pur)

dim_env = 2**qnum_env
vec_env = np.array([0.0]*dim_env)
vec_env[0] = 1.0

vec_whole = np.kron(vec_pur,vec_env)

qs = QState(vector=vec_whole)
de = DensOp(qstate=[qs],prob=[1.0])
```

最初の４行で、注目系Aと参照系Rを合わせた系で定義される $\ket{0}^A\ket{0}^R$ に相当するベクトルを作成し、scipyの関数で作ったランダムなユニタリ演算を実施して、ランダムな純粋状態を作り、変数vec_purに格納します。注目系Aの密度演算子をまず作って純粋化すべきところですが、純粋化したものをランダムに用意することにしました（すみません、処理を端折りました。同じことなので）。次に、環境系Eに関して、$\ket{0}^{E}$に相当するベクトルを作成し、変数vec_envに格納します。２つのベクトルのテンソル積（クロネッカー積）をnumpyの関数を使って実行し、変数vec_wholeに格納します。これで、注目系でのランダムな密度演算子に対応した、全体系の純粋状態ができたことになります。これに基づき、密度演算子のインスタンスdeを生成し、リターンします。

main部に戻ります。

```python
# two states in system A (trace out R+E)
de1_ini = de1_whole.partial(id=list(range(qnum_tar)))
de2_ini = de2_whole.partial(id=list(range(qnum_tar)))
```

全体系の密度演算子から参照系と環境系をトレースアウトして、注目系に注目します。密度演算子に対するpatialメソッドに引数として注目系の量子番号リストを与えることで実行できます。今の場合、引数には[0,1]が入ることになります。これで、２つのランダムな初期密度関数が得られたので、、、

```python
# fidelity for initial states
fid_ini = de1_ini.fidelity(de2_ini)
```

で、本日のメインイベントであるフィデリティを計算します。qlazypyの密度演算子クラスDensOpにfidelityメソッドを追加しました(v0.0.27)。この１行で終わりです。中ではnumpy.linlagを使っていて、固有値問題を解いて得られた固有値のルートを計算するとか、トレースを計算するとか、やっています。

```python
# unitary transformation for whole system
U = random_unitary(qnum_whole)
de1_whole.apply(U)
de2_whole.apply(U)
```

random_unitary関数でランダムなユニタリ行列を取得します。関数定義を見ていただければわかる通り、scipyの関数を召喚しています。このユニタリを全体系の密度演算子に施すため、密度演算子クラスDensOpのapplyメソッドを使っています。これで、初期状態がランダムに定義された量子チャネルを通ったことになります。

```python
# two states in system A (trace out R+E)
de1_fin = de1_whole.partial(id=list(range(qnum_tar)))
de2_fin = de2_whole.partial(id=list(range(qnum_tar)))
```

量子チャネルを通った後の状態に対して、部分トレースをとり、注目系での密度演算子を取得します。

```python
# fidelity for final states
fid_fin = de1_fin.fidelity(de2_fin)
```

先ほどと同様、フィデリティを計算します。

```python
# result
print("* fidelity(ini) =", fid_ini)
print("* fidelity(fin) =", fid_fin)

if fid_ini <= fid_fin:
    print("OK!")
else:
    print("NG!")
```

結果を表示します。フィデリティが増加していれば「OK!」、そうでなければ「NG!」を表示します。

さて、実行結果です。

```
* fidelity(ini) = 0.7344321087768828
* fidelity(fin) = 0.9503724941444357
OK!
```

というわけで、フィデリティが増加していることがわかります。何度も実行しましたが必ず増加しました。


## おわりに

「はじめに」で述べましたが、量子状態の違いを定量化する指標として、今回説明した「フィデリティ」の他に、「トレース距離」というものもあります。これは名前の通り、状態がどれだけ離れているかを表す指標です。なので「フィデリティ」とはちょうど逆の関係にあります。この指標もよく使われるということなので、次回は「トレース距離」について勉強したいと思います。

以上