void report(void) /* Report generator function. */ { int i; float overall_avg_job_tot_delay, avg_job_tot_delay, sum_probs; /* Compute the average total delay in queue for each job type and the overall average job total delay. */ fprintf(outfile, "\n\n\n\nJob type Average total delay in queue"); overall_avg_job_tot_delay = 0.0; sum_probs = 0.0; for (i = 1; i <= num_job_types; ++i) { avg_job_tot_delay = sampst(0.0, -(num_stations + i)) * num_tasks[i]; fprintf(outfile, "\n\n%4d%27.3f", i, avg_job_tot_delay); overall_avg_job_tot_delay += (prob_distrib_job_type[i] - sum_probs) * avg_job_tot_delay; sum_probs = prob_distrib_job_type[i]; } fprintf(outfile, "\n\nOverall average job total delay =%10.3f\n", overall_avg_job_tot_delay); /* Compute the average number in queue, the average utilization, and the average delay in queue for each station. */ fprintf(outfile, "\n\n\n Work Average number Average Average delay"); fprintf(outfile, "\nstation in queue utilization in queue"); for (j = 1; j <= num_stations; ++j) fprintf(outfile, "\n\n%4d%17.3f%17.3f%17.3f", j, filest(j), timest(0.0, -j) / num_machines[j], sampst(0.0, -j)); }
void depart (void) /* Event function for departure of a job from a particular station. */ { int station, job_type_queue, task_queue; /* Determine the station from which the job is departing. */ job_type = transfer[3]; task = transfer[4]; station = route[job_type][task]; /* Check to see whether the queue for this station is empty. */ if (list_size[station] == 0) { /* The queue for this station is empty, so make a machine in this station idle. */ --num_machines_busy[station]; timest ((double) num_machines_busy[station], station); } else { /* The queue is nonempty, so start service on first job in queue. */ list_remove (FIRST, station); /* Tally this delay for this station. */ sampst (sim_time - transfer[1], station); /* Tally this same delay for this job type. */ job_type_queue = transfer[2]; task_queue = transfer[3]; sampst (sim_time - transfer[1], num_stations + job_type_queue); /* Schedule end of service for this job at this station. Note defining attributes beyond the first two for the event record before invoking event_schedule. */ transfer[3] = job_type_queue; transfer[4] = task_queue; event_schedule (sim_time + erlang (2, mean_service[job_type_queue][task_queue], STREAM_SERVICE), EVENT_DEPARTURE); } /* If the current departing job has one or more tasks yet to be done, send the job to the next station on its route. */ if (task < num_tasks[job_type]) { ++task; arrive (2); } }
void report(void) /* Report generator function. */ { /* Get and write out estimates of desired measures of performance. */ fprintf(outfile, "\n\n%5d%16.3f%16.3f%16.3f CPU-1", num_terms, sampst(0.0, -SAMPST_RESPONSE_TIMES_1), filest(LIST_QUEUE_1), filest(LIST_CPU_1)); fprintf(outfile, "\n %16.3f%16.3f%16.3f CPU-2", sampst(0.0, -SAMPST_RESPONSE_TIMES_2), filest(LIST_QUEUE_2), filest(LIST_CPU_2)); fprintf(outfile, "\n %16.3f%16.3f%16.3f CPU-3\n", sampst(0.0, -SAMPST_RESPONSE_TIMES_3), filest(LIST_QUEUE_3), filest(LIST_CPU_3)); }
void out_sampst (FILE * unit, int lowvar, int highvar) { /* Write sampst statistics for variables lowvar through highvar on file "unit". */ int ivar, iatrr; if (lowvar > highvar || lowvar > MAX_SVAR || highvar > MAX_SVAR) return; fprintf (unit, "\n sampst Number"); fprintf (unit, "\nvariable of"); fprintf (unit, "\n number Average values Maximum"); fprintf (unit, " Minimum"); fprintf (unit, "\n___________________________________"); fprintf (unit, "_____________________________________"); for (ivar = lowvar; ivar <= highvar; ++ivar) { fprintf (unit, "\n\n%5d", ivar); sampst (0.00, -ivar); for (iatrr = 1; iatrr <= 4; ++iatrr) pprint_out (unit, iatrr); } fprintf (unit, "\n___________________________________"); fprintf (unit, "_____________________________________\n\n\n"); }
void skaut_departure() { push_array(); int current_unit = (int) transfer[3]; int i = 0; for (i = NUM_MACHINES; i>=current_unit; i--) { //add delay if machine is broken or there is a broken machine before current one if (machine_broken[i] > 0.0) { if ((i == current_unit) || (list_size[1+number_of_machines + current_unit] < queue_size[1+current_unit])) { // if current machine is broken then delay it. event_schedule(PREP_TIME+sim_time + machine_broken[i], EVENT_SKAUT_DEPARTURE); //also if next queue is full then delay it. return; } // printf("Size of next queue %d, limit of next queue %d\n",list_size[1+number_of_machines + current_unit], queue_size[1+current_unit]); break; } } if (current_unit == MACHINES_ON_THE_LEFT_SIDE) { skaut_throughput += 2; sampst(sim_time - transfer[4], throughput_time); list_remove(FIRST,current_unit); } else { list_remove(FIRST,current_unit); pop_array(); transfer[3]++; event_schedule(PREP_TIME + sim_time + transfer_time[(int)(transfer[3])-1], EVENT_SKAUT_ARRIVAL); } if (list_size[number_of_machines + current_unit] != 0) { pop_array(); list_file(FIRST,current_unit); // first equals last because size should only be 1 pop_array(); list_remove(FIRST, number_of_machines + current_unit); pop_array(); sampst(sim_time - transfer[5], sampst_delays); sampst(sim_time - transfer[5], current_unit); event_schedule(PREP_TIME + sim_time + work_time[current_unit], EVENT_SKAUT_DEPARTURE); } }
void skaut_arrival() { push_array(); int current_unit = (int)transfer[3]; int i; for (i = NUM_MACHINES; i>=current_unit; i--) { //add delay if there is a broken machine before current one if (machine_broken[i] > 0.0) { if ((list_size[1+number_of_machines + current_unit] < queue_size[1+current_unit])||queue_size[1+current_unit] == 0) { // if current machine is broken then delay it.x event_schedule(PREP_TIME+sim_time + machine_broken[i] + work_time[current_unit], EVENT_SKAUT_ARRIVAL); //also if next queue is full then delay it. return; } } } // check if machine is not busy if (list_size[current_unit] == 0 && machine_broken[current_unit] == 0.0) { sampst(0.0, sampst_delays); sampst(0.0, current_unit); list_file(FIRST, current_unit); // last := first here because there are only to be 0 or 1 items in machine // schedule departure after machine processing time pop_array(); event_schedule(PREP_TIME + sim_time + work_time[current_unit], EVENT_SKAUT_DEPARTURE); } else { if (list_size[number_of_machines + current_unit] == queue_size[current_unit]) { event_schedule(PREP_TIME + sim_time + work_time[current_unit], EVENT_SKAUT_ARRIVAL); //also if queue is full then delay it. } else { transfer[5] = sim_time; list_file(LAST, number_of_machines + current_unit); if(list_size[current_unit] > queue_max_lengths[number_of_machines + current_unit]) { queue_max_lengths[current_unit] = list_size[number_of_machines + current_unit]; } } } }
void init_simlib () { /* Initialize simlib.c. List LIST_EVENT is reserved for event list, ordered by event time. init_simlib must be called from main by user. */ int list, listsize; if (maxlist < 1) maxlist = MAX_LIST; listsize = maxlist + 1; /* Initialize system attributes. */ sim_time = 0.0; if (maxatr < 4) maxatr = MAX_ATTR; /* Allocate space for the lists. */ list_rank = (int *) calloc (listsize, sizeof (int)); list_size = (int *) calloc (listsize, sizeof (int)); head = (struct master **) calloc (listsize, sizeof (struct master *)); tail = (struct master **) calloc (listsize, sizeof (struct master *)); transfer = (double *) calloc (maxatr + 1, sizeof (double)); /* Initialize list attributes. */ for (list = 1; list <= maxlist; ++list) { head[list] = NULL; tail[list] = NULL; list_size[list] = 0; list_rank[list] = 0; } /* Set event list to be ordered by event time. */ list_rank[LIST_EVENT] = EVENT_TIME; /* Initialize statistical routines. */ sampst (0.0, 0); timest (0.0, 0); }
void arrive (int new_job) /* Function to serve as both an arrival event of a job to the system, as well as the non-event of a job's arriving to a subsequent station along its route. */ { int station; /* If this is a new arrival to the system, generate the time of the next arrival and determine the job type and task number of the arriving job. */ if (new_job == 1) { event_schedule (sim_time + expon (mean_interarrival, STREAM_INTERARRIVAL), EVENT_ARRIVAL); job_type = intrand (prob_distrib_job_type, STREAM_JOB_TYPE); task = 1; } /* Determine the station from the route matrix. */ station = route[job_type][task]; /* Check to see whether all machines in this station are busy. */ if (num_machines_busy[station] == num_machines[station]) { /* All machines in this station are busy, so place the arriving job at the end of the appropriate queue. Note that the following data are stored in the record for each job: 1. Time of arrival to this station. 2. Job type. 3. Current task number. */ transfer[1] = sim_time; transfer[2] = job_type; transfer[3] = task; list_file (LAST, station); } else { /* A machine in this station is idle, so start service on the arriving job (which has a delay of zero). */ sampst (0.0, station); /* For station. */ sampst (0.0, num_stations + job_type); /* For job type. */ ++num_machines_busy[station]; timest ((double) num_machines_busy[station], station); /* Schedule a service completion. Note defining attributes beyond the first two for the event record before invoking event_schedule. */ transfer[3] = job_type; transfer[4] = task; event_schedule (sim_time + erlang (2, mean_service[job_type][task], STREAM_SERVICE), EVENT_DEPARTURE); } }
void end_CPU_run(int list_cpu_num) /* Event function to end a CPU run of a job. */ { /* Remove the job from the CPU. */ list_remove(FIRST, list_cpu_num); int jenis_job_queue; switch (list_cpu_num){ case LIST_CPU_1: jenis_job_queue=LIST_QUEUE_1; break; case LIST_CPU_2: jenis_job_queue=LIST_QUEUE_2; break; case LIST_CPU_3: jenis_job_queue=LIST_QUEUE_3; break; } /* Check to see whether this job requires more CPU time. */ if (transfer[2] > 0.0) { /* This job requires more CPU time, so place it at the end of the queue and start the first job in the queue. */ list_file(LAST, jenis_job_queue); start_CPU_run(jenis_job_queue); } else { /* This job is finished, so collect response-time statistics and send it back to its terminal, i.e., schedule another arrival from the same terminal. */ sampst(sim_time - transfer[1], SAMPST_RESPONSE_TIMES);//TODO nanti hapus switch(jenis_job_queue){ case (LIST_QUEUE_1): sampst(sim_time - transfer[1], SAMPST_RESPONSE_TIMES_1); break; case (LIST_QUEUE_2): sampst(sim_time - transfer[1], SAMPST_RESPONSE_TIMES_2); break; case (LIST_QUEUE_3): sampst(sim_time - transfer[1], SAMPST_RESPONSE_TIMES_3); break; } event_schedule(sim_time + expon(mean_think, STREAM_THINK), EVENT_ARRIVAL); //TODO nanti ganti sama distribusi yang disebut di spek (belum jelas) /* Increment the number of completed jobs. */ ++num_responses; /* Check to see whether enough jobs are done. */ if (num_responses >= num_responses_required) /* Enough jobs are done, so schedule the end of the simulation immediately (forcing it to the head of the event list). */ event_schedule(sim_time, EVENT_END_SIMULATION); else /* Not enough jobs are done; if the queue is not empty, start another job. */ if (list_size[jenis_job_queue] > 0) start_CPU_run(jenis_job_queue); } }
void report() { int i; float total_downtime = 0.0; printf("\n*****************************************************\n"); printf("Report for %d failures per day\n",failure_nr); for (i=0; i <NUM_MACHINES; i++) { printf("--Breakdown in machine nr %d--\n", i+1); printf("Number of fails\t Downtime \t\n"); printf("\t %d\t", fail_list[i].machine_nr); printf("%.3f sec / %.3f min\t", fail_list[i].downtime,fail_list[i].downtime/60.0); printf("\n"); total_downtime+=fail_list[i].downtime; } printf("\n\n"); printf("Total downtime was %.3lf seconds or %.3lf minutes\n",total_downtime, total_downtime/60.0); printf("--------------\nMachine load\n--------------\n"); for (i=1; i <= number_of_machines; i++) { printf("Machine %d\t", i); } printf("\n"); for (i=1; i <= number_of_machines; i++) { printf("%f\t", filest(i) ); } printf("\n\n"); printf("-----------------------\nAverage delay in queues\n-----------------------\n"); for (i=1; i <= number_of_machines; i++) { printf("Queue %d \t", i); } printf("\n"); for (i=1; i <= number_of_machines; i++) { printf("%f\t", sampst(0.0, -i)); } printf("\n\n"); printf("Average queue delay: %f\n", sampst(0.0, -sampst_delays)); printf("Worst case queue delay: %f\n", transfer[3]); printf("Best case queue delay: %f\n", transfer[4]); printf("System throughput: %d\n", skaut_throughput ); printf("Average throughput time: %f\n", sampst(0.0, -throughput_time)); printf("Min throughput time: %f\n", transfer[4]); printf("Random seed: %d\n\n", stream); int l; int sum_q_lenths =0; int number_of_queues =0; for (l = 1; l <= number_of_machines; l++) { if (queue_size[l] < 1) continue; printf("Maximum length of queue %d: %d\n", l, queue_max_lengths[l]); sum_q_lenths += queue_max_lengths[l]; number_of_queues++; } printf("Average maximum length of queues: %f\n\n", (float) sum_q_lenths / (float) number_of_queues); }
void end_warmup() { sampst(0.0, 0); timest(0.0, 0); skaut_throughput = 0; }
void verify_actors(FILE *storm_list, FILE *plane_list, FILE *verification_log) { int time, time_diff, time_prev = 0; while (fscanf(plane_list, "%*d %d %*d\n", &time) != EOF) { time_diff = time - time_prev; sampst((float)time_diff, SAMPST_PLANE_LAND); time_prev = time; } time_prev = 0; while (fscanf(storm_list, "%*d %d %*d\n", &time) != EOF) { time_diff = time - time_prev; sampst((float)time_diff, SAMPST_STORM_BETWEEN); time_prev = time; fscanf(storm_list, "%*d %d %*d\n", &time); time_diff = time - time_prev; sampst((float)time_diff, SAMPST_STORM_LENGTH); time_prev = time; } sampst(0.0, -SAMPST_PLANE_LAND); float plane_avg = transfer[1], plane_max = transfer[3], plane_min = transfer[4]; /* Check if average landing frequency generated agrees with the specified value */ if (plane_avg-TIME_HOUR > G.time_land_freq || plane_avg+TIME_HOUR < G.time_land_freq) { fprintf(verification_log, "actors = -1\n"); printf("The generated average plane landing time does not agree with the specified value.\n"); exit(0); } /* Check if any plane landing frequencies go outside the specified range. */ if (plane_max > G.time_land_freq+G.time_land_var || plane_min < G.time_land_freq-G.time_land_var) { fprintf(verification_log, "actors = -1\n"); printf("The generated plane landing frequencies go out of the specified range.\n"); exit(0); } sampst(0.0, -SAMPST_STORM_LENGTH); float storm_len_avg = transfer[1], storm_len_max = transfer[3], storm_len_min = transfer[4]; /* Check if average storm length generated agrees with the specified value */ if (storm_len_avg-TIME_HOUR > G.time_storm_dur || storm_len_avg+TIME_HOUR < G.time_storm_dur) { printf("Average: %f Specified: %d\n", storm_len_avg/60, G.time_between_storms/60); fprintf(verification_log, "actors = -2\n"); printf("The generated average storm length does not agree with the specified value.\n"); exit(0); } /* Check if any storm lengths go outside the specified range. */ if (storm_len_max > G.time_storm_dur+G.time_storm_var || storm_len_min < G.time_storm_dur-G.time_storm_var) { fprintf(verification_log, "actors = -3\n"); printf("The generated storm lengths go out of the specified range.\n"); exit(0); } sampst(0.0, -SAMPST_STORM_BETWEEN); float storm_btw_avg = transfer[1], storm_btw_max = transfer[3], storm_btw_min = transfer[4]; /* Check if average storm frequency generated agrees with the specified value */ if (storm_btw_avg-TIME_HOUR*8 > G.time_between_storms || storm_btw_avg+TIME_HOUR*8 < G.time_between_storms) { printf("Average: %f Specified: %d\n", storm_btw_avg/60, G.time_between_storms/60); fprintf(verification_log, "actors = -1\n"); printf("The generated average storm frequency does not agree with the specified value.\n"); exit(0); } fprintf(verification_log, "actors = 0\n"); }