使用 Simmer 构建特定模型
Using Simmer to build a specific model
我有实际事件的数据,我需要模拟如果有不同的资源可能会发生什么。下一阶段将构建一个 "proper" 模拟,其中事件和时间的创建更加随机。我的问题是我无法弄清楚如何确保为特定的 activity 分配实际生活中的开始时间、优先级和超时。
library(simmer)
set.seed(654)
env <- simmer()
workerCount <- 2
actualData <- data.frame(arrTime = c(1:10,1:5),
priority = 1:3, duration = rnorm(15, 50, 5))
activityTraj <- trajectory() %>%
seize('worker') %>%
timeout(5) %>%
release('worker')
env %>%
add_resource('worker', workerCount, Inf, preemptive = TRUE) %>%
add_generator('worker', activityTraj, at(actualData$arrTime),
mon = 2, priority = 2)
env %>% run(50)
我在上面需要做的是让生成器中的优先级从数据帧中读取(当前硬编码为 2),轨迹中的超时(当前硬编码为 5)也从数据框。我看不出如何确保指定 activity 的优先级和时间的行也将用于指定持续时间(或 "timeout")。
首先,您必须确保您的actualData
帧按arrTime
:
排序
actualData <- data.frame(arrTime = c(1:10,1:5),
priority = 1:3,
duration = rnorm(15, 50, 5)) %>%
dplyr::arrange(arrTime)
然后,让我们构建一个辅助函数来使用您的 actualData
:
的列
consume <- function(x, prio=FALSE) {
i <- 0
function() {
i <<- i + 1
if (prio) c(x[[i]], x[[i]], FALSE)
else x[[i]]
}
}
可以按如下方式应用于您的轨迹:
activityTraj <- trajectory() %>%
set_prioritization(consume(actualData$priority, TRUE)) %>%
set_attribute("duration", consume(actualData$duration)) %>%
seize('worker') %>%
timeout(function(attr) attr["duration"]) %>%
release('worker')
因为您的到达时间已排序。最后,让我们运行模拟一下:
env %>%
add_resource('worker', workerCount, Inf, preemptive = TRUE) %>%
add_generator('worker_', activityTraj, at(actualData$arrTime)) %>%
run()
并检查实际持续时间是否正常:
activity_time <- get_mon_arrivals(env) %>%
tidyr::separate(name, c("prefix", "n"), convert=TRUE) %>%
dplyr::arrange(n) %>%
dplyr::pull(activity_time)
all(activity_time == actualData$duration)
#> TRUE
更新:自simmer v3.8.0以来,新的数据源add_dataframe
大大简化了这种模式:
library(simmer)
workerCount <- 2
actualData <- data.frame(
time = c(1:10,1:5), priority = 1:3, service = rnorm(15, 50, 5)) %>%
dplyr::arrange(time)
activityTraj <- trajectory() %>%
seize('worker') %>%
timeout_from_attribute("service") %>%
release('worker')
env <- simmer() %>%
add_resource('worker', workerCount, Inf, preemptive = TRUE) %>%
add_dataframe('worker_', activityTraj, actualData, time="absolute") %>%
run()
activity_time <- get_mon_arrivals(env) %>%
tidyr::separate(name, c("prefix", "n"), convert=TRUE) %>%
dplyr::arrange(n) %>%
dplyr::pull(activity_time)
all(activity_time == actualData$duration)
#> TRUE
我有实际事件的数据,我需要模拟如果有不同的资源可能会发生什么。下一阶段将构建一个 "proper" 模拟,其中事件和时间的创建更加随机。我的问题是我无法弄清楚如何确保为特定的 activity 分配实际生活中的开始时间、优先级和超时。
library(simmer)
set.seed(654)
env <- simmer()
workerCount <- 2
actualData <- data.frame(arrTime = c(1:10,1:5),
priority = 1:3, duration = rnorm(15, 50, 5))
activityTraj <- trajectory() %>%
seize('worker') %>%
timeout(5) %>%
release('worker')
env %>%
add_resource('worker', workerCount, Inf, preemptive = TRUE) %>%
add_generator('worker', activityTraj, at(actualData$arrTime),
mon = 2, priority = 2)
env %>% run(50)
我在上面需要做的是让生成器中的优先级从数据帧中读取(当前硬编码为 2),轨迹中的超时(当前硬编码为 5)也从数据框。我看不出如何确保指定 activity 的优先级和时间的行也将用于指定持续时间(或 "timeout")。
首先,您必须确保您的actualData
帧按arrTime
:
actualData <- data.frame(arrTime = c(1:10,1:5),
priority = 1:3,
duration = rnorm(15, 50, 5)) %>%
dplyr::arrange(arrTime)
然后,让我们构建一个辅助函数来使用您的 actualData
:
consume <- function(x, prio=FALSE) {
i <- 0
function() {
i <<- i + 1
if (prio) c(x[[i]], x[[i]], FALSE)
else x[[i]]
}
}
可以按如下方式应用于您的轨迹:
activityTraj <- trajectory() %>%
set_prioritization(consume(actualData$priority, TRUE)) %>%
set_attribute("duration", consume(actualData$duration)) %>%
seize('worker') %>%
timeout(function(attr) attr["duration"]) %>%
release('worker')
因为您的到达时间已排序。最后,让我们运行模拟一下:
env %>%
add_resource('worker', workerCount, Inf, preemptive = TRUE) %>%
add_generator('worker_', activityTraj, at(actualData$arrTime)) %>%
run()
并检查实际持续时间是否正常:
activity_time <- get_mon_arrivals(env) %>%
tidyr::separate(name, c("prefix", "n"), convert=TRUE) %>%
dplyr::arrange(n) %>%
dplyr::pull(activity_time)
all(activity_time == actualData$duration)
#> TRUE
更新:自simmer v3.8.0以来,新的数据源add_dataframe
大大简化了这种模式:
library(simmer)
workerCount <- 2
actualData <- data.frame(
time = c(1:10,1:5), priority = 1:3, service = rnorm(15, 50, 5)) %>%
dplyr::arrange(time)
activityTraj <- trajectory() %>%
seize('worker') %>%
timeout_from_attribute("service") %>%
release('worker')
env <- simmer() %>%
add_resource('worker', workerCount, Inf, preemptive = TRUE) %>%
add_dataframe('worker_', activityTraj, actualData, time="absolute") %>%
run()
activity_time <- get_mon_arrivals(env) %>%
tidyr::separate(name, c("prefix", "n"), convert=TRUE) %>%
dplyr::arrange(n) %>%
dplyr::pull(activity_time)
all(activity_time == actualData$duration)
#> TRUE