One barber, one line, one eight-hour day. It is the first model most people write in GPSS. Here it is as a deck, as a chiaha-SLX model, and as the numbers 20 runs of it produce.
Customers walk in every 12 to 24 minutes, any time in that range equally likely. If the barber is free they sit down; if not, they wait in line. A haircut takes 12 to 20 minutes, also uniform. The shop runs for 480 minutes.
The questions are the usual ones: how many customers get a haircut in a day, how long they wait, and how much of the day the barber spends cutting hair. With an average gap of 18 minutes and an average haircut of 16, the barber should be busy about 16/18 of the time over a long stretch. A single day will wander around that.
Two segments. The first moves customers: GENERATE 18,6 makes one every 18 ± 6 minutes, QUEUE and DEPART bracket the wait so the line gets statistics, SEIZE and RELEASE take and free the barber, and ADVANCE 16,4 is the haircut.
The second segment is a timer. One transaction arrives at minute 480 and TERMINATE 1 ends the run.
GENERATE 18,6
QUEUE LINE
SEIZE BARBER
DEPART LINE
ADVANCE 16,4
RELEASE BARBER
TERMINATE
GENERATE 480
TERMINATE 1
deck/barber carries this deck in its header.chiaha-SLX keeps GPSS’s words. facility and queue declare the barber and the line, and a customer’s actions read like the deck from top to bottom: enqueue, seize, depart, advance, release, terminate. The difference is that the times are explicit (rv_uniform(Service, 12.0, 20.0) is 16 ± 4) and each one draws from its own named random stream.
The three totals at the top (served, waited, busy) are plain variables, so “show final values” prints them after each run and the results below are worked out from them.
import <h4>
module barber_h4
{
facility Barber;
queue Line;
rn_stream Arrivals seed=100000;
rn_stream Service seed=200000;
float day_length = 480;
int served;
float waited;
float busy;
object customer
{
float arrived, service;
actions
{
arrived = time;
enqueue Line;
seize Barber;
depart Line;
waited += time - arrived;
service = rv_uniform(Service, 12.0, 20.0);
advance service;
release Barber;
busy += service;
served++;
terminate;
}
}
procedure main
{
arrivals: customer iat = rv_uniform(Arrivals, 12.0, 24.0);
advance day_length;
report(system);
}
}
deck/barber, without its header comment. arrivals: plays the part of GENERATE; advance day_length is the timer segment.One day, as written, run 20 times from seed 1. The spread is the point: the same shop gives quite different days, from a mean wait under half a minute to one over seven.
| Measure | Mean of 20 runs | Lowest to highest run |
|---|---|---|
| Customers served | 25.4 ± 0.5 | 24 to 28 |
| Mean wait in line | 1.99 min ± 0.74 | 0.47 min to 7.24 min |
| Barber utilization | 83.92% ± 1.51 | 78.94% to 90.91% |
± is the 95% confidence interval of the mean over 20 runs.
Change day_length to 48,000 (100 days) and the averages settle onto the arithmetic:
| Measure | Mean of 20 runs | Lowest to highest run | Theory |
|---|---|---|---|
| Customers served per 480 minutes | 26.7 ± 0.1 | 26.5 to 26.9 | 26.7 |
| Mean wait in line | 2.39 min ± 0.08 | 2.13 min to 2.77 min | – |
| Barber utilization | 88.91% ± 0.22 | 88.16% to 89.76% | 88.89% |
Theory here is the means of the uniform times: 480/18 arrivals a day and a barber busy 16/18 of the time. Waiting time has no simple formula with uniform times, so it has no theory column. The full check against queueing theory is on the verification page.
Add a second barber (two facilities and a customer who takes whichever is free; the workspace has it as deck/multi-barber), use a storage for several identical servers as the bank tellers problem does, or make customers give up when the wait is too long, which is the reneging problem. How each GPSS block maps to chiaha-SLX is on the GPSS models page.
GPSS/H is a trademark of its owner. ChiAha is not affiliated with or endorsed by it.