質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

2509閲覧

周期境界条件を適用した量子ウォークの確率が保存されない。

Fallout_18

総合スコア124

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2018/07/30 06:45

編集2018/07/30 15:38

問題点、欲しいもの

量子ウォークという、いわゆるランダムウォークの量子版という物を勉強しています。
全確率が保存するように、以下の周期境界条件をつかって、時間t=0で(0,0)にだけ確率1をもってブルーの2n*2nの正方格子上に時間毎に1移動していくようにコードを書いたのですが、t>2秒以降の時間発展で確率が保存されず、どんどん減っていってしまい原因が全く分からず、かれこれ1カ月経過しようてしており、お力を借りたく質問させて頂きました。

前提

ステージ
物理的背景を除いて、量子状態の時間発展の式は
ψ(t+1,x,y) = Pψ(t,x-1,y) + Qψ(t,x+1,y) + Rψ(t,x,y+1) + Sψ(t,x,y-1)
と表せるとします。
P~Rは44の行列で、ψは[a,b,c,d]のような4状態で表すとします。
このψから確率pは**p(t,x,y) = ψ
(t,x,y).ψ(t,x,y) **と算出できます。(*は複素共役)。
以上を踏まえて、以下にコードと結果をリポジっトします。

コード内容

python

1import numpy as np 2import matplotlib.pyplot as plt 3import math 4import itertools 5 6n = 3 7itr = 3 8x_list=[i for i in range(0,2*n+1)] 9y_list=[i for i in range(0,2*n+1)] 10##### 11P = [[-1/2, 1/2, 1/2, 1/2],[0,0,0,0],[0,0,0,0],[0,0,0,0]] #→ 12Q = [[0,0,0,0],[1/2, -1/2, 1/2, 1/2],[0,0,0,0],[0,0,0,0]] #← 13R = [[0,0,0,0],[0,0,0,0],[1/2, 1/2, -1/2, 1/2],[0,0,0,0]] #↓ 14S = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[1/2, 1/2, 1/2, -1/2]] #↑ 15#### 16phi_map = np.zeros((2*n+1, 2*n+1,4),dtype="complex") 17phi_map[0,0]= np.array([1,0,0,0]) 18#t+1の状態を収納する用 19next_phi_map = np.zeros((2*n+1, 2*n+1, 4),dtype="complex") 20#確率収納 21p_map=np.zeros([2*n+1,2*n+1]) 22p_map[0,0] = np.real(np.inner(phi_map[0,0], np.conj(phi_map[0,0]))) 23##main計算 24for t in range(0,itr+1): 25 if t == 0: 26 p_map 27 phi_map 28 else: 29 for i in itertools.product(x_list,y_list): 30 if i[0]==0: #x座標が0のときで場合分け 31 if i[1]==0: #y =0 32 next_phi_map[i] = np.array([np.dot(P, phi_map[i[0]+2*n,0]) + np.dot(Q, phi_map[i[0]+1,i[0]]) + np.dot(R, phi_map[i[0],i[1]+1]) 33 + np.dot(S, phi_map[i[0],i[1]+2*n])]) 34 elif i[1] == 2*n: 35 next_phi_map[i] = np.array([np.dot(P, phi_map[2*n,i[1]]) + np.dot(Q, phi_map[i[0]+1, i[1]]) 36 + np.dot(R, phi_map[i[0], 0]) 37 + np.dot(S, phi_map[0,2*n-1])]) 38 else: 39 next_phi_map[i] = np.array([np.dot(P, phi_map[2*n,i[1]]) + np.dot(Q, phi_map[i[0]+1,i[1]]) + np.dot(R, phi_map[i[0],i[1]+1]) 40 + np.dot(S, phi_map[i[0],i[1]-1])]) 41 elif i[0] == 2*n:#x=2nの時で場合分け 42 if i[1] == 0: #y=0 43 next_phi_map[i] = np.array([np.dot(P, phi_map[i[0]-1,i[1]]) + np.dot(Q, phi_map[0,i[1]]) + np.dot(R, phi_map[i[0],i[1]+1]) 44 + np.dot(S, phi_map[i[0],2*n])]) 45 elif i[1] == 2*n: 46 next_phi_map[i] = np.array([np.dot(P, phi_map[i[0]-1,i[1]]) + np.dot(Q, phi_map[0, i[1]]) + np.dot(R, phi_map[i[0], 0]) + np.dot(S, phi_map[i[0],i[1]-1])]) 47 else: 48 next_phi_map[i] = np.array([np.dot(P, phi_map[2*n-1,i[1]]) + np.dot(Q, phi_map[0,i[1]]) + np.dot(R, phi_map[2*n, i[1]+1])+ np.dot(S, phi_map[2*n, i[1]-1])]) 49 else: #xがそれ以外のときのyで場合分け 50 if i[1] == 0: 51 next_phi_map[i] = np.array([np.dot(P, phi_map[i[0]-1,i[1]]) + np.dot(Q, phi_map[i[0]+1,i[1]]) + np.dot(R, phi_map[i[0],i[1]+1]) 52 + np.dot(S, phi_map[i[0],2*n])]) 53 elif i[1] == 2*n: 54 next_phi_map[i] = np.array([np.dot(P, phi_map[i[0]-1, i[1]]) + np.dot(Q, phi_map[i[0]+1,i[1]]) + np.dot(R, phi_map[i[0],0]) 55 + np.dot(S, phi_map[i[0],i[1]-1])]) 56 else: 57 next_phi_map[i] = np.array([np.dot(P, phi_map[i[0]-1,i[1]]) + np.dot(Q, phi_map[i[0]+1,i[1]]) + np.dot(R, phi_map[i[0],i[1]+1]) 58 + np.dot(S, phi_map[i[0],i[1]-1])]) 59 p_map[i] = np.real(np.inner(next_phi_map[i], np.conj(next_phi_map[i]))) 60 phi_map = next_phi_map 61 print(t,np.real(p_map),p_map.sum())

結果

0 [[1. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0.]] 1.0 1 [[0. 0.25 0. 0. 0. 0. 0.25] [0.25 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 0. ] [0.25 0. 0. 0. 0. 0. 0. ]] 1.0 2 (行列は省略) 0.8534011840820312 3 (行列は省略) 0.7919882354326546

とt>2で既に確率が保存されていない状況が生まれてしまい、コードを見直しても原因がわかりません。
怪しいと思ったこと何でも言ってください。
よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

t = 1 でループを回った直後を考えてみてください。
phi_map = next_phi_map の直後なので、
phi_mapnext_phi_map は同じものを指していますよね。

phi_map は時刻 t の、next_phi_map は時刻 t+1 のときの ψ の値を保持していて欲しいのですから、これは変です。
この状態で next_phi_map を書きかえているので、ψ_{t+1} だけを変更しているつもりが、
「過去の値」である ψ_{t} (phi_map) も書きかえられてしまっています。
……というのがうまくいかなかった理由です。

対策としては、ループ内で next_phi_map を毎回新たに作成すればよいです。
分かってしまえばよくある凡ミスですが、コードが入り組んでいて発見が難しかったのだと思います。
抽象化できる処理はできるだけ抽象化するのがオススメです。

// ちなみに、ψ は psi です。phi は φ のことですね。

python

1# coding: utf-8 2 3import numpy as np 4 5# 一辺の長さは 2n+1 6n = 3 7 8# 繰り返し数 9itr = 3 10 11# 初期位置 12(x0, y0) = (0, 0) 13 14# ============================================= 15# ψ と p の初期化 16# ============================================= 17 18# 遷移の重みを表す行列 19P = [[-1/2, 1/2, 1/2, 1/2],[0,0,0,0],[0,0,0,0],[0,0,0,0]] #→ 20Q = [[0,0,0,0],[1/2, -1/2, 1/2, 1/2],[0,0,0,0],[0,0,0,0]] #← 21R = [[0,0,0,0],[0,0,0,0],[1/2, 1/2, -1/2, 1/2],[0,0,0,0]] #↓ 22S = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[1/2, 1/2, 1/2, -1/2]] #↑ 23 24# ψ_{t}(x,y) の初期化 25phi_map = np.zeros((2*n+1, 2*n+1,4), dtype="complex") 26 27# 時刻 t における ψ_{t} の確率分布 p_{t}(x, y) 28p_map = np.zeros([2*n+1,2*n+1]) 29 30# 初期条件の設定 31phi_map[x0,y0]= np.array([1,0,0,0]) 32p_map[x0,y0] = 1.0 33 34# ============================================= 35# 便利関数 36# ============================================= 37 38# (x, y) where 0 <= x <= 2n, 0 <= y <= 2n を満たす (x,y) の組を生成するジェネレータを返す 39def Lattice(width = 2*n+1, height = 2*n+1): return ( (x, y) for x in range(width) for y in range(height) ) 40 41# v ≡ x mod (2n+1) を満たす最小の非負整数 x を返す 42def mod(v): return v % (2*n + 1) 43 44# ψ の第 n 項を計算する 45def T(v, x, y): return np.dot(v, phi_map[mod(x), mod(y)]) 46def T1(x, y): return T(P, x, y) 47def T2(x, y): return T(Q, x, y) 48def T3(x, y): return T(R, x, y) 49def T4(x, y): return T(S, x, y) 50 51# ψ_{t} を使って座標 (x, y) の ψ_{t+1} を計算する 52def calc_phi(x, y): 53 return np.array([ T1(x-1, y) + T2(x+1, y) + T3(x, y+1) + T4(x, y-1) ]) 54 55# ψ_{t} から p_{t} を計算する 56def calc_p(phi): 57 return np.real(np.vdot(phi, phi)) 58 59# 時刻 t とそのときの確率分布を表示する 60def show(t, p): 61 print(t) 62 print(np.real(p), p.sum()) 63 64# ============================================= 65# main 66# ============================================= 67np.set_printoptions(linewidth=256) 68 69show(0, p_map) 70for t in range(itr): 71 # v こいつは毎回初期化が必要 72 # ψ_{t+1}(x,y) の初期化 73 next_phi_map = np.zeros((2*n+1, 2*n+1, 4), dtype="complex") 74 for (x,y) in Lattice(): 75 next_phi = calc_phi(x, y) 76 next_phi_map[x,y] = next_phi 77 p_map[x,y] = calc_p(next_phi) 78 79 phi_map = next_phi_map 80 show(t, p_map)

投稿2018/07/30 16:31

編集2018/07/30 16:32
pute

総合スコア134

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Fallout_18

2018/07/31 03:55

初めに、懇切丁寧なご指摘、お時間を割いて頂き、誠に感謝いたします。 ただ、まだピンとこないのですが、 僕としては、t+1のnext_phi_mapが計算し終わって、t+2に行くときにphi_mapにt+1を代入してあげたら次のループでt+2のnext_phi_mapが来ると想定しています(つまり書き換えられて良いと思ったのですが。。。) その事を考え、 phi_map = np.copy(next_phi_map)としてみたら確率が保存されたのですが、つまりは、next_phi_mapのデータをphi_mapに移行するときに、完全に移行されていなかったということだと感じました(浅いコピー、深いコピーが関係している(?))。そのやりかたでも良いのでしょうか(自分では良いと思います)? ただ、どちらにせよ、上記のpute様のコードの書き方は非常に為になり、とても勉強になります。貪欲に吸収させてい頂きます!!
Fallout_18

2018/07/31 03:57

それと、psiとphiはいつもどっちだっけとなってしまいます。申し訳ないです。。
Fallout_18

2018/07/31 12:10

next_phi_mapの初期化に関して、理解できました!
pute

2018/07/31 14:47

よかったです。「=」が何をするのか、というのは割とつまづきどころかと思います。 ちなみに、過去の質問の Sierpinski carpet も今回と同じではないでしょうか。 https://teratail.com/questions/136122 確認はしていませんが、もしまだ未解決でしたら試してみてください。 それでは。
guest

0

こんにちわ。

もうBA出ていますが、補足させてください。

コードの最後のあたり、

next_phi_mapをphi_mapにコピーしようとしている箇所ですが、

python

1 phi_map = next_phi_map

これだと値をコピーしたことにならないので、

次のようにすればよいです。

python

1 phi_map = copy.copy(next_phi_map)

修正後のコードを実行させたところ、以下の結果になりました。

0 [[1. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0.] [0. 0. 0. 0. 0. 0. 0.]] 1.0 1 [[0. 0.25 0. 0. 0. 0. 0.25] [0.25 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 0. ] [0.25 0. 0. 0. 0. 0. 0. ]] 1.0 2 [[0.25 0. 0.0625 0. 0. 0.0625 0. ] [0. 0.125 0. 0. 0. 0. 0.125 ] [0.0625 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 0. ] [0.0625 0. 0. 0. 0. 0. 0. ] [0. 0.125 0. 0. 0. 0. 0.125 ]] 1.0 3 [[0. 0.078125 0. 0.015625 0.015625 0. 0.078125] [0.015625 0. 0.078125 0. 0. 0.078125 0. ] [0. 0.078125 0. 0. 0. 0. 0.078125] [0.015625 0. 0. 0. 0. 0. 0. ] [0.015625 0. 0. 0. 0. 0. 0. ] [0. 0.015625 0. 0. 0. 0. 0.015625] [0.390625 0. 0.015625 0. 0. 0.015625 0. ]] 1.0

なお、修正コードはプログラムの頭に import copy を追加しています。

投稿2018/07/31 10:26

srsnsts

総合スコア480

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Fallout_18

2018/07/31 11:18

参考にさせて頂きます! ちなみになんですが、phi_map =np.copy(next_phi_map)でも解決しました!
srsnsts

2018/07/31 11:34

それでもいいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問