实现都市喧嚣算法

时间:2019-04-04 21:19:42

标签: python montecarlo

在过去的几周里,我一直在试图了解MCMC和Metropolis-Hastings,但是每次尝试实现它都失败了。

因此,我尝试使用Metropolis-Hastings算法从均匀分布中获取Boltzmann分布,但是它不起作用。

以下是我在做什么的摘要:

  1. 我从均匀分布m画一个随机数。
  2. 我从均匀分布n中画出另一个随机数。
  3. 我设置dU = n-m。
  4. 如果dU <0,则我接受dU,设置m = n,然后重复。
  5. 如果dU> 0,则我计算w = exp(-b * dU),其中b是1 / kT,并从均匀分布r中绘制一个随机数。
  6. 如果w> r,我接受dU,设置m = n,然后重复。 7如果w

我是该领域和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

1 个答案:

答案 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的图形

enter image description here