set_attribute function to identify resource to select, fails when no resources available

32 views
Skip to first unread message

Ralph Asher

unread,
May 15, 2022, 7:23:56 PM5/15/22
to simmer-devel
I am simulating a store's parking lot.  Spaces are resources, cars are on a trajectory.  For simplicity purposes, all parking spaces are in a single file, numbered by their proximity to the store's front door (space1 is closest, space2 is next closest, etc.)

Cars arrive and seize one open space, but there is a preference function - cars generally want to seize the closest open space to the door, but not always.  There is a timeout, then the car releases their space and exit the system.

My code below works fine when I have the timeout set low enough that there is always an available space.  When I raise the timeout (say, to a mean of 120), the lot fills up and I get the error:

Error in sample.int(x, size, replace, prob) :   incorrect number of probabilities

This arises because there isn't any available spaces.  Is there a simple way to avoid this issue?  Perhaps by making cars wait until a spot opens, then seize it?

Thanks
Ralph


-----
#Discrete Event Simulation Example: parking lot
library(tidyverse)
library(magrittr)
library(simmer)
library(simmer.plot)

#clear workspace and run Garbage Collector
rm(list=ls())
gc(T,T,T)
#no scientific notation
options(scipen=999)

parkingspot_count <- 25

car_trajectory <- trajectory("car_in_parkinglot") %>%
set_attribute(c("selected_spot"), function() {
server_count <- get_server_count(parkinglot_env, paste0("space", 1:parkingspot_count))

#find indices of available spaces
open_spaces <- sort(which(server_count ==0))

df <- cbind.data.frame(open_spaces) %>%
dplyr::mutate(prob= 0.5^dplyr::row_number()) %>%
#normalize
dplyr::mutate(prob = prob/sum(prob))
#select a space
space_index <-  sample(x=df$open_spaces,size=1,replace=FALSE,prob=df$prob)
#return space_index, that's the space to occupy
return(space_index) } ) %>%

simmer::select(function() paste0("space", get_attribute(parkinglot_env, "selected_spot"))) %>%
seize_selected() %>%
timeout(function() {max(rnorm(n=1,mean=20,sd=5), 1)}) %>% #normally distributed time, min 1 minute
release_selected() %>%
log_("Left Parking Lot")
 
 
 
parkinglot_env <-   simmer() %>%  
  add_resource(name= paste0("space",1:parkingspot_count), capacity=1) %>%
  add_resource(name = "common_queue", capacity= parkingspot_count, queue_size=Inf)%>%
  add_generator(name_prefix = "Car", trajectory= car_trajectory, function() {rexp(n=1,rate=(20/60))}) #rate is arrivals per unit of time.
  #timeout is in minutes, so arrivals must be in minutes.  want 30 arrivals per hour --> (30/60) arrivals per minute
 
   
sim_out <- parkinglot_env %>% run(until = (60*24))

Iñaki Ucar

unread,
May 16, 2022, 1:19:07 AM5/16/22
to simmer-devel
I'd say you need an additional resource representing the entire parking lot, with as much capacity as parking spots, which must be seized in the first place.

Iñaki

--
You received this message because you are subscribed to the Google Groups "simmer-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to simmer-devel...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/simmer-devel/9c87a9a3-8774-4b2a-9851-5058b2c57662n%40googlegroups.com.

Ralph Asher

unread,
May 16, 2022, 9:45:16 AM5/16/22
to simmer-devel
Thanks, that worked!  I also had to edit my `sample` code a bit.  When I had just a single space available (and thus trying to sample from a one-row dataframe) R didn't like that, so I wrapped it in an ifelse:
space_index <-  ifelse(nrow(df)==1, df$space[1], sample(x=df$space,size=1,replace=FALSE,prob=df$prob))

Simmer is awesome, I talk it up whenever I can in my specialty of supply chain analytics!

Ralph
Reply all
Reply to author
Forward
0 new messages