質問編集履歴
6
アルゴリズムにミスがあったので更新しました
title
CHANGED
File without changes
|
body
CHANGED
@@ -2,8 +2,10 @@
|
|
2
2
|
コードにもコメント文で書いていますが、以下に具体的に書きたいと思います。
|
3
3
|
メトロポリス法という物理学の中の統計力学におけるシミュレーションをを行う際の計算方法です。
|
4
4
|
|
5
|
-
|
5
|
+
**20181024 追記メトロポリスアルゴリズムにミスがあったため、全面的に書きなおしました。**
|
6
6
|
|
7
|
+
**初期状態の形成**
|
8
|
+
|
7
9
|
(1)Nx*Nyの行列を生成し、各成分を(i,j)であらわす。
|
8
10
|
|
9
11
|
(2)行列の各要素は0~2*np.piの乱数を取るものとする。この値をS[i,j]とする。
|
@@ -14,37 +16,22 @@
|
|
14
16
|
~~周期的境界条件~~
|
15
17
|
例えばNx=8,Ny=8の場合、S[0,1]=S[8,1]、S[1,0]=S[1,8]というように、行列の各端で値を折り返します。
|
16
18
|
|
17
|
-
**メトロポリスアルゴリズム(10/24追記:(6)以下で一部間違っています。下に正しいものを載せました。)**
|
18
19
|
|
19
20
|
(4)行列Sのある要素S(i,j)をランダムに抽出し、その要素だけを0~2πの乱数で変動させる。
|
20
21
|
|
21
22
|
(5)変動させたS(i,j)をSal(i,j)として、以下の計算を行い、Eal(i,j)を計算する。
|
22
|
-
Eal(i,j)=cos(Sal(i,j)-S(i+1,j))-cos(Sal(i,j)-S(i-1,j))-cos(Sal(i,j)-S(i,j+1))-cos(Sal(i,j)-S(i,j-1))
|
23
23
|
|
24
|
-
つまり、変動させた(i,j)以外の要素はそのままにして、手順(3)で行ったものと同じ計算をするということです。
|
24
|
+
つまり、変動させた(i,j)以外の要素はそのままにして、手順(3)で行ったものと同じ計算をするということです。この時、行列Sの要素S[i,j]の変動に伴い、行列Eの要素E[i,j],E[i+1,j],E[i-1,j],E[i,j+1],E[1,j-1]も変動することに注意してください。
|
25
25
|
|
26
|
-
|
26
|
+
(6)変動前の行列Eおよび変動後の行列Eの行列式をそれぞれE、Ealとします。
|
27
|
-
~~
|
28
|
-
|
27
|
+
(6-1)E > Eal の場合、要素S[i,j]→Sal[i,j]への更新に成功したとし、(7)以降の過程へ。
|
29
|
-
~~
|
30
|
-
~~(6-2) E[i,j] < Eal[i,j] の場合、deltaE[i,j]=Eal[i,j]-E[i,j]を計算します。そして確率exp(-deltaE[i,j]/0.001)でもともとの要素S[i,j]をSal[i,j]に更新します。
|
31
|
-
~~
|
32
|
-
~~(7)(4)~(6)を10000回繰り返すことでおおよそすべての要素S[i,j]がスピン更新を経験するようにします。
|
33
|
-
~~
|
34
|
-
~~(8)(7)の操作後の行列Sを用いて行列Eを計算する。それぞれの行列の行列式の値Ssum=np.sum(S)、Esum=np.sum(E)をもとめることができれば計算終了です。
|
35
|
-
参考程度にですが、Ssum~64、Esum~-250 (Nx=8、Ny=8) となれば成功と言えます。~~
|
36
|
-
~~
|
37
|
-
**10/24追記 (6)以下のメトロポリスアルゴリズム(文献を再度確認しなおしました。)**
|
38
|
-
(6)ここで(3)で計算したE[i,j]と(5)で計算したEal[i,j]とを比較します。
|
39
28
|
|
40
|
-
(6-
|
29
|
+
(6-2) E < Eal の場合、deltaE=Eal-Eを計算します。そして確率exp(-deltaE/0.001)でもともとの要素S[i,j]→Sal[i,j]への更新に成功したとします。ここで(6)~(6-2)においてS[i,j]の更新に成功した場合は行列E[i,j],E[i+1,j],E[i-1,j],E[i,j+1],E[1,j-1]の要素も当然変化します。
|
41
30
|
|
42
|
-
(6-2)
|
31
|
+
(7)(4)~(6-2)を1回の試行として、1000回繰り返す。
|
43
32
|
|
44
|
-
(7)(4)~(6-2)を
|
33
|
+
(8)(7)の後(4)~(6-2)を10000回繰り返す。しかし、この時1回ごとにS_sum = np.sum(S)、E_sum = np.sun(E)を計算し、足し合わせていく。つまりi回目の更新で得られたS_sumをS_sum(i)とすると、S_end(10000)=S_sum(1)+S_sum(2)+S_sum(3)...+S_sum(10000)を求めるということです。E_end(10000)についても同様です。
|
45
34
|
|
46
|
-
(8)(7)の後(4)~(6-2)を10000回繰り返す。しかし、この時1回ごとにS_sum = np.sum(S)、E_sum = np.sun(E)を計算し、その和を求める。つまりi回目の更新で得られたS_sumをS_sum(i)とすると、S_end(10000)=S_sum(1)+S_sum(2)+S_sum(3)...+S_sum(10000)を求めるということです。E_end(10000)についても同様です。
|
47
|
-
|
48
35
|
(9)(8)で求めた値を用いて、S_ave = S_end(10000)/10000,E_ave = E_end(10000)/10000 を出力できればOKです。
|
49
36
|
|
50
37
|
|
5
アルゴリズムにミスがあったので、訂正を行いました。
title
CHANGED
File without changes
|
body
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
### 仕様
|
2
|
-
コードにもコメント文で書いていますが、以下に具体的に
|
2
|
+
コードにもコメント文で書いていますが、以下に具体的に書きたいと思います。
|
3
3
|
メトロポリス法という物理学の中の統計力学におけるシミュレーションをを行う際の計算方法です。
|
4
4
|
|
5
5
|
**初期状態の形成**
|
@@ -14,7 +14,7 @@
|
|
14
14
|
~~周期的境界条件~~
|
15
15
|
例えばNx=8,Ny=8の場合、S[0,1]=S[8,1]、S[1,0]=S[1,8]というように、行列の各端で値を折り返します。
|
16
16
|
|
17
|
-
**メトロポリスアルゴリズム**
|
17
|
+
**メトロポリスアルゴリズム(10/24追記:(6)以下で一部間違っています。下に正しいものを載せました。)**
|
18
18
|
|
19
19
|
(4)行列Sのある要素S(i,j)をランダムに抽出し、その要素だけを0~2πの乱数で変動させる。
|
20
20
|
|
@@ -23,17 +23,35 @@
|
|
23
23
|
|
24
24
|
つまり、変動させた(i,j)以外の要素はそのままにして、手順(3)で行ったものと同じ計算をするということです。
|
25
25
|
|
26
|
+
~~(6)ここで(3)で計算したE[i,j]と(5)で計算したEal[i,j]とを比較します。
|
27
|
+
~~
|
28
|
+
~~(6-1)E[i,j] > Eal[i,j] の場合、もともとの要素S[i,j]をSal[i,j]に更新し、(7)以降の過程へ。
|
29
|
+
~~
|
30
|
+
~~(6-2) E[i,j] < Eal[i,j] の場合、deltaE[i,j]=Eal[i,j]-E[i,j]を計算します。そして確率exp(-deltaE[i,j]/0.001)でもともとの要素S[i,j]をSal[i,j]に更新します。
|
31
|
+
~~
|
32
|
+
~~(7)(4)~(6)を10000回繰り返すことでおおよそすべての要素S[i,j]がスピン更新を経験するようにします。
|
33
|
+
~~
|
34
|
+
~~(8)(7)の操作後の行列Sを用いて行列Eを計算する。それぞれの行列の行列式の値Ssum=np.sum(S)、Esum=np.sum(E)をもとめることができれば計算終了です。
|
35
|
+
参考程度にですが、Ssum~64、Esum~-250 (Nx=8、Ny=8) となれば成功と言えます。~~
|
36
|
+
~~
|
37
|
+
**10/24追記 (6)以下のメトロポリスアルゴリズム(文献を再度確認しなおしました。)**
|
26
38
|
(6)ここで(3)で計算したE[i,j]と(5)で計算したEal[i,j]とを比較します。
|
27
39
|
|
28
|
-
(6-1
|
40
|
+
(6-1)E[i,j] > Eal[i,j] の場合、もともとの要素S[i,j]をSal[i,j]に更新し、(7)以降の過程へ。
|
29
41
|
|
30
42
|
(6-2) E[i,j] < Eal[i,j] の場合、deltaE[i,j]=Eal[i,j]-E[i,j]を計算します。そして確率exp(-deltaE[i,j]/0.001)でもともとの要素S[i,j]をSal[i,j]に更新します。
|
31
43
|
|
32
|
-
(7)(4)~(6)を
|
44
|
+
(7)(4)~(6-2)を1000回繰り返す。(ここでは(8)でしているような計算は行わず、Sの更新だけを行います。)
|
33
45
|
|
34
|
-
(8)(7)の
|
35
|
-
参考程度にですが、Ssum~64、Esum~-250 (Nx=8、Ny=8) となれば成功と言えます。
|
46
|
+
(8)(7)の後(4)~(6-2)を10000回繰り返す。しかし、この時1回ごとにS_sum = np.sum(S)、E_sum = np.sun(E)を計算し、その和を求める。つまりi回目の更新で得られたS_sumをS_sum(i)とすると、S_end(10000)=S_sum(1)+S_sum(2)+S_sum(3)...+S_sum(10000)を求めるということです。E_end(10000)についても同様です。
|
36
47
|
|
48
|
+
(9)(8)で求めた値を用いて、S_ave = S_end(10000)/10000,E_ave = E_end(10000)/10000 を出力できればOKです。
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
|
37
55
|
### 実際に書いてみたコード
|
38
56
|
|
39
57
|
```python
|
4
仕様の項目に追記を行いました
title
CHANGED
File without changes
|
body
CHANGED
@@ -31,9 +31,9 @@
|
|
31
31
|
|
32
32
|
(7)(4)~(6)を10000回繰り返すことでおおよそすべての要素S[i,j]がスピン更新を経験するようにします。
|
33
33
|
|
34
|
-
(8)(7)の操作後の行列式
|
34
|
+
(8)(7)の操作後の行列Sを用いて行列Eを計算する。それぞれの行列の行列式の値Ssum=np.sum(S)、Esum=np.sum(E)をもとめることができれば計算終了です。
|
35
|
+
参考程度にですが、Ssum~64、Esum~-250 (Nx=8、Ny=8) となれば成功と言えます。
|
35
36
|
|
36
|
-
|
37
37
|
### 実際に書いてみたコード
|
38
38
|
|
39
39
|
```python
|
3
追記2を更新しました
title
CHANGED
File without changes
|
body
CHANGED
@@ -158,4 +158,35 @@
|
|
158
158
|
if random() < np.exp(-delta / 0.001):
|
159
159
|
TypeError: 'module' object is not callable
|
160
160
|
|
161
|
+
```
|
162
|
+
|
163
|
+
###追記2(#更新部分について、教えていただいた内容をもとに条件分岐を訂正しました)
|
164
|
+
```python
|
165
|
+
def Metropolis(Nx=8, Ny=8, iterations=10000):
|
166
|
+
S = np.random.uniform(0, 2 * np.pi, (Nx, Ny)) # Nx * Ny の行列Sを形成。各要素は0~2πの乱数
|
167
|
+
E = update(S)
|
168
|
+
|
169
|
+
indices = np.dstack(np.mgrid[0:Nx, 0:Ny]).reshape(-1, 2)
|
170
|
+
for k in range(iterations): # モンテカルロステップ数を 10000 とする
|
171
|
+
# ランダムに要素を選択する。
|
172
|
+
index = tuple(indices[np.random.randint(len(indices))])
|
173
|
+
|
174
|
+
# 乱数を生成する。
|
175
|
+
E_tmp = E.copy()
|
176
|
+
E_tmp[index] = np.random.uniform(0, 2 * np.pi)
|
177
|
+
|
178
|
+
# 計算
|
179
|
+
E_tmp = update(E_tmp)
|
180
|
+
|
181
|
+
# 更新
|
182
|
+
if E[index] > E_tmp[index]:
|
183
|
+
E[index] = E_tmp[index]
|
184
|
+
|
185
|
+
else:
|
186
|
+
delta = E_tmp[index] - E[index]
|
187
|
+
if np.random.random() < np.exp(-delta / 0.001):
|
188
|
+
E[index] = E_tmp[index]
|
189
|
+
|
190
|
+
|
191
|
+
return S, E
|
161
192
|
```
|
2
追記を追加しました。
title
CHANGED
File without changes
|
body
CHANGED
@@ -116,4 +116,46 @@
|
|
116
116
|
### 参考
|
117
117
|
以前にも以下のような質問をし、本プログラム作成の際にお世話になりました。
|
118
118
|
https://teratail.com/questions/152409
|
119
|
-
https://teratail.com/questions/152518
|
119
|
+
https://teratail.com/questions/152518
|
120
|
+
|
121
|
+
###追記(elseの分岐以降でエラーが出ています)
|
122
|
+
|
123
|
+
|
124
|
+
```python
|
125
|
+
def Metropolis(Nx=8, Ny=8, iterations=10000):
|
126
|
+
S = np.random.uniform(0, 2 * np.pi, (Nx, Ny)) # Nx * Ny の行列Sを形成。各要素は0~2πの乱数
|
127
|
+
E = update(S)
|
128
|
+
|
129
|
+
indices = np.dstack(np.mgrid[0:Nx, 0:Ny]).reshape(-1, 2)
|
130
|
+
for k in range(iterations): # モンテカルロステップ数を 10000 とする
|
131
|
+
# ランダムに要素を選択する。
|
132
|
+
index = tuple(indices[np.random.randint(len(indices))])
|
133
|
+
|
134
|
+
# 乱数を生成する。
|
135
|
+
E_tmp = E.copy()
|
136
|
+
E_tmp[index] = np.random.uniform(0, 2 * np.pi)
|
137
|
+
|
138
|
+
# 計算
|
139
|
+
E_tmp = update(E_tmp)
|
140
|
+
|
141
|
+
# 更新
|
142
|
+
if E[index] > E_tmp[index]:
|
143
|
+
continue
|
144
|
+
else:
|
145
|
+
delta = E_tmp[index] - E[index]
|
146
|
+
if random() < np.exp(-delta / 0.001):#変更部分です
|
147
|
+
continue
|
148
|
+
|
149
|
+
return S, E
|
150
|
+
|
151
|
+
```
|
152
|
+
↓
|
153
|
+
```output
|
154
|
+
Traceback (most recent call last):
|
155
|
+
File "C:/Users/user2/Desktop/2DXYTEST/testtesttesttest13.py", line 44, in <module>
|
156
|
+
S, E = Metropolis(Nx=8, Ny=8, iterations=10000)
|
157
|
+
File "C:/Users/user2/Desktop/2DXYTEST/testtesttesttest13.py", line 37, in Metropolis
|
158
|
+
if random() < np.exp(-delta / 0.001):
|
159
|
+
TypeError: 'module' object is not callable
|
160
|
+
|
161
|
+
```
|
1
質問の題にミスがあったので修正しました。
title
CHANGED
@@ -1,1 +1,1 @@
|
|
1
|
-
python
|
1
|
+
python TypeErrorが解決できない
|
body
CHANGED
File without changes
|