Juliaで1次元量子ウォークをシミュレーションする
1次元量子ウォークをJuliaでシミュレーションしてみた.
とりあえず,コード,実行結果は以下.初Juliaなので,変な書き方してるかもしれない.
using Plots
n = 1000 #シミュレーション数
H = [1 1; 1 -1] / sqrt(2) #アダマールゲート
P = zeros(Float64, 2, 2) #左に飛ぶ
Q = zeros(Float64, 2, 2) #右に飛ぶ
P[1,:] = H[1, :]
Q[2,:] = H[2, :]
buffer = zeros(Complex{Float64}, n, 2n+1, 2) # shape -> (time, position i, two dim complex vector a,b)
buffer[1, :, :] = zeros(Complex{Float64}, 2n+1, 2)
buffer[1, n+1, :] = [1+0im, 0+1im] / sqrt(2) # |a|^2 + |b|^2 = 1
prob = zeros(Float64, n, 2n+1) # shape -> (time, probability at position i)
prob[1, :] = real(sum(conj(buffer[1,:,:]).*buffer[1,:,:], dims=2)) # 確率 = |a|^2 + |b|^2
random_walk_prob = zeros(Float64, n,2n+1) #ランダムウォークと比較
random_walk_prob[1, n+1] = 1.
for t = 2:n
buffer[t, 1:end-1, :] += buffer[t-1, 2:end, :]*transpose(P) # 左に飛ぶ
buffer[t, 2:end, :] += buffer[t-1, 1:end-1, :]*transpose(Q) # 右に飛ぶ
prob[t, :] = real(sum(conj(buffer[t,:,:]).*buffer[t,:,:], dims=2))
random_walk_prob[t-1, :, :] = random_walk_prob[t-1, :, :] / 2
random_walk_prob[t, 1:end-1, :] += random_walk_prob[t-1, 2:end, :]
random_walk_prob[t, 2:end, :] += random_walk_prob[t-1, 1:end-1, :]
end
x = range(-n,n,step=1)
p = plot(x,
prob[end,:],
xlabel = "Position",
ylabel = "Probability",
label = "quantum walk",
)
plot!(p,
x,
random_walk_prob[end,:],
label = "random walk"
)
ランダムウォークというのは聞いたことがあると思う.初めて聞いたというかたは,いろんな面白い記事があるのでみてみるといい. ref
1次元ランダムウォークでは,時刻tとして,t=0(スタート)で原点を出発とし,確率1/2で左へ1進み,確率1/2で右へ1進むという様なことを考える.これを繰り返していくと,ある地点iの確率は正規分布の様に見える.上の図でいう茶色のグラフだ.実際,時間軸をより細かくしていくと,中心極限定理から正規分布が得られ,ブラウン運動を定義できる.
対して量子ウォークとは,Wikiをそのまま書くと,「ランダムウォークの量子版と見なされるモデル」である.量子ウォークでは,ユニタリ行列をある状態に対してかけることを繰り返す.厳密かどうかは置いておき,ランダムウォークと比較して理解してみよう.ランダムウォークでは原点をスタートとするとだけ述べたが,量子ウォークでは原点に2次元複素ベクトルが乗っているとする.これが状態を表していると考え,ユニタリ行列を
グラフをみるとわかるが,量子ウォークの方がより広く分布していることがわかる.時刻をtとすると,ランダムウォークは
Discussion