らんだむな記憶

blogというものを体験してみようか!的なー

Qiskit (60) —VQE

サンプルコードを見ていく。内容は単純で、

  • ランダムな $\theta$, $\phi$, $\lambda$ で初期化されたユニバーサルゲート $U3(\theta, \phi, \lambda)$ だけからなる variational form について、
  • $U3(\theta, \phi, \lambda) \ket{0} = \alpha \ket{0} + \beta \ket{1}$ が $0.48642994 \ket{0} + 0.51357006 \ket{1}$ を出力するような variational form になるように COBYLA オプティマイザで最適化した時、
  • $\theta$, $\phi$, $\lambda$ はどういう値になっているか?

を確認するというものである。

from qiskit.aqua.components.optimizers import COBYLA

の部分は Qiskit 0.34.2 で動いているがいつ動かなくなるかあやしいので、

from qiskit.algorithms.optimizers import COBYLA

に変更しておく。

def get_var_form(params):
    qr = QuantumRegister(1, name="q")
    cr = ClassicalRegister(1, name='c')
    qc = QuantumCircuit(qr, cr)
    qc.u3(params[0], params[1], params[2], qr[0])
    qc.measure(qr, cr[0])
    return qc

も怒られたので、

    qc.u(params[0], params[1], params[2], qr[0])

にする。UGate については UGate — Qiskit 0.34.2 documentation が参考になる。U3Gate とはゲートの分解が少し違うが論理的には等価である。

この改造を施して上から見ていく。

>>> print(target_distr)
[0.51357006 0.48642994]

ここはシードを固定しているのでこういう値になる。

分布の近さは Manhattan 距離($L^1$ 距離)で見るということなので、何かしら離散的な分布 $p = \{p_i\}$ と $q = \{q_i\}$ があるとして距離は $\mathrm{dist}(p, q) = \sum_i |p_i - q_i|$ で測られる。
objective_function の実装としては、variational form に 10000 ショット打って観測された分布と前述の target_distr の $L^1$ 距離をとっている。

$U3$ ゲートの変数 $\theta$, $\phi$, $\lambda$ はランダムな値で初期化されて、
COBYLA オプティマイザが最適化するパラメータとして渡されている。

maxiter は 2 や 3 でも近い時は近い値が出てくる。500 くらいだとまぁ安定しているが、10000 にしても滅茶苦茶近い値になるわけでもなかった。optimizer.optimize の中で全部やってくれるようなので、まるで Keras を叩いているかのような心地だが、なんとなく雰囲気は分かったような気がする。

何度か適当に実行すると

Target Distribution: [0.51357006 0.48642994]
Obtained Distribution: [0.5135, 0.4865]
Output Error (Manhattan Distance): 0.049940118738839134
Parameters Found: [1.60055144 0.73234824 0.5787642 ]

が出た。

>>> print(counts)
{'1': 5135, '0': 4865}
>>> import math
>>> print(math.cos(1.60055144/2)**2)
0.4851246386492849

なので、$\theta$ は正しそう。($\phi$ と $\lambda$ は観測に関係ないので実質ランダムな値のまま)