この記事に関して
ここではpythonライブラリのblueqatを用いて量子プログラミングを行っていこうと思います。
内容は公式のチュートリアルを元に作成しています。
今回は VQE を実装していきます。
VQE
詳しい理論はここに述べています。
このアルゴリズムはハミルトニアン(エルミート行列)の固有値を量子コンピュータと
古典コンピューターを用いて近似的に求めるものです。
ハミルトニアンを $H$ とし、これに対する固有値を $E_0$ とします。
このとき量子変分原理から、一般の状態 $\left|\psi\right>$ に対し、 $\left<\psi\right|H\left|\psi\right> ≧ E_0$ となります。
このことから $\left|\psi\right>$ を自由に動かして、$\left<\psi\right|H\left|\psi\right>$ の最小値を求めればいいことがわかります。
アルゴリズムの流れ
流れは以下のようになります。
1 . 自由に動かす状態は $\theta$ でパラメータ表示された状態 $\left|\psi(\theta)\right>$ とし、これと $H\left|\psi(\theta)\right>$ を量子コンピューターで計算する。
2 . 古典コンピュータで $\left<\psi(\theta)\right|H\left|\psi(\theta)\right>$ を計算する。
3 . $\left<\psi(\theta)\right|H\left|\psi(\theta)\right>$ が最小値でなければ、$\theta$ を更新する。最小値であればそれは $E_0$ の近似解である。
実装 1
blueqat を用いて実装します。
今回はハミルトニアン $H = Z$ としておきます。
$Z$ の固有値は $1, -1$ です。
$\left|\psi(\theta)\right> = R_y(\theta)\left|0\right>$ とし、$\theta$ は $(0≦\theta<2\pi)$ とします。
from blueqat import Circuit
import numpy as np
import matplotlib.pyplot as plt
import math
# θの初期値、重み、誤差
th, w, d = 1.0, 0.4, 0.005
while True:
d_ry = Circuit().ry(th+math.pi)[0].run()
_ry = Circuit().ry(th)[0].run()
hd_ry = Circuit().ry(th+math.pi)[0].z[0].run()
h_ry = Circuit().ry(th)[0].z[0].run()
'''
d_ry = (-sin(θ/2) cos(θ/2)) => (d/dθ)|ψ(0)>
_ry = (cos(θ/2) sin(θ/2)) => |ψ(0)>
hd_ry = (-sin(θ/2) -cos(θ/2)) => (d/dθ)H|ψ(0)>
h_ry = (cos(θ/2) -sin(θ/2)) => H|ψ(0)>
'''
# 位相処理
if math.sin(th/2.0) >= 0.0:
d_ry = -d_ry
hd_ry = -hd_ry
if math.cos(th/2.0) < 0.0:
_ry = -_ry
h_ry = -h_ry
# 勾配
ds_th = (np.dot(d_ry, h_ry) + np.dot(_ry, hd_ry))*(1/2.0) # -sinθ
# θの更新
th = th - w*ds_th*th
# 誤差範囲
if ds_th <= d and ds_th >= -d:
s_th = np.dot(_ry, h_ry) # 期待値
print(i) # 回数
break
print(th) # θ
print(s_th) # 固有値
結果
3
(3.140573290275759+0j)
(-0.9999922075939599+0j)
上手く固有値を取り出すことができました。
実装 2
blueqat を用いて実装します。
今度はハミルトニアンを以下の行列とします。
H =
\left(\begin{array}{cc}
1 & 1 \\
1 & 1
\end{array}\right)
= I + X
この固有値は $0, 2$ です。
$\left|\psi(\theta)\right> = R_y(\theta)\left|0\right>$ とし、$\theta$ は $(0≦\theta<2\pi)$ とします。
from blueqat import Circuit
import numpy as np
import matplotlib.pyplot as plt
import math
# θの初期値、重み、誤差
th, w, d = 2.0, 0.05, 0.01
# 格納配列
th_a, s_a = [], []
while True:
# |ψ(θ)> の作成
d_ry = Circuit().ry(th+math.pi)[0].run()
_ry = Circuit().ry(th)[0].run()
'''
d_ry = (-sin(θ/2) cos(θ/2)) => (d/dθ)|ψ(0)>
_ry = (cos(θ/2) sin(θ/2)) => |ψ(0)>
'''
# X の処理
hd_ry = Circuit().ry(th+math.pi)[0].x[0].run()
h_ry = Circuit().ry(th)[0].x[0].run()
'''
hd_ry = (cos(θ/2) -sin(θ/2)) => (d/dθ)X|ψ(0)>
h_ry = (sin(θ/2) cos(θ/2)) => X|ψ(0)>
'''
# 位相処理
if math.sin(th/2.0) >= 0.0:
d_ry = -d_ry
if math.sin(th/2.0) < 0.0:
h_ry = -h_ry
if math.cos(th/2.0) < 0.0:
_ry = -_ry
hd_ry = -hd_ry
# 勾配
ds_th = (np.dot(d_ry, _ry) + np.dot(_ry, d_ry) + np.dot(d_ry, h_ry) + np.dot(_ry, hd_ry))*(1/2.0)
# θの更新
th = th - w*ds_th*th
# 誤差範囲
if ds_th <= d and ds_th >= -d:
s_th = np.dot(_ry, _ry) + np.dot(_ry, h_ry) # 期待値
print(i) # 回数
break
print(th) # θ
print(s_th) # 固有値
結果
19
(4.7057364938256585+0j)
(3.7828454340083084e-05+0j) # 3.0 × 10^-5
上手く固有値を取り出すことができました。
まとめ
今回はblueqatを用いて VQE を実装しました。
次回は QAOA をblueqatで実装してみます。