Skip to content

Instantly share code, notes, and snippets.

@amackey
Created January 5, 2011 14:59
Show Gist options
  • Save amackey/766418 to your computer and use it in GitHub Desktop.
Save amackey/766418 to your computer and use it in GitHub Desktop.
elevator simulation code
nmin <- 120;
time <- nmin * 60;
lambda <- 10/60; # 10 passengers every minute, on average
arrivals <- rpois(time, lambda);
population <- sum(arrivals);
nelev <- 4; # number of elevators
nfloor <- 7; # number of floors
elevators <- matrix(1, ncol=nelev, nrow=time)
entry <- 10; # seconds for doors to open, people to enter, doors to close
exit <- 10; # seconds for doors to open, people to leave, doors to close
speed <- 1/5; # floors/second
max <- 10; # (soft) maximum number of passengers per car
waiting <- 0; # how many people are currently waiting
waittimes <- integer(0); # vector of waiting times for currently waiting
totalwait <- integer(0); # total wait for those whose elevators left before the end
passengers <- integer(nelev); # number of passengers boarding each elevator
departing <- integer(nelev); # number of seconds until each elevator will depart, if boarding
for (t in 1:time) {
# any elevators about ready to go?
if (any(departing == 1)) {
leaving <- which(departing == 1);
while (length(leaving)) {
elevator <- leaving[1];
leaving <- leaving[-1];
totalwait <- c(totalwait, waittimes[1:passengers[elevator]]);
waittimes <- waittimes[-(1:passengers[elevator])];
dests <- sample(2:nfloor, passengers[elevator], replace=T); # random individual destinations
stops <- sort(unique(dests)); # floors to stop at
dists <- rev(rev(stops) - c(rev(stops)[-1],1)); # distance between stops
offset <- t;
d <- 1;
while (offset < time && d <= length(dists)) {
# time spent between stops:
enroute <- min(offset+as.integer(round(dists[d] / speed, 0)), time);
elevators[offset:enroute, elevator] <- NA;
offset <- enroute;
# time spent exiting at each stop:
onfloor <- min(offset+exit, time);
elevators[offset:onfloor, elevator] <- stops[d];
offset <- onfloor+1;
d <- d + 1;
}
# time spent returning back to first floor:
if (offset < time) {
enroute <- min(offset+as.integer(round(sum(dists)/speed, 0)), time);
elevators[offset:enroute, elevator] <- NA;
}
passengers[elevator] <- 0; # reset passenger count.
}
}
# count down for departing elevator(s):
departing <- departing - ifelse(departing, 1, 0);
# add any new arrivals to the waiting line:
waiting <- waiting + arrivals[t];
waittimes <- c(waittimes, rep(0, arrivals[t]));
if (waiting > 0) {
# board anyone we can:
available <- which(elevators[t,] == 1 & passengers <= max);
while (waiting > 0 && length(available) > 0) {
elevator <- available[1]; # first available elevator
available <- available[-1]; # remove this elevator from available list
boarding <- min(waiting, max-passengers[elevator]);
passengers[elevator] <- passengers[elevator] + boarding;
waiting <- waiting - boarding;
# mark when this elevator will depart: "entry" seconds for first passenger(s),
# and +1 additional second for each new set of arrivals before departure
departing[elevator] <- departing[elevator] + ifelse(departing[elevator], 1, entry)
}
}
# update how long everyone has been waiting:
waittimes <- waittimes + 1;
}
image(list(x=1:500, y=1:4, z=elevators[1:500,]),col=rainbow(7), ylab="elevator",xlab="time")
for (f in 1:nelev) {
floors <- rle(elevators[1:500, f]);
text(cumsum(floors$lengths)[!is.na(floors$values)]-(exit/2), f, floors$values[!is.na(floors$values)])
}
@GHoernchen
Copy link

Hi,

this is probably late to ask, but why do you add an additional second for each new set of arrivals before departure on line 84?

Thanks

@GHoernchen
Copy link

Something else: variable population is never used :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment