R simmer:选择服务器的自定义逻辑
R simmer: custom logic for selecting server
我正在构建一个 simmer
模拟通过无人机运送疫苗。模拟部分的伪代码是:
- 在一个地理区域中生成 N 个“需求点”,代表需要疫苗的位置。制作成数据框。添加到达时间作为数据框列。添加优先级列 - 先到先得。
- 使用 kmeans 聚类找到整个地理区域的 K 个无人机站位置
- 生成一个 N x K 矩阵,表示从每个无人机站到每个需求点的行程时间
在模拟中,疫苗运送是到达,无人机是资源(服务器容量1,无限队列容量)。我希望模拟使用此资源 selection logic:
- 到达时,确定可用的无人机。其中,select 飞行时间矩阵确定的飞行时间最短的无人机。
- 如果当前使用了所有无人机,则新来的无人机会被放入一个公共队列中。每当任何无人机可用时,公共队列中的到达者优先,队列中最老的到达者优先。这可能意味着最近的无人机站没有提供疫苗。
- 到达后
seize_selected
selected 无人机,timeout
飞行时间,然后 release_selected
无人机。
我正在尝试调整 中的逻辑,但没有按预期工作。
感谢任何帮助。对我来说真正棘手的部分是将到达的飞机放入公共队列,然后 select使用最快的无人机。
我目前的模拟代码是:
delivery_env <- simmer()
delivery_traj <- trajectory("delivery") %>%
set_attribute(c("min_drone_index", "min_drone_delay"), function() {
# find available resources
server_count <- numeric(drone_count)
for (i in 1:length(server_count)){server_count[i] <- get_server_count(delivery_env, paste0("drone", i)) }
#find index of minimum travel time, inclusive of server_count
#since the capacity of each drone is 1, we want to find the drones
#that have server_count == 1 and set them "very very far away" from the deliverypoint
#so the ranking system puts them last
#identify row of traveltime_matrix that corresponds to the delivery point
#in traveltime_matrix, rows are vaccines, columns are drones
k <- get_attribute(delivery_env, "arrival_index_index1")
traveltime_vec <- traveltime_matrix[k, ]
#make the currently-occupied drones, "very very far away"
traveltime_vec[which(server_count==1)] <- traveltime_vec[which(server_count==1)]+ 9999999999
#identify a single value for the minimum distance - more than 1 drone index may be the minimum
#identify closest available. randomly sample if more than 1 is closest
k <- which.min(traveltime_vec)
min_drone_index <- sample(k,1)
#the drone (resource) is seized for 2x the one-way travel time, plus time on the ground.
min_drone_delay <- 2*traveltime_vec[min_drone_index] + delivery_ontheground_time_minutes
# take the nearest available resource.
return(c(min_drone_index, min_drone_delay))
}) %>%
simmer::select(function() paste0("drone", get_attribute(delivery_env, "min_drone_index"))) %>%
seize_selected() %>%
timeout_from_attribute("min_drone_delay") %>%
release_selected() %>%
#release("drone") %>%
log_("Delivery Finished")
delivery_env <-
simmer("drone") %>%
add_resource(name= paste0("drone",seq(1,drone_count,1)), capacity=1) %>%
add_dataframe(name_prefix='delivery',trajectory = delivery_traj, data=pointsdf,mon=2,batch=50,col_priority="priority",
col_time = "absolute_time", time ="absolute",col_attributes = c("longitude","latitude","arrival_index_index1","arrival_index_index0"))
sim_out <- delivery_env %>% run()
您还需要一个额外的资源,其容量等于无人机的数量。那是你的公共队列。如果您需要先到达最年长的孩子,那就是后进先出法。根据计数器函数设置优先级值将完全实现这一点(或者,如果您在源数据框中设置该优先级,那也可以)。将所有内容放在一起:
prio_counter <- function() {
i <- 0
function() {
i <<- i + 1
c(i, NA, NA)
}
}
delivery_traj <- trajectory("delivery") %>%
set_prioritization(prio_counter()) %>%
seize("common_queue") %>%
set_attribute(c("min_drone_index", "min_drone_delay"), function() {
...
}) %>%
simmer::select(...) %>%
seize_selected() %>%
timeout_from_attribute("min_drone_delay") %>%
release_selected() %>%
release("common_queue") %>%
log_("Delivery Finished")
顺便说一句:get_server_count()
(以及所有其他吸气剂)是矢量化的,那里不需要循环。
我正在构建一个 simmer
模拟通过无人机运送疫苗。模拟部分的伪代码是:
- 在一个地理区域中生成 N 个“需求点”,代表需要疫苗的位置。制作成数据框。添加到达时间作为数据框列。添加优先级列 - 先到先得。
- 使用 kmeans 聚类找到整个地理区域的 K 个无人机站位置
- 生成一个 N x K 矩阵,表示从每个无人机站到每个需求点的行程时间
在模拟中,疫苗运送是到达,无人机是资源(服务器容量1,无限队列容量)。我希望模拟使用此资源 selection logic:
- 到达时,确定可用的无人机。其中,select 飞行时间矩阵确定的飞行时间最短的无人机。
- 如果当前使用了所有无人机,则新来的无人机会被放入一个公共队列中。每当任何无人机可用时,公共队列中的到达者优先,队列中最老的到达者优先。这可能意味着最近的无人机站没有提供疫苗。
- 到达后
seize_selected
selected 无人机,timeout
飞行时间,然后release_selected
无人机。
我正在尝试调整
感谢任何帮助。对我来说真正棘手的部分是将到达的飞机放入公共队列,然后 select使用最快的无人机。
我目前的模拟代码是:
delivery_env <- simmer()
delivery_traj <- trajectory("delivery") %>%
set_attribute(c("min_drone_index", "min_drone_delay"), function() {
# find available resources
server_count <- numeric(drone_count)
for (i in 1:length(server_count)){server_count[i] <- get_server_count(delivery_env, paste0("drone", i)) }
#find index of minimum travel time, inclusive of server_count
#since the capacity of each drone is 1, we want to find the drones
#that have server_count == 1 and set them "very very far away" from the deliverypoint
#so the ranking system puts them last
#identify row of traveltime_matrix that corresponds to the delivery point
#in traveltime_matrix, rows are vaccines, columns are drones
k <- get_attribute(delivery_env, "arrival_index_index1")
traveltime_vec <- traveltime_matrix[k, ]
#make the currently-occupied drones, "very very far away"
traveltime_vec[which(server_count==1)] <- traveltime_vec[which(server_count==1)]+ 9999999999
#identify a single value for the minimum distance - more than 1 drone index may be the minimum
#identify closest available. randomly sample if more than 1 is closest
k <- which.min(traveltime_vec)
min_drone_index <- sample(k,1)
#the drone (resource) is seized for 2x the one-way travel time, plus time on the ground.
min_drone_delay <- 2*traveltime_vec[min_drone_index] + delivery_ontheground_time_minutes
# take the nearest available resource.
return(c(min_drone_index, min_drone_delay))
}) %>%
simmer::select(function() paste0("drone", get_attribute(delivery_env, "min_drone_index"))) %>%
seize_selected() %>%
timeout_from_attribute("min_drone_delay") %>%
release_selected() %>%
#release("drone") %>%
log_("Delivery Finished")
delivery_env <-
simmer("drone") %>%
add_resource(name= paste0("drone",seq(1,drone_count,1)), capacity=1) %>%
add_dataframe(name_prefix='delivery',trajectory = delivery_traj, data=pointsdf,mon=2,batch=50,col_priority="priority",
col_time = "absolute_time", time ="absolute",col_attributes = c("longitude","latitude","arrival_index_index1","arrival_index_index0"))
sim_out <- delivery_env %>% run()
您还需要一个额外的资源,其容量等于无人机的数量。那是你的公共队列。如果您需要先到达最年长的孩子,那就是后进先出法。根据计数器函数设置优先级值将完全实现这一点(或者,如果您在源数据框中设置该优先级,那也可以)。将所有内容放在一起:
prio_counter <- function() {
i <- 0
function() {
i <<- i + 1
c(i, NA, NA)
}
}
delivery_traj <- trajectory("delivery") %>%
set_prioritization(prio_counter()) %>%
seize("common_queue") %>%
set_attribute(c("min_drone_index", "min_drone_delay"), function() {
...
}) %>%
simmer::select(...) %>%
seize_selected() %>%
timeout_from_attribute("min_drone_delay") %>%
release_selected() %>%
release("common_queue") %>%
log_("Delivery Finished")
顺便说一句:get_server_count()
(以及所有其他吸气剂)是矢量化的,那里不需要循环。