/* Simulation of the COVID Barber Shop for CPSC 641 */ /* */ /* Written by Carey Williamson, University of Calgary */ /* */ /* Usage: cc -o barber barber.c -lm */ /* ./barber */ #include #include #include /* use man 3 log for the math functions */ #define HAIRCUTS 1000000 /* Number of haircuts to simulate */ #define LAMBDA 6.0 /* Arrival rate of new customers */ #define FARUZ_RATE 5.0 /* Service rate of Faruz */ #define GEMAL_RATE 3.0 /* Service rate of Gemal */ #define END_OF_TIME 999999.9 /* Time far in the future */ #define IDLE 0 #define FARUZ 1 #define GEMAL 2 #define BOTH 3 #define MAX_QUEUE 3 /* Number of chairs in waiting room */ /* Debugging output */ /* #define DEBUG 1 */ /***********************************************************************/ /* RANDOM NUMBER GENERATION STUFF */ /***********************************************************************/ /* Parameters for random number generation. */ #define MAX_INT 2147483647 /* Maximum positive integer 2^31 - 1 */ /* Generate a random floating point value uniformly distributed in [0,1] */ float Uniform01() { float randnum; /* get a random positive integer from random() */ randnum = (float) 1.0 * random(); /* divide by max int to get something in 0..1 */ randnum = (float) randnum / (1.0 * MAX_INT); return( randnum ); } /* Generate a random floating point number from an exponential */ /* distribution with mean mu. */ float Exponential(mu) float mu; { float randnum, ans; randnum = Uniform01(); ans = -(mu) * log(randnum); return( ans ); } /***********************************************************************/ /* MAIN PROGRAM */ /***********************************************************************/ int main() { int arrivals, departures, active, qsize, state, who, lost; float now, nextarrival, nextdeparture, fdone, gdone, rand; int fcuts, gcuts; /* Initialization */ state = IDLE; qsize = 0; active = 0; arrivals = 0; departures = 0; lost = 0; fcuts = 0; gcuts = 0; now = 0.0; fdone = END_OF_TIME; gdone = END_OF_TIME; nextdeparture = END_OF_TIME; nextarrival = now + Exponential(1.0 / LAMBDA); while( departures < HAIRCUTS ) { /* determine next event */ if( nextarrival < nextdeparture ) { #ifdef DEBUG printf("Customer arrival at time %8.6f\n", nextarrival); #endif now = nextarrival; arrivals++; active++; if( state == IDLE ) { rand = Uniform01(); /* #define MM1K 1 */ #ifdef MM1K #define FARUZ_RATE 8.0 /* Service rate of Faruz */ #define GEMAL_RATE 0.0 /* Service rate of Gemal */ if( rand < 1.0 ) #else if( rand < 0.5 ) #endif { who = FARUZ; state = FARUZ; #ifdef DEBUG printf("State is now FARUZ\n"); #endif fdone = now + Exponential(1.0/FARUZ_RATE); #ifdef DEBUG printf("Faruz cutting hair until %8.6f\n", fdone); #endif nextdeparture = fdone; } else { who = GEMAL; state = GEMAL; #ifdef DEBUG printf("State is now GEMAL\n"); #endif gdone = now + Exponential(1.0/GEMAL_RATE); #ifdef DEBUG printf("Gemal cutting hair until %8.6f\n", gdone); #endif nextdeparture = gdone; } } else if( state == FARUZ ) { state = BOTH; gdone = now + Exponential(1.0/GEMAL_RATE); #ifdef DEBUG printf("State is now BOTH\n"); #endif #ifdef DEBUG printf("Gemal also cutting hair until %8.6f\n", gdone); #endif if( gdone < nextdeparture ) { nextdeparture = gdone; who = GEMAL; } } else if( state == GEMAL ) { state = BOTH; #ifdef DEBUG printf("State is now BOTH\n"); #endif fdone = now + Exponential(1.0/FARUZ_RATE); #ifdef DEBUG printf("Faruz also cutting hair until %8.6f\n", fdone); #endif if( fdone < nextdeparture ) { nextdeparture = fdone; who = FARUZ; } } else if( state == BOTH ) { if( qsize < MAX_QUEUE ) { qsize++; #ifdef DEBUG printf("Waiting room now has %d customers!\n", qsize); #endif } else { #ifdef DEBUG printf("Waiting room overflow! You have lost a customer!!! :-(\n"); #endif lost++; active--; } } nextarrival = now + Exponential(1.0 / LAMBDA); } else { #ifdef DEBUG printf("Next event is departure at time %8.6f\n", nextdeparture); #endif now = nextdeparture; departures++; active--; if( who == FARUZ ) { fcuts++; if( qsize > 0 ) { qsize--; #ifdef DEBUG printf("Waiting room now has %d customers\n", qsize); #endif nextdeparture = gdone; who = GEMAL; fdone = now + Exponential(1.0/FARUZ_RATE); #ifdef DEBUG printf("Faruz resumes cutting hair until %8.6f\n", fdone); #endif if( fdone < nextdeparture ) { nextdeparture = fdone; who = FARUZ; } } else if( state == FARUZ ) { state = IDLE; fdone = END_OF_TIME; nextdeparture = END_OF_TIME; #ifdef DEBUG printf("State is now IDLE\n"); #endif } else if( state == BOTH ) { state = GEMAL; who = GEMAL; #ifdef DEBUG printf("State is now GEMAL\n"); #endif nextdeparture = gdone; } } else { gcuts++; if( qsize > 0 ) { qsize--; #ifdef DEBUG printf("Waiting room now has %d customers\n", qsize); #endif nextdeparture = fdone; who = FARUZ; gdone = now + Exponential(1.0/GEMAL_RATE); #ifdef DEBUG printf("Gemal resumes cutting hair until %8.6f\n", gdone); #endif if( gdone < nextdeparture ) { nextdeparture = gdone; who = GEMAL; } } else if( state == GEMAL ) { state = IDLE; gdone = END_OF_TIME; nextdeparture = END_OF_TIME; #ifdef DEBUG printf("State is now IDLE\n"); #endif } else if( state == BOTH ) { state = FARUZ; who = FARUZ; nextdeparture = fdone; #ifdef DEBUG printf("State is now FARUZ\n"); #endif } } } } printf("\n"); printf("COVID Barber Shop: LAMBDA %3.2f FARUZ %3.2f GEMAL %3.2f MAX_QUEUE %d\n", LAMBDA, FARUZ_RATE, GEMAL_RATE, MAX_QUEUE); printf("Target number of haircuts: %d\n", HAIRCUTS); printf("Faruz: %d Gemal: %d\n", fcuts, gcuts); printf("Time: %8.6f Arrivals: %d Departures: %d In system: %d\n", now, arrivals, departures, active); printf("Lost: %d (%5.2f%%)\n", lost, 100.0*lost/arrivals); }