【问题标题】:R simmer: custom logic for selecting serverR simmer:选择服务器的自定义逻辑
【发布时间】:2021-07-28 16:02:15
【问题描述】:

我正在构建一个simmer 模拟,用于通过无人机运送疫苗。仿真部分的伪代码是:

  1. 在地理中生成 N 个“需求点”,代表需要疫苗的位置。做成一个数据框。将到达时间添加为数据框列。添加优先级列 - 先到先得。
  2. 使用 kmeans 聚类在整个地理范围内查找 K 个无人机站点位置
  3. 生成一个 N x K 矩阵,表示从每个无人机站点到每个请求点的行程时间

在模拟中,疫苗交付是到达,无人机是资源(服务器容量 1,无限队列容量)。我希望模拟使用这个资源选择逻辑:

  1. 当到达时,确定哪些无人机可用。其中,根据行程时间矩阵,选择行程时间最短的无人机。
  2. 如果当前使用了所有无人机,则新来的无人机将被放入一个公共队列中。每当有任何无人机可用时,公共队列中的到达优先,队列中最早到达的优先。这可能意味着疫苗不是从最近的无人机站运送的。
  3. 一旦到达seize_selected 所选无人机,timeout 为旅行时间,然后release_selected 那架无人机。

我正在尝试调整 Use routing logic when dispatching resources with simmer package (or an alternative) 的逻辑,但没有按预期工作。

感谢任何帮助。对我来说真正棘手的部分是将到达的人放入一个共同的队列中,然后选择最快的可用无人机。
我目前的模拟代码是:

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()

【问题讨论】:

    标签: r simulation event-simulation


    【解决方案1】:

    除此之外,您还需要容量等于无人机数量的额外资源。那是你的普通队列。如果您需要最先到达的时间,那就是 LIFO。根据计数器函数设置优先级值将完全实现这一点(或者,如果您在源数据框中设置该优先级,那也可以)。把所有东西放在一起:

    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()(以及所有其他吸气剂)是矢量化的,你不需要在那里循环。

    【讨论】:

    • 谢谢,这似乎运作良好。我需要更深入地研究结果以查看我的 select() 函数是否按预期工作,但排队问题已得到修复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-22
    • 2011-02-19
    • 1970-01-01
    • 2016-12-24
    • 2022-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多