BlueqatでVariational-Quantum-Eigensolver (VQE) アルゴリズムやってみる

$$
\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}}
$$
量子ゲートシミュレータBlueqatの練習がてらVQEアルゴリズムで簡単なハミルトニアンの基底エネルギーを求めてみます。
Blueqatとは : https://blueqat.readthedocs.io/ja/latest/
VQEとは : http://dojo.qulacs.org/ja/latest/notebooks/5.1_variational_quantum_eigensolver.html
他に参考にしたページ: 
https://qiita.com/YuichiroMinato/items/62444351b712743d83b7 
http://dkopczyk.quantee.co.uk/vqe/
## 設定
今回は[こちらの記事](https://qiita.com/YuichiroMinato/items/62444351b712743d83b7)のように、状態$\ket{0} = (1, 0)^{\mathrm{T}}$にRY($\theta$)ゲートを作用させることで、パラメータ$\theta$に依存する状態$\ket{\psi(\theta)}$を作り、
いろんな$\theta$の値で内積$\braket{\psi(\theta)} {H \psi(\theta)}$の値を計算し、
[変分法](https://en.wikipedia.org/wiki/Variational_method_(quantum_mechanics))により、この内積$\braket{\psi(\theta)} {H \psi(\theta)}$が最小となる$\theta (= \theta_{\mathrm{min}})$を求めることで、基底状態$\ket{\psi(\theta_{\mathrm{min}})}$を求めることにする。
RY($\theta$)ゲートとは、状態をbloch球のy軸周りに回転させる演算である。

```math
RY(\theta) = 
\left(
    \begin{array}{cc}
            \cos{\Big( \frac{\theta}{2}\Big)} & -\sin{\Big( \frac{\theta}{2}\Big)} \\
             \sin{\Big( \frac{\theta}{2}\Big)} &  \cos{\Big( \frac{\theta}{2}\Big)}\\
    \end{array}
\right)
```

また今回はハミルトニアン$H$として、[こちらの記事](https://qiita.com/YuichiroMinato/items/62444351b712743d83b7)と同じように、パウリ行列$Z$

```math
Z = \left(
    \begin{array}{cc}
            1 & 0 \\
            0 & -1\\
    \end{array}
\right)
```

を用いる。
もともと$Z$は対角化されていて、その基底状態は$\ket{1} = (0, 1)^{\mathrm{T}}$(の複素数倍)とわかるので、今回のパラメータ$\theta$探索では、$\theta = \pi$が基底状態を与えるパラメータであることが求まれば成功である。
なぜなら、今回の設定では

```math
\ket{\psi(\theta = \pi)} = \left(
    \begin{array}{cc}
            \cos{\Big( \frac{\pi}{2}\Big)} & -\sin{\Big( \frac{\pi}{2}\Big)} \\
             \sin{\Big( \frac{\pi}{2}\Big)} &  \cos{\Big( \frac{\pi}{2}\Big)}\\
    \end{array}
\right)
 \left(
    \begin{array}{c}
            1  \\
             0 \\
    \end{array}
\right)
=
\left(
    \begin{array}{cc}
            0 & -1 \\
            1 &  0\\
    \end{array}
\right)
 \left(
    \begin{array}{c}
            1  \\
             0 \\
    \end{array}
\right)
=
 \left(
    \begin{array}{c}
            0  \\
             1 \\
    \end{array}
\right)
```

だからである。

## 実際にBlueqatを使ってやってみる
jupyter notebookで行う。
Blueqatインストールしていない場合は以下でpipインストールする。

```
!pip3 install blueqat
```

今回使用するライブラリをインポート

```
import numpy as np
import matplotlib.pyplot as plt
from blueqat import Circuit
```

まずはパラメータの候補として、$0$から$2\pi$までを20等分した物を用意する。

```
angles = np.linspace(0.0,2*np.pi,20)
angles
# array([0.        , 0.33069396, 0.66138793, 0.99208189, 1.32277585,
#       1.65346982, 1.98416378, 2.31485774, 2.64555171, 2.97624567,
#       3.30693964, 3.6376336 , 3.96832756, 4.29902153, 4.62971549,
#       4.96040945, 5.29110342, 5.62179738, 5.95249134, 6.28318531])
```

まずは4個目の角度(angle[3] = 0.99208189)を使って、内積$\braket{\psi(\theta)} {H \psi(\theta)}$を計算してみる。
Blueqatでは、まず回路(Circuit())を用意し、そこにゲート(今回はRYゲート)を追加していくことでゲート回路が構築できる。
RYゲートは以下のように、ry({角度})[{作用させる量子ビット番号}]を追加させれば良い。

```
# 回路
Circuit().ry(angles[3])[0]
```

また、ゲート回路に対してrunメソッドを実行させると、その段階での状態ベクトルがnumpyで得られる。

```
# 初期状態なので| 0>
Circuit().run()
# array([1.+0.j])

# | 0>にRYゲートを作用させた後の状態
Circuit().ry(angles[3])[0].run()
# array([0.87947375+0.j, 0.47594739+0.j])
```

それでは、実際に内積$\braket{\psi(\theta)} {H \psi(\theta)}$を計算する。
まず、$\ket{\psi(\theta)}$は以下のようになり、

```
psi = Circuit().ry(angles[3])[0].run()
psi
# array([0.87947375+0.j, 0.47594739+0.j])
```

続いて、$\ket{H \psi(\theta)}$は以下のようになる。

```
h_psi = Circuit().ry(angles[3])[0].z[0].run()
h_psi
# array([ 0.87947375+0.j, -0.47594739+0.j])
```

これらより、内積$\braket{\psi(\theta)} {H \psi(\theta)}$は以下のようになる。

```
np.dot(psi, h_psi)
# (0.5469481581224267+0j)
```

それでは、この内積を最初に作った20個の角度に対して計算し、横軸を角度、縦軸を内積でプロットし、線を引くと以下のようになる。

```
energies = []
for angle in angles:
    psi = Circuit().ry(angle)[0].run()
    z_psi = Circuit().ry(angle)[0].z[0].run()
    energies.append(np.dot(psi, z_psi))
plt.xlabel('angle') 
plt.ylabel('Expectation value') 
plt.plot(angles, energies) 
plt.show() 
```
<img width="426" alt="スクリーンショット 2020-02-09 20.52.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331208/3a0d9273-3131-54ba-7c0f-b8b2735245a3.png">

確かに$\theta = 3$付近で最小値を取っているようなので、VQEアルゴリズム成功である。
ちなみに、パラメータ$\theta$に依存する状態$\ket{\psi(\theta)}$を作るとき、RY($\theta$)ゲートの代わりにRX($\theta$)ゲートを用いてもVQEアルゴリズムは成功する。
しかし、RZ($\theta$)ゲートでは成功しない。
それはRZ($\theta$)は

```math
RZ(\theta) = 
\left(
    \begin{array}{cc}
            e^{-i\frac{\theta}{2}} & 0 \\
             0 &  e^{ i\frac{\theta}{2}}\\
    \end{array}
\right)
```
という形をしているため、これによって作成される状態$\ket{\psi(\theta)}$は

```math
\ket{\psi(\theta)} = \left(
    \begin{array}{cc}
            e^{-i\frac{\theta}{2}} & 0 \\
             0 &  e^{ i\frac{\theta}{2}}\\
    \end{array}
\right)
 \left(
    \begin{array}{c}
            1  \\
             0 \\
    \end{array}
\right)
=
 \left(
    \begin{array}{c}
            e^{-i\frac{\theta}{2}}  \\
             0 \\
    \end{array}
\right)
=
e^{-i\frac{\theta}{2}}
\left(
    \begin{array}{c}
            1  \\
             0 \\
    \end{array}
\right)
```
となり、どんなパラメータ$\theta$の値でも、基底状態である$\ket{1} = (0, 1)^{\mathrm{T}}$(の複素数倍)は作れないからである。
## 最後に
量子コンピュータ面白