После этого вы найдете возможное решение для вашего минимального примера с пакетом simmer
.
Сначала мы выбрали альтернативу имитации, которая позже используется в set_attribute
:
sim_first_available <- T
sim_use_nearest <- F
Создайте данные events
и resources
, как и раньше.
set.seed(1)
events <- data.frame(
id = 1:3L,
t = sort(trunc(rexp(3) * 100)),
position = runif(3),
resource = NA,
worktime = NA
)
resources <- data.frame(
id = 1:2L,
position = c(0.2, 0.8),
t_free = 0
)
Начать simmer
с траектории sim
.
library(simmer)
sim <- trajectory() %>%
Затем установить t_free
в качестве глобального атрибута.При первом поступлении (t = 14) вы можете использовать t_free
из данных ресурса для инициализации.При последующих поступлениях используйте get_global
, чтобы получить текущий t_free
определенного ресурса.
set_global(paste0("t_free_res_", resources$id), function() {
if (now(env) == 14) {return(resources$t_free) # Initialize parameters when first event arrives
} else {
get_global(env, paste0("t_free_res_", resources$id))
}}) %>%
Теперь определите атрибуты для этого события:
На основе текущего времени моделирования выберитеevent_position
из фрейма данных events
.
set_attribute(c("event_position","my_resource", "timeout"), function() {
t <- now(env)
event_position <- events$position[events$t == t]
my_resource
выбрано в соотв.к альтернативе, которую вы хотите симулировать.
t_free <- get_global(env, paste0("t_free_res_", resources$id))
if (sim_first_available & !sim_use_nearest) {
my_resource <- resources$id[t_free <= now(env)][1]
} else if (!sim_first_available & sim_use_nearest){
ids_free <- resources$id[t_free <= now(env)]
my_resource <- resources$id[which.min(abs(resources$position[ids_free] - event_position))]
}
На основе resource_pos
рассчитать timeout
для этого ресурса и вернуть атрибуты:
resource_pos <- resources$position[resources$id == my_resource]
timeout <- trunc(abs(event_position - resource_pos)*100)
return(c(event_position, my_resource, timeout))
}) %>%
Выберите определенный ресурс и воспользуйтесь им:
select(resources = function() paste0("res_", get_attribute(env, "my_resource"))) %>%
seize_selected(amount = 1) %>%
Теперь перезапишите t_free
этого ресурса, добавив timeout
к текущему времени моделирования.
set_global(function() {
paste0("t_free_res_", get_attribute(env, "my_resource"))
}, function() {
return(now(env) + get_attribute(env, "timeout"))
}) %>%
Установите рассчитанное время ожидания для ресурса и отпустите его снова.
timeout(function() get_attribute(env, "timeout")) %>%
release_selected(amount = 1)
Наконец, сгенерируйте события для траектории sim
через определенные промежутки времени в событиях, добавьте ресурсы и запустите симуляцию.
env <- simmer() %>%
add_generator("event_", sim, at(events$t), mon = 2) %>%
add_resource("res_1", capacity = 1) %>%
add_resource("res_2", capacity = 1)
env %>% run()
print(get_mon_attributes(env))
print(get_mon_arrivals(env))
print(get_mon_resources(env))
Надеюсь, это поможет.