Using the queuecomputer package

Anthony Ebert

2017-04-11

Introduction

The purpose of the package queuecomputer is to compute, deterministically, the output of a queue network given the arrival and service times for all customers. The most important functions are queue_step, lag_step and wait_step.

Input format

The first argument to the functions queue_step, lag_step and wait_step is a vector of arrival times. For example:

library(queuecomputer)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
arrivals <- cumsum(rexp(100))

head(arrivals)
## [1] 2.262266 5.986274 6.280253 6.347830 7.185039 7.708771
service <- rexp(100)

departures <- queue_step(arrivals = arrivals, service = service)

print(departures, n = 6)
## # A tibble: 100 × 6
##   arrivals   service departures      waiting system_time server
##      <dbl>     <dbl>      <dbl>        <dbl>       <dbl>  <dbl>
## 1 2.262266 0.1923963   2.454662 8.326673e-17   0.1923963      1
## 2 5.986274 1.7214155   7.707689 2.220446e-16   1.7214155      1
## 3 6.280253 0.9915863   8.699276 1.427436e+00   2.4190226      1
## 4 6.347830 0.9092315   9.608507 2.351445e+00   3.2606767      1
## 5 7.185039 0.1131049   9.721612 2.423468e+00   2.5365734      1
## 6 7.708771 0.7935246  10.515137 2.012842e+00   2.8063661      1
## # ... with 94 more rows

Resourcing schedule

The resourcing schedule is specified with either a non-zero natural number, a server.stepfun or a server.list object. Use a non-zero natural number when the number of servers does not change over time. The server.stepfun specifies a step function to indicate how many servers are available throughout the day. The computation speed for queue_step() is much faster when using a server.stepfun rather than a server.list input for the servers argument.

We create a server.stepfun object with the as.server.stepfun function.

# Zero servers available before time 10
# One server available between time 10 and time 50
# Three servers available between time 50 and time 100
# One server available from time 100 onwards
resource_schedule <- as.server.stepfun(c(10,50,100), c(0, 1, 3, 1))

resource_schedule
## $x
## [1]  10  50 100
## 
## $y
## [1] 0 1 3 1
## 
## attr(,"class")
## [1] "list"           "server.stepfun"
departures <- queue_step(arrivals = arrivals, service = service, servers = resource_schedule)

print(departures, n = 6)
## # A tibble: 100 × 6
##   arrivals   service departures  waiting system_time server
##      <dbl>     <dbl>      <dbl>    <dbl>       <dbl>  <dbl>
## 1 2.262266 0.1923963   10.19240 7.737734    7.930131      1
## 2 5.986274 1.7214155   11.91381 4.206122    5.927538      1
## 3 6.280253 0.9915863   12.90540 5.633559    6.625145      1
## 4 6.347830 0.9092315   13.81463 6.557568    7.466799      1
## 5 7.185039 0.1131049   13.92773 6.629591    6.742696      1
## 6 7.708771 0.7935246   14.72126 6.218964    7.012489      1
## # ... with 94 more rows

The server.list object is a list of step functions which represent each server, the range is \(\{0,1\}\), where 0 represents unavailable and 1 represents available and the knots represent the times where availability changes.

The as.server.list function is used to create a server.list object.

# Server 1 is available before time 10.
# Server 2 is available between time 15 and time 30.
# Server 3 is available after time 10. 
as.server.list(list(10, c(15,30), 10), c(1,0,0))
## [[1]]
## Step function
## Call: stats::stepfun(times[[i]], y)
##  x[1:1] =     10
## 2 plateau levels =      1,      0
## 
## [[2]]
## Step function
## Call: stats::stepfun(times[[i]], y)
##  x[1:2] =     15,     30
## 3 plateau levels =      0,      1,      0
## 
## [[3]]
## Step function
## Call: stats::stepfun(times[[i]], y)
##  x[1:1] =     10
## 2 plateau levels =      0,      1
## 
## attr(,"class")
## [1] "list"        "server.list"

Setting up a queue network

It is simple to set up a chain of queueing elements with queuecomputer. Suppose passengers must walk to a queue, then wait for service and then wait for their bags.

library(queuecomputer)
library(dplyr)

set.seed(500)

n <- 100

arrivals <- cumsum(rexp(n))
service_l <- rexp(n, 0.8)
service_q <- rexp(n, 0.5)
arrivals_b <- cumsum(rexp(n, 0.8))

# The queue elements can be computed one by one. 

departures_1 <- lag_step(arrivals, service_l)
departures_2 <- queue(departures_1, service = service_q, servers = 2)
departures_3 <- wait_step(departures_2, arrivals_b)

# Or the queue elements can be chained together with the %>% operator. 

departures <- lag_step(arrivals, service_l) %>% queue_step(service = service_q, servers = 2) %>% wait_step(arrivals_b)

all(departures == departures_3)
## [1] TRUE
# Plot densities for this tandem queueing network

colours <- rainbow(4)
plot(density(arrivals, from = 0), 
  col = colours[1], xlim = c(0, 220), ylim = c(0, 0.015), 
  main = "Density plot")
lines(density(departures_1, from = 0), col = colours[2])
lines(density(departures_2, from = 0), col = colours[3])
lines(density(departures_3, from = 0), col = colours[4])
legend(150,0.012, legend = c("Start walk",
    "Finish walk",
    "Finish service", 
    "Pick up bag"),
    col = colours, lwd = 1, cex = 0.8
)