我在R中运行离散事件模拟。我算法的“核心”执行以下操作(伪代码):
1)迭代
events
a)变化
event[i]
取决于
resources
b)变化
资源
取决于步骤a)的结果
以下可重复的示例捕获主要方面:
生成一些数据:
set.seed(4)
n <- 3
nr_resources <- 2
events <- data.frame(
t = as.integer(trunc(cumsum(rexp(n)))),
resource = NA,
worktime = as.integer(trunc(runif(n)*10))
)
resources <- data.frame(
id = 1:nr_resources,
t_free = 0L
)
events
resources
# > events
# t resource worktime
# 0 NA 2
# 4 NA 8
# 5 NA 2
# > resources
# id t_free
# 1 0
# 2 0
现在我们可以模拟资源调度:
for (i in 1:n) {
events$resource[i] <- resources$id[resources$t_free <= events$t[i]][1]
resources$t_free[events$resource[i]] <- events$t[i] + events$worktime[i]
}
events
resources
# > events
# t resource worktime
# 0 1 2
# 4 1 8
# 5 2 2
# > resources
# id t_free
# 1 12
# 2 7
这种方法工作得很好,但我想消除一些缺点。自从
事件
和
资源
被分成两个数据集,两个数据集之间有相当多的子集(搜索和替换)。这不是真正的可读性。在实际应用中,它甚至成为性能瓶颈。(当然,真正的例子要复杂得多。)
因此,我问自己是否有更好的方法来完成这项任务在R。
我考虑用一个普通的高阶函数替换for循环,但没有得到任何结果。
-
典型的R
lapply
-方法不起作用,因为
勒普
不是为输入数据中的此迭代更改而生成的。(据我所见)
-
我的任务有点像
Reduce
模式。自从
Reduce(sum, 1:3, accumulate = TRUE)
使用中间结果并保存它们,我想我可以使用
减少
但没有取得任何效果。
我也考虑过重组我的数据,但直到现在都没有成功。
我详细尝试过的
上
算法的
侧面:
失败的方法
勒普
:
l <- list(events = events, resources = resources)
l <- lapply(l, function(x) {
l$events$resource <- l$resources$id[l$resources$t_free <= l$events$t][1]
l$resources$t_free[l$events$resource] <- l$events$t + l$events$worktime
return(l)
})
l$events
l$resources
结果变成:
# $events
# t resource worktime
# 1 0 1 2
# 2 4 1 8
# 3 5 1 2
#
# $resources
# id t_free
# 1 1 7
# 2 2 0
对资源的中间更改将丢失,因此总是会预订资源1。
失败的方法
减少
:
l <- list(events = events, resources = resources)
l <- Reduce(function(l) {
l$events$resource <- l$resources$id[l$resources$t_free <= l$events$t][1]
l$resources$t_free[l$events$resource] <- l$events$t + l$events$worktime
return(l)}, l, accumulate = TRUE)
失败的原因是
f中的错误(init,x[[i]]):未使用的参数(x[[i]])
上
数据
侧面:
我能想到的另一种方法是
更改数据
在一个数据集中表示。例如,将事件乘以资源数。我尝试了以下方法:
data <- merge(events, resources)
data <- data[order(data$t), ]
data
# t resource worktime id t_free
# 0 NA 2 1 0
# 0 NA 2 2 0
# 4 NA 8 1 0
# 4 NA 8 2 0
# 5 NA 2 1 0
# 5 NA 2 2 0
for (i in seq_along(data)) {
if ( is.na(data$resource[i])) {
data$resource[data$t == data$t[i]] <- data$id[data$t_free <= data$t[i]][1]
data$t_free[data$id == data$resource[i]] <- data$t[i] + data$worktime[i]
}
}
data
# t resource worktime id t_free
# 0 1 2 1 12
# 0 1 2 2 7
# 4 1 8 1 12
# 4 1 8 2 7
# 5 2 2 1 12
# 5 2 2 2 7
events <- unique(data[,1:3])
events
# t resource worktime
# 0 1 2
# 4 1 8
# 5 2 2
resources <- unique(data[,4:5])
resources
# id t_free
# 1 12
# 2 7
这也很有效,但我不确定这是否会带来更好的性能、可读性和可伸缩性。
所以我的问题是:
有其他的选择吗
算法的
侧面或侧面
数据
改进我实际解决方案的那一面?