🎲

Julia からBlueqat をつかってみる。

2020/11/29に公開
2

Blueqat とは?

Blueqat社 が作ってる量子コンピュータのシミュレータ。
たぶん一番簡単。たしかPython (numpy)で書かれている。

おまじないが少なくていい。

Julia とは?

科学技術計算のプログラミング言語 Julia
どちゃくそ速い。最近のお気に入り。
環境構築もバイナリを落としてくるだけでいいので楽。

Yao.jl あるくない?

Yao.jl
まぁ現状維持バイアスというか、blueqat の手軽さを捨てられないからですね。

戦略

Pycall で呼び出す。

参考:
Juliaで機械学習:PyCall.jlを使ってTensorFlowのKerasを使ってみる

すでにBlueqat がローカルのPythonにインストール済みであることを前提にします。
またJulia もダウンロード済みで、パスも通ってるとします。

which python

でわかるPythonのpath をメモしておく。
筆者の場合だと

/anaconda3/bin/python

次にjulia を起動する。
Pycall でつかうPythonを指定する。

ENV["PYTHON"]="/anaconda3/bin/python"

つぎに ] キーを押してパッケージモードに入って

add PyCall

もしくは、既に入ってる場合には、

build PyCall

とする。これで準備完了。

つかってみる。

今回は、Jupyter notebook 上でJulia をつかう。
(参考)

まず、blueqat をロードする。

using PyCall
bq = pyimport("blueqat")

あとは、実際に量子回路を組む。ただしインデックスが1から始まることに注意。

c = bq.Circuit(2)
c.h[1].h[2]
c.m[1].m[2]

測定は、

Nshots = 1000
res = c.run(shots=Nshots)
for key = keys(res)
    println("$key $(res[key]/Nshots)")
end

とする。
結果をみると、

00 0.269
10 0.232
11 0.266
01 0.233

と得られる。

今回の量子回路

2つの量子ビットそれぞれにアダマールがついた単純なもの。

|0> - [H] - [m]
|0> - [H] - [m]

ここで[H]はアダマールゲート、[m]はz測定(0か1かの測定)を表す。

測定すると、00, 01, 10, 11 が等確率で観測される。

残るなぞ

c.m[1].m[2]c.m[:] と書けない。

2020/12/13追記。
コメント欄で解決法を教えていただきました!

コード

https://github.com/akio-tomiya/notebooks/blob/main/blueqat_julia.ipynb
ここにおいておきました。

補足

まず初期化された量子ビットは、

|0\rangle = \begin{pmatrix} 1 \\ 0 \end{pmatrix}

と書ける。
直交する状態は、

|1\rangle = \begin{pmatrix} 0 \\ 1 \end{pmatrix}

と書ける。

またアダマールゲートは行列として

H = \frac{1}{\sqrt{2}} \begin{pmatrix} 1& 1 \\ 1& -1 \end{pmatrix}

とかくことができる。

1量子ビットに対してアダマールゲートは、

H |0\rangle = \frac{1}{\sqrt{2}} (|0\rangle + |1\rangle)

という重ね合わせ状態を作る。

さらに2量子ビットは、

|00\rangle = |0\rangle_1 \otimes |0\rangle_2

のようなテンソル積としてかける。
ただし添字は、量子ビットを区別するためにつけた。

いまの量子回路は、

(H |0\rangle_1) \otimes (H |0\rangle_2) = \frac{1}{2}(|0\rangle_1 + |1\rangle_1) (|0\rangle_2 + |1\rangle_2)

右辺を展開すると、

(H |0\rangle_1) \otimes (H |0\rangle_2) = \frac{1}{2}( |0\rangle_1 |0\rangle_2 + |1\rangle_1 |0\rangle_2 + |0\rangle_1 |1\rangle_2 + |1\rangle_1 |1\rangle_2 )

とすべてのパターンが同じ係数で出現する。
ボルンの規則 に従うと、全パターンが等確率(1/2^2 = 1/4)で出現し、これは実際に上のシミュレーションで確かめられた。

Discussion

pitmanpitman

no method matching getindex(::PyObject, ::Colon) などというエラーが出ますので、getindex(o::PyObject, ::Colon) メソッドを登録すると上手く行きます。

面倒くさいので Python 側へ丸投げです(pyeval)。

julia> PyCall.getindex(o::PyObject, ::Colon) = py"$o[:]"

julia> c.h[:].m[:]
PyObject Circuit(2).h[:].measure[:]

julia> c.to_qasm()
"OPENQASM 2.0;\ninclude \"qelib1.inc\";\nqreg q[2];\ncreg c[2];\nh q[0];\nh q[1];\nmeasure q[0] -> c[0];\nmeasure q[1] -> c[1];"