这是一种不同的方法。第一个想法是一次做很多试验。因此,我们有
gamble0 <-
function(n_trials, k, n, p)
{
## create n_trials simulations
stakes <- rep(k, n_trials)
trials <- seq_len(n_trials)
repeat {
## bet on all trials still in play, and update
bet <- sample(c(1, -1), length(trials), TRUE, prob=c(1-p, p))
stakes[trials] <- stakes[trials] + bet
## only continue to follow those trials that have not terminated
trials <- trials[(stakes[trials] > 0L) & (stakes[trials] < n)]
if (length(trials) == 0)
break
}
stakes
}
结果是一个结果向量,计算速度很快,因为我们允许 R 进行 矢量化 计算(例如,调用一次 sample() 以生成 length(trials) 结果,而不是调用它 @ 987654324@次)。
> n <- 100000
> system.time(answer <- gamble0(n, 6, 10, .5))
user system elapsed
0.336 0.000 0.338
> table(answer) / n
answer
0 10
0.39973 0.60027
要在每次模拟中累积曲目,请使用list() 来跟踪仍在播放的每个曲目和试验。一旦我们记录了所有轨道的结果,通过创建轨道和试验的单个向量(通过unlist())并使用split()重新拆分轨道,将迭代列表转换为轨道列表基于轨迹的矢量。
gamble2 <-
function(n_trials, k, n, p)
{
## lists to hold tracks
tracks <- trials <- list()
## initial conditions
i <- 1L
stakes <- rep(k, n_trials)
trial <- seq_len(n_trials)
repeat {
## store current tracks
tracks[[i]] <- stakes
trials[[i]] <- trial
## still more to do?
idx <- (stakes > 0L) & (stakes < n)
if (!any(idx))
break
## update tracks that are still in play
bet <- sample(c(1, -1), sum(idx), TRUE, c(1 - p, p))
stakes <- tracks[[i]][idx] + bet
trial <- trials[[i]][idx]
## increment step
i <- i + 1L
}
## reshape results from list-of-iterations to list-of-tracks
tracks <- unlist(tracks, use.names = FALSE)
trials <- unlist(trials, use.names = FALSE)
tracks <- split(tracks, trials)
## report results
list(iterations = i, tracks = tracks)
}
这是相对较快的,并且可以被操纵来调查属性,例如,
> n_trials <- 100000
> system.time(answer <- gamble2(n_trials, 6, 10, .5))
user system elapsed
2.172 0.000 2.172
> tracks0 <- unlist(answer$tracks, use.names=FALSE)
> last <- cumsum(lengths(answer$tracks))
> table(tracks0[last]) / n_trials
0 10
0.39794 0.60206
> hist(lengths(answer$tracks))
(gamble1(),自从被删除后,试图变得过于聪明,使用环境来存储迭代;R 在增长向量和列表方面变得更好,所以这种聪明是不必要的;这是也与@Gregor 的避免增长向量的建议相关——通过索引超过末尾 x[i] 或 x[[i]] 来增长向量现在在 R 中具有合理的性能。