! Setting Staff levels in a system
with random arrivals and random service times;
! Customer requests for service arrive randomly at
one or more service groups. Each request is handled
by one of several servers in the group. The time
to handle the request is a random variable. If all
servers in the group are busy, then the request
waits until a server is free.
For each service group we know the mean arrival rate
of requests, the mean service time, and the standard
deviation in service time.
We are interested in how many servers, e.g., tech support people,
to allocate to each service group, given a fixed
number of servers available overall.
Because arrivals and service times are random, if we set
capacity only slightly larger than incoming load, there may
be intervals in which large queues develop, and so the
average waiting time will be large. To reduce average waiting
time we must increase capacity above the average arriving load.
If arrivals are in a stationary Poisson process, and
the service times have an exponential distribution,
the socalled M/M/c case, then the calculated results are exact,
else they are approximate.;
! Keywords: Staff scheduling, Service level, Queuing, M/M/C queue,
M/G/C queue, Customer support, Erlang C;
SETS:
GROUP: ARATE, STIME, SDST,
NSRVRS, LBSRVR, LOAD, PWAIT, WAITCND, WAITUNC, WAITMGC;
ENDSETS
DATA:
! Names of the service groups;
GROUP= TECH1 DBASE OFFICE;
! Arrival rate in customers/hour;
ARATE = 1.2 2.3 2.9;
! Mean service time/customer in hours;
STIME = 2.5 1.75 1.25;
! Standard deviation in service time;
SDST = 2.1 2.3 1.9;
NSAVAIL = 18; ! Number servers available overall;
ENDDATA
SUBMODEL MULTI_MGC:
! Minimize the expected wait time over all groups;
MIN = @SUM( GROUP(g): ARATE(g)*WAITMGC(g));
! Cannot use more servers than available;
@SUM( GROUP(g): NSRVRS(g)) <= NSAVAIL;
@FOR( GROUP(g):
! Average no. of busy servers in group g;
LOAD(g) = ARATE(g) * STIME(g);
! Lower bound on number of servers by group;
LBSRVR(g) = @FLOOR( LOAD(g) + 0.99999);
NSRVRS(g) >= LBSRVR(g);
@GIN( NSRVRS(g)); ! Must be integer valued;
! Fraction of calls that wait, the Erlang C calculation.
Assumes Poisson arrivals, exponential service time distribution. ;
PWAIT(g) = @PEB( LOAD, NSRVRS(g));
! Conditional expected wait, i.e., for customers who must wait,
what is their average wait for the queue M/M/C;
WAITCND(g) = STIME(g)/( NSRVRS(g)  LOAD);
! Unconditional expected wait, including those who wait 0;
WAITUNC(g) = PWAIT(g) * WAITCND(g);
! An approximation for General, nonexponential service times,
the M/G/C queue;
WAITMGC(g) = WAITUNC(g)*(1 + SDST(g)*SDST(g)/(STIME(g)*STIME(g)))/2;
);
ENDSUBMODEL
CALC:
@SET("TERSEO",2); ! Turn off default output;
@SET('GLOBAL',1); ! Use the Global solver;
@SOLVE( MULTI_MGC);
! Generate a little report;
@WRITE(' Best allocation of ',NSAVAIL,' servers.',@NEWLINE(1));
@WRITE(' Service group No. servers Est. wait time', @NEWLINE(1));
@WRITE('   ', @NEWLINE(1));
@FOR( GROUP(g):
@WRITE( @FORMAT( GROUP(g),"12s"),' ', @FORMAT(NSRVRS(g),"5.0f"),
' ', @FORMAT( WAITMGC(g),"9.2f"), @NEWLINE(1));
);
ENDCALC
