//====================================================== file = mm1_csim.c =====
//=  A CSIM simulation of an M/M/1 queueing system                             =
//==============================================================================
//=  Notes: 1) Values for lambda and mu are set in the main program            =
//=         2) Value for SIM_TIME is set in #define                            =
//=         3) Computes M/M/1 theoretical results for comparison               =
//=----------------------------------------------------------------------------=
//= Example execution:                                                         =
//=                                                                            =
//=   *** BEGIN SIMULATION ***                                                 =
//=   =============================================================            =
//=   ==     *** CSIM M/M/1 queueing system simulation ***       ==            =
//=   =============================================================            =
//=   = Lambda   = 1.000000 cust/sec                                           =
//=   = Mu       = 3.000000 cust/sec                                           =
//=   =============================================================            =
//=   = Total CPU time     = 2.386000 sec                                      =
//=   = Total sim time     = 1000000.000000 sec                                =
//=   = Total completions  = 1001182 cust                                      =
//=   =------------------------------------------------------------            =
//=   = >>> Simulation results                                    -            =
//=   =------------------------------------------------------------            =
//=   = Utilization        = 33.359231 %                                       =
//=   = Mean num in system = 0.500356 cust                                     =
//=   = Mean response time = 0.499765 sec                                      =
//=   = Mean service time  = 0.333198 sec                                      =
//=   = Mean throughput    = 1.001182 cust/sec                                 =
//=   =------------------------------------------------------------            =
//=   = >>> Theoretical results from M/M/1 formulas               -            =
//=   =------------------------------------------------------------            =
//=   = Utilization        = 33.333333 %                                       =
//=   = Mean num in system = 0.500000 cust                                     =
//=   = Mean response time = 0.500000 sec                                      =
//=   = Mean service time  = 0.333333 sec                                      =
//=   = Mean throughput    = 1.000000 cust/sec                                 =
//=   =============================================================            =
//=   *** END SIMULATION ***                                                   =
//=----------------------------------------------------------------------------=
//=  Build: standard CSIM build                                                =
//=----------------------------------------------------------------------------=
//=  Execute: mm1_csim                                                         =
//=----------------------------------------------------------------------------=
//=  Author: Ken Christensen                                                   =
//=          University of South Florida                                       =
//=          WWW: http://www.csee.usf.edu/~christen                            =
//=          Email: christen@csee.usf.edu                                      =
//=----------------------------------------------------------------------------=
//=  History: KJC (02/27/97) - Genesis                                         =
//=           KJC (01/27/04) - Added documentation and localized some vars     =
//=           KJC (10/24/14) - Minor clean-up of documentation                 =
//==============================================================================
//----- Includes ---------------------------------------------------------------
#include <stdio.h>      // Needed for printf()
#include "csim.h"       // Needed for CSIM stuff

//----- Defines ----------------------------------------------------------------
#define SIM_TIME 1.0e6  // Total simulation time in seconds

//----- Globals ----------------------------------------------------------------
FACILITY Server;        // Declaration of CSIM Server facility

//----- Prototypes -------------------------------------------------------------
void generate(double lambda, double mu);  // Customer generator
void queue1(double service_time);         // Single server queue

//==============================================================================
//==  Main program                                                            ==
//==============================================================================
void sim(void)
{
  double   lambda;      // Mean arrival rate (cust/sec)
  double   mu;          // Mean service rate (cust/sec)
  double   rho;         // Theoretical utilization

  // Create the simulation
  create("sim");

  // CSIM initializations
  Server = facility("Server");

  // Parameter initializations
  lambda = 1.0;
  mu = 3.0;

  // Output begin-of-simulation banner
  printf("*** BEGIN SIMULATION *** \n");

  // Initiate generate function and hold for SIM_TIME
  generate(lambda, mu);
  hold(SIM_TIME);

  // Compute theoretical utilization
  rho = lambda / mu;

  // Output results
  printf("============================================================= \n");
  printf("==     *** CSIM M/M/1 queueing system simulation ***       == \n");
  printf("============================================================= \n");
  printf("= Lambda   = %f cust/sec   \n", lambda);
  printf("= Mu       = %f cust/sec   \n", mu);
  printf("============================================================= \n");
  printf("= Total CPU time     = %f sec      \n", cputime());
  printf("= Total sim time     = %f sec      \n", clock);
  printf("= Total completions  = %d cust     \n", completions(Server));
  printf("=------------------------------------------------------------ \n");
  printf("= >>> Simulation results                                    - \n");
  printf("=------------------------------------------------------------ \n");
  printf("= Utilization        = %f %%       \n", 100.0 * util(Server));
  printf("= Mean num in system = %f cust     \n", qlen(Server));
  printf("= Mean response time = %f sec      \n", resp(Server));
  printf("= Mean service time  = %f sec      \n", serv(Server));
  printf("= Mean throughput    = %f cust/sec \n", tput(Server));
  printf("=------------------------------------------------------------ \n");
  printf("= >>> Theoretical results from M/M/1 formulas               - \n");
  printf("=------------------------------------------------------------ \n");
  printf("= Utilization        = %f %%       \n", 100.0 * rho);
  printf("= Mean num in system = %f cust     \n", rho / (1.0 - rho));
  printf("= Mean response time = %f sec      \n", (1.0 / mu) / (1.0 - rho));
  printf("= Mean service time  = %f sec      \n", (1.0 / mu));
  printf("= Mean throughput    = %f cust/sec \n", lambda);
  printf("============================================================= \n");

  // Output end-of-simulation banner
  printf("*** END SIMULATION *** \n");
}

//==============================================================================
//==  Process to generate Poisson customers                                   ==
//==============================================================================
void generate(double lambda, double mu)
{
  double   interarrival_time;    // Interarrival time to next send
  double   service_time;         // Service time for this customer

  create("generate");

  // Loop forever to create customers
  while(1)
  {
    // Pull an exponentially distributed interarrival time and hold for it
    interarrival_time = exponential(1.0 / lambda);
    hold(interarrival_time);

    // Pull an exponential service time and then send the customer to the queue
    service_time = exponential(1.0 / mu);
    queue1(service_time);
  }
}

//==============================================================================
//==  Process for single server queue                                         ==
//==============================================================================
void queue1(double service_time)
{
  create("queue1");

  // Reserve, hold, and release server
  reserve(Server);
  hold(service_time);
  release(Server);
}
