Application of Queues :  Airport simulation

 

Objectives of this lecture

q       Learn how queues may be applied in real life applications by simulating an airport traffic control program.

 

Problem Specification:

Write a program to simulate airport traffic control for a small but busy airport assuming the following specifications.

q       There is only one runway for both landing and take off.

q       In each unit time, only one plane can land or take off but not both.

q       Planes arrive and take off at random time, so that at any given unit, the runway may be idle or a plane may be landing or taking off.

q       Number of planes waiting to take off or land should not exceed a certain fixed limit.

q       Landing planes should have high priority than Taking-off plane.

q       After running for some period, the program should print statistics such as: number of planes processed, landed, and took off, refused; average landing and take-off waiting times, and average run-way idle time.  

 

Algorithm

Create two queues, landing and takeoff

Initialize statistics counters to zero

Loop for time unit from 1 to some fixed number

     Loop from 1 to some random number of landing planes

     If landing queue is not full, add plane to the queue else

       refuse landing and increment number of refused.

     Loop from 1 to some random number of taking off planes

     If takeoff queue is not full, add plane to the queue else

        refuse landing and increment number of refused.

If landing queue is not empty process next landing plane and

   increment count of planes landed

Else if takeoff queue is not empty, process next plane and

   increment count of take off planes

Else increment count of run-way idle time.

Print the statistics.

 

Implementation.

We note that since the number of planes arriving and taking off must not be more than a fixed number, it is better to use the array implementation of queue.

 

In the QUEUE.H file, we need to add the following:

#define MAXQUEUE    5   /* use a small value for testing    */

 

typedef struct plane {

    int id;             /* identification number of airplane*/

    int tm;             /* time of arrival in queue         */

} Plane;

 

typedef Plane QueueEntry;

 

typedef struct queue {

    int count;          /* number of airplanes in the queue */

    int front;          /* front of the queue               */

    int rear;           /* rear of the queue                */

    QueueEntry entry[MAXQUEUE];

} Queue;

 

//File Name:  Airport.C

/* simulation of an airport: Prints airport traffic statistics for a given

period of time:                               

Pre:  The required time period and expected arrival and departure rates

are read from the user.

Post: The traffic statistics has been printed

Uses: Queue routines. Start, PoissonRandom, NewPlane, Land, Fly,

Refuse, Idle, Conclude

*/ 

 

#include “common.h”

#include “queue.h”

 

typedef enum action { ARRIVE, DEPART } Action;

 

int main(void)

{  Queue landing, takeoff;

    Queue *pl = &landing;

    Queue *pt = &takeoff;

    Plane plane;

 

    int curtime; /* current time; one unit = time for take off or landing */

    int endtime;    /* total number of time units to run    */

    double expectarrive;/* number of planes arriving in one unit    */

    double expectdepart;/* number of planes newly ready to take off */

    int i;          /* loop control variable                */

    int idletime;   /* number of units when runway is idle  */

    int landwait;   /* total waiting time for planes landed */

    int nland;      /* number of planes landed              */

    int nplanes;    /* number of planes processed so far    */

    int nrefuse;    /* number of planes refused use of airport  */

    int ntakeoff;   /* number of planes taken off           */

    int pri;        /* pseudo-random integer                */

    int takeoffwait;/* total waiting time for take off      */

    CreateQueue(pl);

    CreateQueue(pt);

    nplanes = nland = ntakeoff = nrefuse = 0;

    landwait = takeoffwait = idletime = 0;

    Start(&endtime, &expectarrive, &expectdepart);

    for (curtime = 1; curtime <= endtime; curtime++) {

        pri = PoissonRandom(expectarrive);

        for (i = 1; i <= pri; i++) {/* Add to landing queue.    */

            NewPlane(&plane, &nplanes, curtime, ARRIVE);

            if (QueueFull(pl))

                Refuse(plane, &nrefuse, ARRIVE);

            else

                Append(plane, pl);

        }

 

        pri = PoissonRandom(expectdepart);

        for (i = 1; i <= pri; i++) {/* Add to takeoff queue.    */

            NewPlane(&plane, &nplanes, curtime, DEPART);

            if (QueueFull(pt))

                Refuse(plane, &nrefuse, DEPART);

            else

                Append(plane, pt);

        }

 

        if (!QueueEmpty(pl)) {      /* Bring plane to land. */

            Serve(&plane, pl);

            Land(plane, curtime, &nland, &landwait);

        } else if (!QueueEmpty(pt)) {   /* Allow plane to take off. */

            Serve(&plane, pt);

            Fly(plane, curtime, &ntakeoff, &takeoffwait);

        } else

            Idle(curtime, &idletime);

    }

 

    Conclude(nplanes, nland, ntakeoff, nrefuse, landwait,

            takeoffwait, idletime, endtime, pt, pl);

    return 0;

}

 

// Related functions:

 

/* Start: print messages and initialize the parameters.

Pre:  None.

Post: Asks user for responses and initializes all variables specified as

 parameters.

Uses: UserSaysYes.

*/

void Start(int *endtime, double *expectarrive, double *expectdepart)

{    Boolean ok;

 

    printf("This program simulates an airport with only one runway.\n"

            "One plane can land or depart in each unit of time.\n"

            "Up to %d planes can be waiting to land or take off "

            "at any time.\n", MAXQUEUE);

 

    printf("How many units of time will the simulation run? ");

    scanf("%d", endtime);

 

    Randomize();    /* Initialize random number generation. */

    do {

        printf("Expected number of arrivals per unit time (real number)? ");

        scanf("%lf", expectarrive);

        printf("Expected number of departures per unit time? ");

        scanf("%lf", expectdepart);

 

        if (*expectarrive < 0.0 || *expectdepart < 0.0) {

            printf("These numbers must be nonnegative.\n");

            ok = FALSE;

        } else if (*expectarrive + *expectdepart > 1.0) {

            printf("The airport will become saturated. "

                   "Read new numbers? ");

            ok = !UserSaysYes(); /* If user says yes, repeat loop. */

        } else

            ok = TRUE;

    } while (ok == FALSE);

}

 

 /* NewPlane: make a new record for a plane, update nplanes.

Pre:  None.

Post: Makes a new structure for a plane and updates nplanes.

 */

void NewPlane(Plane *p, int *nplanes, int curtime, Action kind)

{

    (*nplanes)++;

    p->id = *nplanes;

    p->tm = curtime;

    switch(kind) {

    case ARRIVE:

        printf("      Plane %3d ready to land.\n", *nplanes);

        break;

    case DEPART:

        printf("      Plane %3d ready to take off.\n", *nplanes);

        break;

    }

}

 

 /* Refuse: processes a plane when the queue is full.

Pre:  None.

Post: Processes a plane wanting to use runway, but the queue is full.

 */

void Refuse(Plane p, int *nrefuse, Action kind)

{

    switch(kind) {

    case ARRIVE:

        printf("      Plane %3d directed to another airport.\n", p.id);

        break;

    case DEPART:

        printf("      Plane %3d told to try later.\n", p.id);

        break;

    }

    (*nrefuse)++;

}

 

 /* Land: process a plane that is actually landing.

Pre:  None.

Post: Processes a plane p that is actually landing.

 */

void Land(Plane p, int curtime, int *nland, int *landwait)

{    int wait;

 

    wait = curtime - p.tm;

    printf("%3d : Plane %3d landed; in queue %d units.\n",

            curtime, p.id, wait);

    (*nland)++;

    *landwait += wait;

}

 

 /* Fly: process a plane that is actually taking off.

Pre:  None.

Post: Processes a plane p that is actually taking off.

 */

void Fly(Plane p, int curtime, int *ntakeoff, int *takeoffwait)

{    int wait;

 

    wait = curtime - p.tm;

    printf("%3d : Plane %3d took off; in queue %d units.\n",

            curtime, p.id, wait);

    (*ntakeoff)++;

    *takeoffwait += wait;

}

 

 /* Idle:  updates variables for idle runway.

Pre:  None.

Post: Updates variables for a time unit when the runway is idle.

 */

void Idle(int curtime, int *idletime)

{

    printf("%3d : Runway is idle.\n", curtime);

    (*idletime)++;

}

 

 /* Conclude: write out statistics and conclude simulation.

Pre:  None.

Post: Writes out all the statistics and concludes the simulation.

 */

void Conclude(int nplanes, int nland, int ntakeoff,

              int nrefuse, int landwait, int takeoffwait,

              int idletime, int endtime,

              Queue *pt, Queue *pl)

{

    printf("Simulation has concluded after %d units.\n", endtime);

    printf("Total number of planes processed:    %3d\n", nplanes);

    printf("   Number of planes landed:          %3d\n", nland);

    printf("   Number of planes taken off:       %3d\n", ntakeoff);

    printf("   Number of planes refused use:     %3d\n", nrefuse);

    printf("   Number left ready to land:        %3d\n", QueueSize(pl));

    printf("   Number left ready to take off:    %3d\n", QueueSize(pt));

    if (endtime > 0)

        printf("   Percentage of time runway idle:   %6.2f\n",

            ((double) idletime / endtime) * 100.0);

    if (nland > 0)

        printf("   Average wait time to land:        %6.2f\n",

            (double) landwait / nland);

    if (ntakeoff > 0)

        printf("   Average wait time to take off:    %6.2f\n",

            (double) takeoffwait / ntakeoff);

}

 

 /* Randomize: set starting point for pseudorandom integers. */

void Randomize(void)

{    srand((unsigned int) (time(NULL) % 10000));

}

 

 /* PoissonRandom: generate a pseudorandom integer according

to the Poisson distribution.

Pre:  None.

Post: Generates a random nonnegative integer according to a Poisson

    distribution with the expected value given as the parameter.

Uses: exp, rand.

 */

int PoissonRandom(double expectedvalue)

{   int n = 0;          /* counter of iterations                    */

    double limit;       /* e^-v, where v is the expected value    */

    double x;           /* pseudorandom number                      */

 

    limit = exp(-expectedvalue);

    x = rand() / (double) INT_MAX;

    while (x > limit) {

        n++;

        x *= rand() / (double) INT_MAX;

    }

    return n;

}