使用指数分布的蒙特卡罗模拟

机器算法验证 可能性 模拟 随机过程 蒙特卡洛
2022-04-16 09:36:02

我正在尝试模拟确定性指数人口增长的随机模型,其中dN/dt=rN在哪里N是人口规模和r是率 (t时间)。我假设没有承载能力。此页面(http://cnr.lwlss.net/DiscreteStochasticLogistic/)建议使用此算法模拟区间上的增长[0,tend]

  1. 开始于t=0具有初始人口规模
  2. 下次为出生事件抽奖,δtExponential(rN(1N/K))(K是承载能力)
  3. 增加人口规模,N=N+1
  4. t=t+δt
  5. 如果t>tend然后退出,否则转到步骤 2。

因为我没有承载能力K,我假设它是无限的,所以下一个出生时间是δtExponential(rN). 那是对的吗?

当我以这种方式运行模拟时,它根本不会给出类似的结果N(t)=P0ert(在哪里P0是初始人口规模)。即使对多次迭代进行平均,它似乎也会给出不同的增长曲线。

下面是我的代码和模拟结果。红色曲线是确定性指数增长,黑色曲线是使用指数分布模拟。他们显然不匹配。

import numpy as np
import matplotlib.pylab as plt
def sim(rate, start, end, init):
    N = 200
    finalsizes = []
    results = []
    for n in range(N):
        size = init
        curr_t = 0
        times = [curr_t]
        sizes = [init]
        new_rate = rate
        while curr_t <= end:
            # simulate next birth time. the scale
            # parameter is inversely proportional to population
            # size
            new_rate = 1/float(new_rate * size)
            div_time = np.random.exponential(scale=new_rate)
            # advance time
            curr_t += div_time
            if curr_t > end:
                # if we exceed time interval, quit
                break
            times.append(curr_t)
            # increase population size
            size += 1
            sizes.append(size)
        finalsizes.append([times, sizes])
    return finalsizes

# run simulation and plot results
init = 20
start = 0
end = 20
rate = 1
finalsizes = sim(rate, start, end, init)
plt.figure()
allsizes = []
for f in finalsizes:
    allsizes.append(f[1][-1])
    plt.plot(f[0], f[1], color="k", alpha=0.5)
times = np.arange(0, end + 1)
plt.plot(times, init*np.power(2, rate * times), color="r")
plt.xlabel("time")
plt.ylabel("size of population")
print "mean final size: ", np.mean(allsizes)
plt.show()

在此处输入图像描述

对 whuber 的出色回答的回应: 我不明白为什么我必须提前指定人口规模。我的模拟是要问:在给定的时间内,假设指数增长,人口规模的可变性是多少?(而不是,平均需要多长时间才能使人口规模达到N,这就是 whuber 的模拟似乎正在做的事情)。

另外,我认为我“还没有做足够的模拟来欣赏他们告诉你的东西”是不正确的。我更新了我的模拟以绘制 1000 次运行。如您所见,在我的基于时间的停止条件下,结果始终低估了确定性指数增长人口规模。

我的理由是,如果我模拟N运行一段时间t,然后作为N,我从模拟中得到的平均人口规模应该是基于确定性指数增长模型的人口规模的无偏估计t, IE2rt. 例如,如果我模拟 3 个时间步长(从单个个体开始),我预计模拟中的人口规模有时会大于 8,有时会小于 8,并且平均值会收敛到 8。这似乎是即使我从一个非常小的人口开始,只要我模拟足够的运行,这应该是正确的。这是不正确的吗?这个推理有什么问题?模拟不支持这一点,尽管我希望它是真的。看来我的推理和/或模拟中必须存在缺陷。

更新 2:固定模拟,其中指数分布的尺度参数随人口规模(与其成反比)而减小,初始人口规模为 10。它仍然严重低估了指数增长。

1个回答

模拟的全部意义在于向您展示这种变化是现实的。 事实上,你的结果似乎没有任何问题——只是你还没有做足够的模拟来理解他们告诉你的东西。在这种情况下,结果特别不稳定,因为起始人口非常少。

让我们将您的场景运行 500 次,直到 300 人口(而不是六次到 3 人口):

图1

当您从更大的人口开始时,它看起来更稳定:

图 2

只是为了好玩,这里有一个类似的模拟,人口从一个人增长到其承载能力:

图 3

我用于R这些模拟和绘图,因为它做了一件非常有趣的事情。由于您事先知道总体将从初始总体到最终总体逐步进行,因此您可以在模拟之前轻松生成总体值序列。 因此,剩下的就是生成一组指数分布的变量,其速率由该序列确定,并累积它们以模拟出生时间。 R使用单个命令(在下面创建的行simulation)执行该操作。大约需要一秒钟。其他一切都只是参数规范和绘图。

(我可以使用这样一个简单的算法,因为我将这些模拟运行到给定的人口目标而不是给定的时间端点。显然模型是相同的;不同的是我如何控制模拟的长度.)

rate <- 1
pop.0 <- 1
time.0 <- 0
k <-   0        # Carrying capacity (use 0 or negative when not applicable)
n.final <- 300  # Must not exceed the capacity!
#
# Pre-calculation: populations and the associated rates.
#
n <- pop.0:(n.final-1)
if (k <= 0) r <- rate * n else r <- rate * n * (1 - n/k)
#
# The simulation.
# Each iteration is stored as a column of the result.
#
simulation <- replicate(500, cumsum(c(time.0, rexp(length(n), r))))
#
# Plot the results:
# Set it up, show the overlaid growth curves, then plot a reference curve.
#
plot(range(simulation), c(pop.0, n.final), type="n", ylab="Population", xlab="Time")
apply(simulation, 2, function(x) lines(x, c(n, n.final), col="#00000020"))
if (k <= 0) {curve(pop.0 * exp((x - time.0)*rate), add=TRUE, col="Red", lwd=2)} else
    curve(k*(1 - 1/(1+(pop.0/(k-pop.0))*exp(rate*(x-time.0)))), add=TRUE, col="Red", lwd=2)