/** * Written by Rajpreet Gill * a computer simulation program (in C++) that models (i.e., simulate) * the channel access protocol used in a Bozon colony, and determines * the average channel performance. */ //***Imports***// #include #include #include #include #include #include #include using namespace std; /* Constants */ #define M 5 /* Number of bozons */ #define S 100.0 /* Mean sleep duration */ #define Y 10.0 /* Mean yodel duration */ /* Simulation parameters */ // Max positive integer is 2^31 - 1 #define WARM_UP 0.0 #define END_TIME 1000000.0 /* Bozon states */ #define SLEEPING 0 #define YODELING 1 /*Yodel duration model */ #define EXPONENTIAL 1 /* #define CONSTANT 1 */ /* Debugging flags */ /* #define DEBUG 1 */ /* #define DEBUG2 1*/ /* Parameters for random number generation. */ #define MAX_INT 2147483647.0 /* Maximum positive integer 2^31 - 1 */ //double log(); int attemptedYodels = 0; int perfectAttemptedYodels = 0; //A "perfect yodel" is one that was melodious from start to finish, without any interruption by other Bozons. double silentTime = 0.0; //needed for average percentage of the time that the channel is silent (i.e., not very interesting to tourists) double melodiousTime = 0.0; //the melodious (i.e., very interesting to tourists) double screechyTime = 0.0; //the screechy (i.e., intolerable to tourists) double perfectYodelTime = 0; double currentTime = 0; //Please note the following code has been adapted from Dr. Carey's demostration code and course TA's code: //https://d2l.ucalgary.ca/d2l/le/content/426495/viewContent/5103557/View //https://d2l.ucalgary.ca/d2l/le/content/426495/viewContent/5263221/View /* Generate a random floating point number uniformly distributed in [0,1] */ double Uniform01() { double randnum; /*get a random positive integer from random() */ randnum = (double) 1.0 * random(); /* divide by max int to get something in the range 0.0 to 1.0 */ randnum = randnum / (1.0 * MAX_INT); return(randnum); } /* Generate a random floating point number from an exponential */ /* distribution with mean mu. */ double Exponential(double mu) { double randnum, ans; randnum = Uniform01(); ans = -(mu) * log(randnum); return(ans); } struct Bozon{ bool bozonYodelling = false; // a variable that stores if the bozon is yodelling or not bool bozonPerfectYodelling; //Determines if the yodel of the bozon is perfect or not // initially the bozon is sleeping so we pass S initially double nextBozonAction = Exponential(S); //this tells us the time of the next action of the bozon --duration double currentBozonTime; //this shows the current time of the bozon's yodel }; int main() { double yodellersNextEvent = 0; int totalNumberOfyodelers = 0; srand(time(NULL)); Bozon bozons[M]; bool standard = false; bool bonus = true; //*********start simulation***********// if(standard == true) { for(;;) { if( currentTime >= END_TIME) { break; } // total number of yodellers totalNumberOfyodelers = 0; // assuming that there is no next event and that the next event is just the end time yodellersNextEvent = END_TIME; //go through for loop to see which bozons need their states switched, // if their bozon action timing is less than the current time, need to switch states for( int i = 0; i < M; i++) { //change the state of the bozons: // sleep->yodel // yodel->sleep // if the current time is greater or equal to the bozon's next action time, // this means that the time is up for the current bozon state and the bozon's state // has to be changed if(currentTime >= bozons[i].nextBozonAction) { double bozonDuration = S; //yodel activity duration // switch the bozon state if(bozons[i].bozonYodelling == true) { bozons[i].bozonYodelling = !bozons[i].bozonYodelling; } else if(bozons[i].bozonYodelling == false) { bozons[i].bozonYodelling = !bozons[i].bozonYodelling; } //bozon experienced a perfect yodel since it did not have its state switched to false for // bozonperfectyodelling except it is true hence it did not get bothered by other bozons if(bozons[i].bozonPerfectYodelling == true) { perfectAttemptedYodels++; bozons[i].bozonPerfectYodelling = false; double p = currentTime - bozons[i].currentBozonTime; perfectYodelTime = perfectYodelTime + p; } // bozon is performing yodel action else if(bozons[i].bozonYodelling == true) { attemptedYodels++; // increment number of attempted yodels bozons[i].currentBozonTime = currentTime; //set the bozon's current yodel time to current time of simulation bozons[i].bozonPerfectYodelling = true; //duration that the bozon yodels for bozonDuration = Y; //mean yodel duration since bozon is yodelling // so bozon yodels for Y amount of time } //bozon's next bozon activity action time is determined by the exponential function + the current time bozons[i].nextBozonAction = Exponential(bozonDuration) + currentTime; } //increment the number of total number of yodellers // if the bozon is yodelling if(bozons[i].bozonYodelling == true) { totalNumberOfyodelers++; } //if the next event time for the bozon is less than the set yodellers next event time, //need to the the yodellers next event this next bozon action if(bozons[i].nextBozonAction < yodellersNextEvent) { // yodellers next event equals to the next set action of // the bozon yodellersNextEvent = bozons[i].nextBozonAction; } } // if the total number of the yodellers is equal to 0, we know it is // silent time if(totalNumberOfyodelers == 0) { // it'll be silent till the yodeller has a next event double h = yodellersNextEvent - currentTime; silentTime = silentTime + h; } //if the total number of the yodellers is equal to 2 or is greater than 2, then there //is screeching else if(totalNumberOfyodelers >= 2) { for( int i = 0; i < M; i++) { //go through each bozon, if the bozon was having a perfect yodel time, //need to end this perfect time since screeching is going hence no perfect //yodel can be going on, so record the perfect yodel time up till the current time - //the time the bozon started yodelling if(bozons[i].bozonPerfectYodelling == true) { bozons[i].bozonPerfectYodelling = false; // set the bozon's yodel to false since it // was interuppted by other yodels (screeching) double g = currentTime - bozons[i].currentBozonTime; perfectYodelTime = perfectYodelTime + g; } else{ continue; } } double t = yodellersNextEvent - currentTime; screechyTime += t; } // if the number of yodellers is not greater or equal to 2 and is not 0, // hence it will be equal to 1, hence this means that there will be melodiousTime else { double y = yodellersNextEvent - currentTime; melodiousTime += y; } //Update the current time currentTime = yodellersNextEvent; } } else if(bonus == true) { for(;;) { if( currentTime >= END_TIME) { break; } // total number of yodellers totalNumberOfyodelers = 0; // assuming that there is no next event and that the next event is just the end time yodellersNextEvent = END_TIME; //go through for loop to see which bozons need their states switched, // if their bozon action timing is less than the current time, need to switch states for( int i = 0; i < M; i++) { //change the state of the bozons: // sleep->yodel // yodel->sleep // if the current time is greater or equal to the bozon's next action time, // this means that the time is up for the current bozon state and the bozon's state // has to be changed if(currentTime >= bozons[i].nextBozonAction) { double bozonDuration = S; //yodel activity duration // switch the bozon state if(bozons[i].bozonYodelling == true) { bozons[i].bozonYodelling = !bozons[i].bozonYodelling; } else if(bozons[i].bozonYodelling == false) { bozons[i].bozonYodelling = !bozons[i].bozonYodelling; } //bozon experienced a perfect yodel since it did not have its state switched to false for // bozonperfectyodelling except it is true hence it did not get bothered by other bozons if(bozons[i].bozonPerfectYodelling == true) { perfectAttemptedYodels++; bozons[i].bozonPerfectYodelling = false; double e = currentTime - bozons[i].currentBozonTime; perfectYodelTime = perfectYodelTime + e; } // bozon is performing yodel action else if(bozons[i].bozonYodelling == true) { attemptedYodels++; // increment number of attempted yodels bozons[i].currentBozonTime = currentTime; //set the bozon's current yodel time to current time of simulation bozons[i].bozonPerfectYodelling = true; //duration that the bozon yodels for bozonDuration = Y; //mean yodel duration since bozon is yodelling // so bozon yodels for Y amount of time } //bozon's next bozon activity action time is determined by the exponential function + the current time if(bozons[i].bozonYodelling == true) { bozons[i].nextBozonAction = 10 + currentTime; } else{ bozons[i].nextBozonAction = Exponential(bozonDuration) + currentTime; } } //increment the number of total number of yodellers // if the bozon is yodelling if(bozons[i].bozonYodelling == true) { totalNumberOfyodelers++; } //if the next event time for the bozon is less than the set yodellers next event time, //need to the the yodellers next event this next bozon action if(bozons[i].nextBozonAction < yodellersNextEvent) { // yodellers next event equals to the next set action of // the bozon yodellersNextEvent = bozons[i].nextBozonAction; } } // if the total number of the yodellers is equal to 0, we know it is // silent time if(totalNumberOfyodelers == 0) { // it'll be silent till the yodeller has a next event double x = yodellersNextEvent - currentTime; silentTime = silentTime + x; } //if the total number of the yodellers is equal to 2 or is greater than 2, then there //is screeching else if(totalNumberOfyodelers >= 2) { for( int i = 0; i < M; i++) { //go through each bozon, if the bozon was having a perfect yodel time, //need to end this perfect time since screeching is going hence no perfect //yodel can be going on, so record the perfect yodel time up till the current time - //the time the bozon started yodelling if(bozons[i].bozonPerfectYodelling == true) { bozons[i].bozonPerfectYodelling = false; // set the bozon's yodel to false since it // was interuppted by other yodels (screeching) double result = currentTime - (bozons[i].currentBozonTime); perfectYodelTime = perfectYodelTime + result; } else{ continue; } } double y = yodellersNextEvent - currentTime; screechyTime += y; } // if the number of yodellers is not greater or equal to 2 and is not 0, // hence it will be equal to 1, hence this means that there will be melodiousTime else { double w = yodellersNextEvent - currentTime; melodiousTime += w; } //Update the current time currentTime = yodellersNextEvent; } } //*********end simulation***********// std::cout<< "M = " << M << ", S = " << S << ", Y = " << Y << std::endl; std::cout<< "Total time observing channel: " << END_TIME << std::endl; std::cout<< " Idle time on the channel: " << silentTime << " " << 100*(silentTime/END_TIME) << "%" << std::endl; std::cout<< " Melodious time on channel: " << melodiousTime << " " << 100*(melodiousTime/END_TIME) << "%" << std::endl; std::cout<< " Screech time on the channel: " << screechyTime << " " << 100*(screechyTime/END_TIME) << "%" << std::endl; std::cout<< std::endl; std::cout<< " Attempted yodels: " << attemptedYodels << std::endl; std::cout<< " Perfect yodels: " << perfectAttemptedYodels <