Guest User

Untitled

a guest
Jun 18th, 2018
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.52 KB | None | 0 0
  1. //******************************************************************************
  2. //* A simple M/M/1 queue simulation *
  3. //******************************************************************************
  4. //* Notes: 1. This program requires parameters for Inter Arrival time, *
  5. //** Service time as well as maximum number of customers *
  6. //*----------------------------------------------------------------------------*
  7. //* Build: gcc -o mm1 mm1.c *
  8. //*----------------------------------------------------------------------------*
  9. //* Execute: ./mm1 MAX_CUSTOMERS ARR_TIME SERV_TIME *
  10. //*----------------------------------------------------------------------------*
  11. //* Author: Anshuman Biswas *
  12. //* Email: anshuman@sce.carleton.ca *
  13. //*----------------------------------------------------------------------------*
  14. //* Version: 1.0 *
  15. //******************************************************************************
  16. //----- Include files ----------------------------------------------------------
  17. #include <stdio.h> // Needed for printf()
  18. #include <stdlib.h> // Needed for rand()
  19. #include <math.h> // Needed for log()
  20.  
  21. // #define MAX 1000000 // Modify this to change the number of requests
  22. // #define SIM_TIME 1.0e2 // Simulation time
  23.  
  24. // #define ARR_TIME 1.25 // Mean time between arrivals
  25. // #define SERV_TIME 1.00 // Mean service time
  26. #define RSEED 1234 // Modify this to change seed of the random number generator function
  27.  
  28. #define FILENAME "mm1.csv" //Change the filename here
  29.  
  30. //----- Link List -------------------------------------------------------------
  31. // This link list will store the future events
  32. typedef struct node {
  33. int callerID;
  34. char event;
  35. double time;
  36. struct node *next;
  37. } node_t;
  38.  
  39. long int MAX;
  40. double ARR_TIME,SERV_TIME;
  41.  
  42. //----- Function prototypes ----------------------------------------------------
  43. double expntl(double x); // Generate exponential RV with mean x
  44. void print_list(node_t * head); // Print the future event list
  45. int popEvent(node_t ** head); // Remove the event at the front of the list
  46. int popBuffer(FILE *f,node_t ** head,node_t ** bhead,
  47. double *busyTime,double *residenceTime,
  48. double *waitingTime,double currentTime); // Remove the waiting event at the front of the buffer
  49. void insertEvent(node_t ** head,int callerID,char event,double time); // Insert an event at the appropriate time of occurence
  50. void print_all(node_t * head,node_t * bhead); // Print both the future event list as well as the buffer
  51.  
  52.  
  53. int main( int argc, char *argv[])
  54. {
  55. int i,j,line=0,callerID=0,localCallerID,departures=0;
  56.  
  57. double prevTime = 0.0,newTime = 0.0,busyTime = 0.0,serviceTime=0.0,waitingTime = 0.0,residenceTime=0.0;
  58. node_t * fel = NULL;
  59. node_t * head = fel;
  60.  
  61. node_t * buffer = NULL;
  62. node_t * bhead = buffer;
  63.  
  64. // Check if the command line argument is correct
  65. if ( argc != 4 ) /* argc should be 4 for correct execution */
  66. {
  67. /* We print argv[0] assuming it is the program name */
  68. printf( "usage: %s MAX_CUSTOMERS INTER_ARR_TIME SERV_TIME\n", argv[0] );
  69. exit(-1);
  70. }
  71. else if( atof(argv[2]) < 0)
  72. {
  73. printf( "Inter arrival time must be greater than 0.\n" );
  74. exit(-1);
  75. }
  76. else if (atof(argv[3]) < 0 )
  77. {
  78. printf( "Service time must be greater than 0.\n" );
  79. exit(-1);
  80. }
  81. else
  82. {
  83. SERV_TIME = atof(argv[3]);
  84. ARR_TIME = atof(argv[2]);
  85. MAX = atoi(argv[1]);
  86. }
  87. // Open a file for reading
  88. FILE *f = fopen(FILENAME, "w");
  89. if (f == NULL) {
  90. printf("Error opening file!\n");
  91. exit(1);
  92. }
  93.  
  94. // Assign a seed for the random number
  95. srand(RSEED);
  96.  
  97. insertEvent(&head,++callerID,'A',prevTime + expntl(ARR_TIME));
  98. // print_all(head,bhead); // UNCOMMENT THIS TO VIEW THE FEL and the buffer
  99. while(1) {
  100. // Pickup the next event in the list
  101. switch(head->event){
  102. case 'A':
  103. prevTime = head->time;
  104. localCallerID = head->callerID;
  105. popEvent(&head);
  106. if(!line) {
  107. // Create a departure event in the FEL
  108. serviceTime = expntl(SERV_TIME);
  109. newTime = prevTime+serviceTime;
  110. busyTime += serviceTime;
  111. residenceTime += serviceTime;
  112. insertEvent(&head,localCallerID,'D',newTime);
  113. // Write the data to file
  114. fprintf(f, "%d,%lf,%lf,%lf\n",localCallerID,prevTime,0.0,serviceTime);
  115. line = 1; // Make the line busy
  116. }
  117. // Add to buffer
  118. else
  119. insertEvent(&bhead,localCallerID,'A',prevTime);
  120.  
  121. // Stop creating new arrivals after the conditions are met
  122. if(callerID < MAX) // Uncomment this to make use of the number of requests
  123. // if(prevTime < SIM_TIME) // Uncomment this to make use of the total simulation time
  124. insertEvent(&head,++callerID,'A',prevTime + expntl(ARR_TIME));
  125. // printf("Arrival Event\n"); // UNCOMMENT THIS TO VIEW THE FEL and the buffer
  126. // print_all(head,bhead); // UNCOMMENT THIS TO VIEW THE FEL and the buffer
  127. break;
  128. case 'D':
  129. departures++;
  130. prevTime = head->time;
  131. popEvent(&head);
  132. if(departures == MAX) // Uncomment this to make use of the number of requests
  133. // if(departures == callerID) // Uncomment this to make use of the total simulation time
  134. goto Result;
  135. if(bhead!=NULL)
  136. popBuffer(f,&head,&bhead,&busyTime,&residenceTime,&waitingTime,prevTime);
  137. else
  138. line=0;
  139. // printf("Departure Event\n"); // UNCOMMENT THIS TO VIEW THE FEL and the buffer
  140. // print_all(head,bhead); // UNCOMMENT THIS TO VIEW THE FEL and the buffer
  141. break;
  142. }
  143. }
  144.  
  145. Result:
  146. // CLose file for writing
  147. fclose(f);
  148. // Output results
  149. printf("**************************************STATISTICS*******************************\n");
  150. if(ARR_TIME < SERV_TIME)
  151. printf("* UNSTABLE:\tArrival rate is greater than service rate!!\n");
  152. printf("* Results from M/M/1 simulation * \n");
  153. printf("*******************************************************************************\n");
  154. printf("* INPUTS: \n");
  155. printf("* Total simulated time = %3.4f sec \n", prevTime);
  156. printf("* Mean time between arrivals = %lf sec \n", ARR_TIME);
  157. printf("* Mean service time = %lf sec \n", SERV_TIME);
  158. printf("*******************************************************************************\n");
  159. printf("* OUTPUTS: \n");
  160. printf("* Number of completions = %u cust \n", departures);
  161. printf("* Throughput rate = %lf cust/sec \n", departures/prevTime);
  162. printf("* Busy Time = %lf sec \n", busyTime);
  163. printf("* Server utilization = %lf %% \n", 100.0 * busyTime/prevTime);
  164. printf("* Mean residence time = %lf sec \n", residenceTime/departures);
  165. printf("* Mean queueing time = %lf sec \n", waitingTime/departures);
  166. printf("* Mean number in system = %lf cust \n", residenceTime/prevTime);
  167. printf("* Mean number in queue = %lf cust \n", (residenceTime-busyTime)/prevTime);
  168. printf("*******************************************************************************\n");
  169. return 0;
  170. }
  171.  
  172. //******************************************************************************
  173. //* Function: Print both the future event list as well as the buffer *
  174. //* - Input: 1) The pointer to the head of the link list *
  175. //* - 2) The pointer to the head of the buffer *
  176. //* - Output: void *
  177. //******************************************************************************
  178.  
  179. void print_all(node_t * head,node_t * bhead) {
  180. printf("*******************************************************************************\n");
  181. printf("FEL-");
  182. print_list(head);
  183. printf("***************************\n");
  184. printf("BUFFER-");
  185. print_list(bhead);
  186. printf("*******************************************************************************\n");
  187. }
  188.  
  189. //******************************************************************************
  190. //* Function to generate exponentially distributed RVs using inverse method *
  191. //* - Input: x (mean value of distribution) *
  192. //* - Output: Returns with exponential RV *
  193. //******************************************************************************
  194. double expntl(double x)
  195. {
  196. double z; // Uniform random number from 0 to 1
  197.  
  198. // Pull a uniform RV (0 < z < 1)
  199. do {
  200. z = ((double) rand() / RAND_MAX);
  201. }
  202. while ((z == 0) || (z == 1));
  203.  
  204. // return -log(1.0 - (double) random() / (RAND_MAX + 1)) / x;
  205.  
  206.  
  207. return(-x * log(z));
  208. }
  209.  
  210. //******************************************************************************
  211. //* Function: Print the future event list *
  212. //* - Input: 1) The pointer to the head of the link list *
  213. //* - Output: void *
  214. //******************************************************************************
  215. void print_list(node_t * head) {
  216. node_t * current = head;
  217. while (current != NULL) {
  218. printf("(%d,%c,%lf)", current->callerID,current->event,current->time);
  219. current = current->next;
  220. if(current != NULL)
  221. printf("|");
  222. }
  223. printf("\n");
  224. }
  225.  
  226. //******************************************************************************
  227. //* Function: Remove the event at the front of the list *
  228. //* - Input: 1) The pointer to the pointer of the head of the link list *
  229. //* - Output: int: A bool type for whether the pop was successful or not *
  230. //******************************************************************************
  231. int popEvent(node_t ** head) {
  232. int retval = -1;
  233. node_t * next_node = NULL;
  234.  
  235. if (*head == NULL) {
  236. return -1;
  237. }
  238.  
  239. next_node = (*head)->next;
  240. retval = 1;
  241. free(*head);
  242. *head = next_node;
  243. return retval;
  244. }
  245.  
  246. //******************************************************************************
  247. //* Function: Remove the waiting event at the front of the buffer *
  248. //* - Input: 1) The pointer to the file to store the statistics *
  249. //* - Input: 2) The pointer to the pointer of the head of the fel *
  250. //* - Input: 3) The pointer to the pointer of the head of the queue *
  251. //* - Input: 2) The pointer to the pointer of the head of the link list *
  252. //* - Input: 2) The pointer to the pointer of the head of the link list *
  253. //* - Input: 2) The pointer to the pointer of the head of the link list *
  254. //* - Output: void *
  255. //******************************************************************************
  256. int popBuffer(FILE *f,node_t ** head,node_t ** bhead,double *busyTime,double *residenceTime,double *waitingTime,double currentTime) {
  257. double newTime,serviceTime,wt;
  258. int retval = -1;
  259. node_t * next_node = NULL;
  260.  
  261. if (*bhead == NULL) {
  262. return -1;
  263. }
  264. // printf("Current Time - %lf\n", currentTime);
  265. next_node = (*bhead)->next;
  266. retval = 1;
  267. // Insert as a departure event
  268. serviceTime = expntl(SERV_TIME);
  269. newTime = currentTime+serviceTime;
  270. *busyTime += serviceTime;
  271. wt = (currentTime - (*bhead)->time);
  272. wt = (wt > 0)? wt : 0;
  273. *waitingTime += wt;
  274. *residenceTime += (serviceTime+wt);
  275. // Write the data to file
  276. fprintf(f, "%d,%lf,%lf,%lf\n",(*bhead)->callerID,(*bhead)->time,wt,(serviceTime+wt));
  277. insertEvent((head),(*bhead)->callerID,'D',newTime);
  278. free(*bhead);
  279. *bhead = next_node;
  280. return retval;
  281. }
  282.  
  283. //******************************************************************************
  284. //* Function: Insert an event at the appropriate time of occurence *
  285. //* - Input: 1) The pointer to the pointer of the head of the link list *
  286. //* - Input: 2) int: ID of the the caller *
  287. //* - Input: 3) char: Symbol to signify the event *
  288. //* - Input: 4) double: The time the event will occur *
  289. //* - Output: void *
  290. //******************************************************************************
  291. void insertEvent(node_t ** head,int callerID,char event,double time)
  292. {
  293. node_t * current = *head;
  294. node_t * newEvent = NULL;
  295. if(current == NULL) {
  296. newEvent=malloc(sizeof(node_t));
  297. newEvent->next = NULL;
  298. *head = newEvent;
  299. newEvent->time=time;
  300. newEvent->callerID = callerID;
  301. newEvent->event = event;
  302. }
  303. else {
  304. while(current != NULL) {
  305. // This is the case when the event needs to be inserted in after the last event
  306. if(current->time <= time && current->next == NULL) {
  307. // Create a new memory and re-assign the pointers
  308. newEvent=malloc(sizeof(node_t));
  309. newEvent->next = current->next;
  310. current->next=newEvent;
  311. newEvent->time=time;
  312. newEvent->callerID = callerID;
  313. newEvent->event = event;
  314. break;
  315. }
  316. // This is the case when the event needs to be inserted before the first event
  317. else if(current->time > time && current == *head) {
  318. // Create a new memory and re-assign the pointers
  319. newEvent=malloc(sizeof(node_t));
  320. newEvent->next = current;
  321. *head = newEvent;
  322. newEvent->time=time;
  323. newEvent->callerID = callerID;
  324. newEvent->event = event;
  325. break;
  326. }
  327. // This is the case when the event needs to be inserted in between two other events
  328. else if(current->time < time && current->next->time >= time) {
  329. // Create a new memory and re-assign the pointers
  330. newEvent=malloc(sizeof(node_t));
  331. newEvent->next = current->next;
  332. current->next=newEvent;
  333. newEvent->time=time;
  334. newEvent->callerID = callerID;
  335. newEvent->event = event;
  336. break;
  337. }
  338.  
  339. // Proceed to the next event
  340. current = current->next;
  341. }
  342. }
  343. }
Add Comment
Please, Sign In to add comment