在过去的几周里,我一直在试图了解MCMC和Metropolis-Hastings,但是每次尝试实现它都失败了。
因此,我尝试使用Metropolis-Hastings算法从均匀分布中获取Boltzmann分布,但是它不起作用。
以下是我在做什么的摘要:
我是该领域和python的初学者,所以我不确定代码是否错误或算法是否错误(可能两者都有)。
我的代码附在下面。谢谢。
import random
%matplotlib inline
import numpy as np
import scipy
import matplotlib.pyplot as plt
from scipy import stats
k = 1.38064852 * 10**(-23)
t = 298
b = 1/(t*k) U = []
m = np.random.uniform(0, 1)
for j in range(100000):
n = np.random.uniform(0, 1)
du = n-m
if du<0:
U.append(du)
m = n
elif du > 0:
w = np.exp(-b*du)
r = np.random.uniform(0, 1)
if w > r:
U.append(du)
m = n
else:
U.append(du)
m = m
答案 0 :(得分:0)
您的问题是双重的。一种是您将新能量('n = random()')采样为无量纲的量,这与您正在做的其他所有事情都矛盾(您的温度以开尔文为单位,kB以J / K等)。其次,使用10 23 和inverse之类的值在物理模拟中效果不佳-您最好将其设置在0 ... 1范围内,然后再进行缩放。在下面,我编写了可以在电子伏特中工作的代码,也可以在eV中采样新能量,并产生了类似于事实的东西。
import numpy as np
import matplotlib.pyplot as plt
kB = 1.0/11600. # eV/K
T = 300 # K
b = 1.0/(kB * T) # inverse temperature, eV^-1
np.random.seed(76543217) # for reproducibility
N = 100000
EE = np.empty(N+1) # energy
DE = np.empty(N+1) # delta energy
Ei = 1.0 # initial energy, 1eV
EE[0] = Ei
DE[0] = 0.0
for k in range(N):
E = np.random.random()/b # sample energy, in eV
dE = E - Ei
if dE < 0.0:
Ei = E
EE[k+1] = Ei
DE[k+1] = dE
elif dE > 0.0:
w = np.exp(-b*dE)
r = np.random.random()
if w > r:
Ei = E
EE[k+1] = Ei
DE[k+1] = dE
else:
EE[k+1] = Ei
DE[k+1] = 0.0
x = np.linspace(0, N+1, num=N+1)
print(EE[N-30:])
print(np.mean(EE[N-1000:]))
print(np.mean(EE[N-2000:]))
fig, ax = plt.subplots(1, 1)
ax.plot(x[N-1000:], EE[N-1000:], 'r-', lw=5, alpha=0.6, label='Energy')
ax.plot(x[N-1000:], DE[N-1000:], 'go', lw=5, alpha=0.6, label='Delta Energy')
plt.show()
打印的是1000和2000个样本的两个最后平均值,对我来说看起来很热
0.010188070423940562
0.010666101150488673
和E / dE的图形