$$
\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/
設定
今回はこちらの記事のように、状態$\ket{0} = (1, 0)^{\mathrm{T}}$にRY($\theta$)ゲートを作用させることで、パラメータ$\theta$に依存する状態$\ket{\psi(\theta)}$を作り、
いろんな$\theta$の値で内積$\braket{\psi(\theta)} {H \psi(\theta)}$の値を計算し、
変分法により、この内積$\braket{\psi(\theta)} {H \psi(\theta)}$が最小となる$\theta (= \theta_{\mathrm{min}})$を求めることで、基底状態$\ket{\psi(\theta_{\mathrm{min}})}$を求めることにする。
RY($\theta$)ゲートとは、状態をbloch球のy軸周りに回転させる演算である。
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$として、こちらの記事と同じように、パウリ行列$Z$
Z = \left(
\begin{array}{cc}
1 & 0 \\
0 & -1\\
\end{array}
\right)
を用いる。
もともと$Z$は対角化されていて、その基底状態は$\ket{1} = (0, 1)^{\mathrm{T}}$(の複素数倍)とわかるので、今回のパラメータ$\theta$探索では、$\theta = \pi$が基底状態を与えるパラメータであることが求まれば成功である。
なぜなら、今回の設定では
\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()
確かに$\theta = 3$付近で最小値を取っているようなので、VQEアルゴリズム成功である。
ちなみに、パラメータ$\theta$に依存する状態$\ket{\psi(\theta)}$を作るとき、RY($\theta$)ゲートの代わりにRX($\theta$)ゲートを用いてもVQEアルゴリズムは成功する。
しかし、RZ($\theta$)ゲートでは成功しない。
それはRZ($\theta$)は
RZ(\theta) =
\left(
\begin{array}{cc}
e^{-i\frac{\theta}{2}} & 0 \\
0 & e^{ i\frac{\theta}{2}}\\
\end{array}
\right)
という形をしているため、これによって作成される状態$\ket{\psi(\theta)}$は
\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}}$(の複素数倍)は作れないからである。
最後に
量子コンピュータ面白