Ejemplo n.º 1
0
CUSTOMER * add_customer(CUSTOMER * left_node, int id, char n[])
{
    CUSTOMER * new_node = init_customer(id, n);
    //init new node and connect left node to it
    insert_node(left_node, new_node);
    return new_node;
}
void mm_one_queue_simulator_for_batch_means(long nr_customer, double average_interarrival_time, double average_service_time, long *next_seed_interarrival, long *next_seed_service, long nr_batch, long batch_size, long initial_bias, double correlation_bound, double half_alpha, double eps_relative, struct batch_means_output *result) {
  struct event *event_list = NULL;
  struct queue system_queue;
  enum server_state server_state = IDLE;
  double system_clock = 0.0;
  struct event *event;

  enum event_type event_type;
  int customer_number = 0;
  double clock_time;
  double arrival_time;
  double interarrival_time;
  double departure_time;
  double service_time;

  struct customer *customer;

  double lamda_interarrival_rate = 1.0 / average_interarrival_time; /* interarrival rate: lamda = 1 / average_time */
  double mu_service_rate = 1.0 / average_service_time; /* service_rate: mu = 1 / arverage_service_time */

  double total_customer_in_system_time = 0.0; 

  /* for batch means */
  double *batch_mean;
  batch_mean = malloc(nr_batch * sizeof(double));
  memset(batch_mean, 0, nr_batch * sizeof(double));
  double *batch_sum;
  batch_sum = malloc(nr_batch * sizeof(double));
  memset(batch_sum, 0, nr_batch * sizeof(double));

  double lag_1_corr;
  double t; /* student t distribution */
  double dev;
  double avg;
  double ci_hw;
  double ci_hb;
  long batch_index;
  int i;

  /* initial system */
  init_queue(&system_queue);

  /* step 0: initial first event and add into event list */
#ifdef DEBUG
  printf("Info: simulation starts.\n");
#endif
  if (customer_number < nr_customer) {
    event_type = ARRIVAL;
    clock_time = 1.0;
    customer = init_customer(customer_number);
    customer->arrival_time = clock_time;
    customer_number++;
    add_event(&event_list, event_type, clock_time, (void *) customer);
  }
  /* step 1: pop event from event list */
  event = get_event(event_list);
  while (event) {
    /* step 2: addvance clock */
    system_clock = event->clock_time;
    pop_event(&event_list);
    /* get customer */
    customer = (struct customer *) event->content;
    event->content = NULL;
    switch (event->event_type) {
      case ARRIVAL:
#ifdef DEBUG
        /* print info */
        printf("Info: [time: %12f] [customer: %8d] event: ARRIVAL\n", system_clock, customer->no);
#endif
        /* generate service time */
        service_time = exponential_random_generator(mu_service_rate, next_seed_service);
        add_service_time_to_customer(customer, service_time);
        /* step 3: update state */
        if (server_state == IDLE) {
          server_state = BUSY;
          /* set service time and departure time */
          service_time = customer->service_time;
          departure_time = system_clock + service_time;
          event_type = DEPARTURE;
          customer->departure_time = departure_time;
          add_event(&event_list, event_type, departure_time, (void *) customer);
        } else if (server_state == BUSY) {
          /* add customer into queue */
          enqueue(&system_queue, (void *) customer);
        }
        /* step 4: generate future event into event list */
        /* if customer_number < nr_customer, generate next arrival event */
        if (customer_number < nr_customer) {
          interarrival_time = exponential_random_generator(lamda_interarrival_rate, next_seed_interarrival);
          arrival_time = system_clock + interarrival_time;
          event_type = ARRIVAL;
          customer = init_customer(customer_number);
          customer->arrival_time = arrival_time;
          customer_number++;
          add_event(&event_list, event_type, arrival_time, (void *) customer);
        }
     
        break;
      case DEPARTURE:
#ifdef DEBUG
        /* print info */
        printf("Info: [time: %12f] --------------------------------------- [customer: %8d] event: DEPARTURE\n", system_clock, customer->no);
#endif
        if (customer->no >= (initial_bias + nr_batch * batch_size)) {
          for (i = 0; i < nr_batch; i++) {
            batch_mean[i] = batch_sum[i] / batch_size;
          }
          /* check correlation */
          lag_1_corr = sample_lag1_corr_sequence(batch_mean, nr_batch);
          if (fabs(lag_1_corr) < correlation_bound) {
            /* check confidence interval */
            t = gsl_cdf_tdist_Pinv(1.0-half_alpha, nr_batch - 1); 
            avg = avg_sequence(batch_mean, nr_batch);
            dev = dev_sequence(batch_mean, nr_batch);
            ci_hw = t * dev / sqrt((double) nr_batch);
            ci_hb = avg * eps_relative;
            if (ci_hw < ci_hb) {
              if (result) {
                result->avg = avg;
                result->ci_hw = ci_hw;
                result->lag_1 = lag_1_corr;
              }
              return;
            }
          }
          /* not satisfy constraint, double batch_size */
          batch_size *= 2;
          for (i = 0; i < nr_batch / 2; i++) {
            batch_sum[i] = batch_sum[i*2] + batch_sum[i*2+1];
          }
          for (i = nr_batch / 2; i < nr_batch; i++) {
            batch_sum[i] = 0.0;
          }
        }
        if (customer->no >= initial_bias) {
          batch_index = (customer->no - initial_bias) / batch_size;
          batch_sum[batch_index] += customer->departure_time - customer->arrival_time;
          total_customer_in_system_time += customer->departure_time - customer->arrival_time;
        }
        free(customer);
        customer = NULL;
        /* step 3: update state */
        if (system_queue.count > 0) {
          customer = (struct customer *) dequeue(&system_queue);
          /* set service time and departure time */
          service_time = get_service_time_from_customer(customer);
          departure_time = system_clock + service_time;
          event_type = DEPARTURE;
          customer->departure_time = departure_time;
          add_event(&event_list, event_type, departure_time, (void *) customer);
        } else if (system_queue.count == 0) {
          server_state = IDLE;
        }

        /* step 4: generate future event into event list */
        break;
      default:
        fprintf(stderr, "Error: unkown event type.\n");
        exit(EXIT_FAILURE);
    }
    free(event);
    event = NULL;

    /* get next event */
    event = get_event(event_list);
  }
#ifdef DEBUG
  printf("Info: event list is empty.\n");
  printf("Info: simulation ends.\n");
#endif
}
void mm_one_queue_simulator_with_initail_bias(long nr_customer, double average_interarrival_time, double average_service_time, long *next_seed_interarrival, long *next_seed_service, struct mm_one_simulation_result *result, long initial_bias) {
  struct event *event_list = NULL;
  struct queue system_queue;
  enum server_state server_state = IDLE;
  double system_clock = 0.0;
  struct event *event;

  enum event_type event_type;
  int customer_number = 0;
  double clock_time;
  double arrival_time;
  double interarrival_time;
  double departure_time;
  double service_time;

  struct customer *customer;

  double lamda_interarrival_rate = 1.0 / average_interarrival_time; /* interarrival rate: lamda = 1 / average_time */
  double mu_service_rate = 1.0 / average_service_time; /* service_rate: mu = 1 / arverage_service_time */

  double total_customer_in_system_time = 0.0; 
  /* initial system */
  init_queue(&system_queue);

  /* step 0: initial first event and add into event list */
#ifdef DEBUG
  printf("Info: simulation starts.\n");
#endif
  if (customer_number < nr_customer) {
    event_type = ARRIVAL;
    clock_time = 1.0;
    customer = init_customer(customer_number);
    customer->arrival_time = clock_time;
    customer_number++;
    add_event(&event_list, event_type, clock_time, (void *) customer);
  }
  /* step 1: pop event from event list */
  event = get_event(event_list);
  while (event) {
    /* step 2: addvance clock */
    system_clock = event->clock_time;
    pop_event(&event_list);
    /* get customer */
    customer = (struct customer *) event->content;
    event->content = NULL;
    switch (event->event_type) {
      case ARRIVAL:
#ifdef DEBUG
        /* print info */
        printf("Info: [time: %12f] [customer: %8d] event: ARRIVAL\n", system_clock, customer->no);
#endif
        /* generate service time */
        service_time = exponential_random_generator(mu_service_rate, next_seed_service);
        add_service_time_to_customer(customer, service_time);
        /* step 3: update state */
        if (server_state == IDLE) {
          server_state = BUSY;
          /* set service time and departure time */
          service_time = customer->service_time;
          departure_time = system_clock + service_time;
          event_type = DEPARTURE;
          customer->departure_time = departure_time;
          add_event(&event_list, event_type, departure_time, (void *) customer);
        } else if (server_state == BUSY) {
          /* add customer into queue */
          enqueue(&system_queue, (void *) customer);
        }
        /* step 4: generate future event into event list */
        /* if customer_number < nr_customer, generate next arrival event */
        if (customer_number < nr_customer) {
          interarrival_time = exponential_random_generator(lamda_interarrival_rate, next_seed_interarrival);
          arrival_time = system_clock + interarrival_time;
          event_type = ARRIVAL;
          customer = init_customer(customer_number);
          customer->arrival_time = arrival_time;
          customer_number++;
          add_event(&event_list, event_type, arrival_time, (void *) customer);
        }
     
        break;
      case DEPARTURE:
#ifdef DEBUG
        /* print info */
        printf("Info: [time: %12f] --------------------------------------- [customer: %8d] event: DEPARTURE\n", system_clock, customer->no);
#endif
        /* store each customer's system time in result */
        if (result && result->customer_in_system_time) {
          result->customer_in_system_time[customer->no] = customer->departure_time - customer->arrival_time;
        }

        /* initial bias */
        if (customer->no >= initial_bias) {
          total_customer_in_system_time += customer->departure_time - customer->arrival_time;
        }

        free(customer);
        customer = NULL;
        /* step 3: update state */
        if (system_queue.count > 0) {
          customer = (struct customer *) dequeue(&system_queue);
          /* set service time and departure time */
          service_time = get_service_time_from_customer(customer);
          departure_time = system_clock + service_time;
          event_type = DEPARTURE;
          customer->departure_time = departure_time;
          add_event(&event_list, event_type, departure_time, (void *) customer);
        } else if (system_queue.count == 0) {
          server_state = IDLE;
        }

        /* step 4: generate future event into event list */
        break;
      default:
        fprintf(stderr, "Error: unkown event type.\n");
        exit(EXIT_FAILURE);
    }
    free(event);
    event = NULL;

    /* get next event */
    event = get_event(event_list);
  }
  if (result) {
    result->average_customer_in_system_time = total_customer_in_system_time / (nr_customer - initial_bias);
#ifdef DEBUG
    printf("Info: average time of a customer in system: %12f\n", result->average_customer_in_system_time);
#endif
  }
#ifdef DEBUG
  printf("Info: event list is empty.\n");
  printf("Info: simulation ends.\n");
#endif
}