使用Simmer构建特定模型

时间:2017-07-01 22:31:06

标签: r simulation

我获得了有关实际事件的数据,我需要对可能发生的情况进行建模,如果有不同的资源可用。下一阶段将是建立一个适当的"模拟,其中事件和时间更随机地创建。我的问题是,我无法确定如何确保特定活动被分配了它在现实生活中的开始时间,优先级和超时。

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)也从数据帧中读取。我无法确定如何确保指定活动优先级和时间的行也将用于指定持续时间(或&#34;超时&#34;)。

1 个答案:

答案 0 :(得分:2)

首先,您必须确保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