Simlib to simulate a multiteller bank where the customers are allowed to jockey (move) from one queue to another if it seems to be to their advantage. A bank with five tellers opens its doors at 9 A.M. and closes its doors at 5 P.M., but operates until all customers in the bank by 5 P.M. have been served. Assume that the interarrival times of customers are IID exponential random variables with mean 1 minutes and that service times of customers are IID exponential random variables with mean 4.5 minutes…………….

**mtbank.c**

/* External definitions for multiteller bank. */

#include “simlib.h” /* Required for use of simlib.c. */

#define EVENT_ARRIVAL 1 /* Event type for arrival of a customer. */

#define EVENT_DEPARTURE 2 /* Event type for departure of a customer. */

#define EVENT_CLOSE_DOORS 3 /* Event type for closing doors at 5 P.M. */

#define SAMPST_DELAYS 1 /* sampst variable for delays in queue(s). */

#define STREAM_INTERARRIVAL 1 /* Random-number stream for interarrivals. */

#define STREAM_SERVICE 2 /* Random-number stream for service times. *//* Declare non-simlib global variables. */

int min_tellers, max_tellers, num_tellers, shortest_length, shortest_queue;

float mean_interarrival, mean_service, length_doors_open;

FILE *infile, *outfile;/* Declare non-simlib functions. */

void arrive(void);

void depart(int teller);

void jockey(int teller);

void report(void);int main() /* Main function. */

{

/* Open input and output files. */infile = fopen(“mtbank.in”, “r”);

outfile = fopen(“mtbank.out”, “w”);/* Read input parameters. */

fscanf(infile, “%d %d %f %f %f”, &min_tellers, &max_tellers,

&mean_interarrival, &mean_service, &length_doors_open);/* Write report heading and input parameters. */

fprintf(outfile, “Multiteller bank with separate queues & jockeying\n\n”);

fprintf(outfile, “Number of tellers%16d to%3d\n\n”,

min_tellers, max_tellers);

fprintf(outfile, “Mean interarrival time%11.3f minutes\n\n”,

mean_interarrival);

fprintf(outfile, “Mean service time%16.3f minutes\n\n”, mean_service);

fprintf(outfile,

“Bank closes after%16.3f hours\n\n\n\n”, length_doors_open);/* Run the simulation varying the number of tellers. */

for (num_tellers = min_tellers; num_tellers <= max_tellers; ++num_tellers) {

/* Initialize simlib */

init_simlib();

/* Set maxatr = max(maximum number of attributes per record, 4) */

maxatr = 4; /* NEVER SET maxatr TO BE SMALLER THAN 4. */

/* Schedule the first arrival. */

event_schedule(expon(mean_interarrival, STREAM_INTERARRIVAL),

EVENT_ARRIVAL);/* Schedule the bank closing. (Note need for consistency of units.) */

event_schedule(60 * length_doors_open, EVENT_CLOSE_DOORS);

/* Run the simulation while the event list is not empty. */

while (list_size[LIST_EVENT] != 0) {

/* Determine the next event. */

timing();

/* Invoke the appropriate event function. */

switch (next_event_type) {

case EVENT_ARRIVAL:

arrive();

break;

case EVENT_DEPARTURE:

depart((int) transfer[3]); /* transfer[3] is teller

number. */

break;

case EVENT_CLOSE_DOORS:

event_cancel(EVENT_ARRIVAL);

break;

}

}/* Report results for the simulation with num_tellers tellers. */

report();

}fclose(infile);

fclose(outfile);return 0;

}void arrive(void) /* Event function for arrival of a customer to the bank. */

{

int teller;/* Schedule next arrival. */

event_schedule(sim_time + expon(mean_interarrival, STREAM_INTERARRIVAL),

EVENT_ARRIVAL);/* If a teller is idle, start service on the arriving customer. */

for (teller = 1; teller <= num_tellers; ++teller) {

if (list_size[num_tellers + teller] == 0) {

/* This teller is idle, so customer has delay of zero. */

sampst(0.0, SAMPST_DELAYS);

/* Make this teller busy (attributes are irrelevant). */

list_file(FIRST, num_tellers + teller);

/* Schedule a service completion. */

transfer[3] = teller; /* Define third attribute of type-two event-

list record before event_schedule. */event_schedule(sim_time + expon(mean_service, STREAM_SERVICE),

EVENT_DEPARTURE);/* Return control to the main function. */

return;

}

}/* All tellers are busy, so find the shortest queue (leftmost shortest in

case of ties). */shortest_length = list_size[1];

shortest_queue = 1;

for (teller = 2; teller <= num_tellers; ++teller)

if (list_size[teller] < shortest_length) {

shortest_length = list_size[teller];

shortest_queue = teller;

}/* Place the customer at the end of the leftmost shortest queue. */

transfer[1] = sim_time;

list_file(LAST, shortest_queue);

}void depart(int teller) /* Departure event function. */

{

/* Check to see whether the queue for teller “teller” is empty. */if (list_size[teller] == 0)

/* The queue is empty, so make the teller idle. */

list_remove(FIRST, num_tellers + teller);

else {

/* The queue is not empty, so start service on a customer. */

list_remove(FIRST, teller);

sampst(sim_time – transfer[1], SAMPST_DELAYS);

transfer[3] = teller; /* Define before event_schedule. */

event_schedule(sim_time + expon(mean_service, STREAM_SERVICE),

EVENT_DEPARTURE);

}/* Let a customer from the end of another queue jockey to the end of this

queue, if possible. */jockey(teller);

}void jockey(int teller) /* Jockey a customer to the end of queue “teller” from

the end of another queue, if possible. */

{

int jumper, min_distance, ni, nj, other_teller, distance;/* Find the number, jumper, of the queue whose last customer will jockey to

queue or teller “teller”, if there is such a customer. */jumper = 0;

min_distance = 1000;

ni = list_size[teller] + list_size[num_tellers + teller];/* Scan all the queues from left to right. */

for (other_teller = 1; other_teller <= num_tellers; ++other_teller) {

nj = list_size[other_teller] + list_size[num_tellers + other_teller];

distance = abs(teller – other_teller);/* Check whether the customer at the end of queue other_teller qualifies

for being the jockeying choice so far. */if (other_teller != teller && nj > ni + 1 && distance < min_distance) {

/* The customer at the end of queue other_teller is our choice so

far for the jockeying customer, so remember his queue number and

its distance from the destination queue. */jumper = other_teller;

min_distance = distance;

}

}/* Check to see whether a jockeying customer was found. */

if (jumper > 0) {

/* A jockeying customer was found, so remove him from his queue. */

list_remove(LAST, jumper);

/* Check to see whether the teller of his new queue is busy. */

if (list_size[num_tellers + teller] > 0)

/* The teller of his new queue is busy, so place the customer at the

end of this queue. */list_file(LAST, teller);

else {

/* The teller of his new queue is idle, so tally the jockeying

customer’s delay, make the teller busy, and start service. */sampst(sim_time – transfer[1], SAMPST_DELAYS);

list_file(FIRST, num_tellers + teller);

transfer[3] = teller; /* Define before event_schedule. */

event_schedule(sim_time + expon(mean_service, STREAM_SERVICE),

EVENT_DEPARTURE);

}

}

}void report(void) /* Report generator function. */

{

int teller;

float avg_num_in_queue;/* Compute and write out estimates of desired measures of performance. */

avg_num_in_queue = 0.0;

for (teller = 1; teller <= num_tellers; ++teller)

avg_num_in_queue += filest(teller);

fprintf(outfile, “\n\nWith%2d tellers, average number in queue = %10.3f”,

num_tellers, avg_num_in_queue);

fprintf(outfile, “\n\nDelays in queue, in minutes:\n”);

out_sampst(outfile, SAMPST_DELAYS, SAMPST_DELAYS);

}

**simlib.c, simlib.h, simlibdefs.h** can be found here

Input Parameters : minimal number of tellers, maximal number of tellers, mean interarrival time, mean service time and length doors open (hours).

**mtbank.out** – Simulation Result

**Reference :**

Textbook : Simulation Modeling and Analysis

*Strive to be independence
*

*April 15, 2008*

*Taipei City
High Speed Network Lab*

Udin Harun