/////////////////////////////////////////////////////////// // // // BIG NOTE: ARRAY INDEX O ARE NEVER USED // // // /////////////////////////////////////////////////////////// // // TODO: // // None ! // Yeah, How about that? // #include #include #include #include #include #include "eclipse.h" #include "sim.h" // ------------------------------------------------------------ // External Predicates // ------------------------------------------------------------ int sim_init(){ pword arg; double num; pword list, head, tail; pword lst, hd, tl; int count, idx; int i; // Set up the GSL gsl_rng_env_setup (); T = gsl_rng_default; r = gsl_rng_alloc(gsl_rng_taus); gsl_rng_set(r, (unsigned long int) time(NULL) ); // Seed the randomizer srand(time(NULL)); /* -------------------------------------------- */ // Hopitalize rate arg = ec_arg(1); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; hosp_rate = num; // Request rate arg = ec_arg(2); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; request_rate = (int) num; // Comm Fail rate arg = ec_arg(3); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; comm_fail_rate = num; // Diagnosis time arg = ec_arg(4); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; diag_time = (int) num; // Unload time arg = ec_arg(5); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; unload_time = (int) num; // Extra time the crew needs, per consecutive trip arg = ec_arg(6); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; markup_time = (int) num; // Crew recovery time arg = ec_arg(7); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; crew_recovery_time = (int) num; // Emergency speed arg = ec_arg(8); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; spb_emerg = (int) num; // Normal (non-emergency) speed arg = ec_arg(9); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; spb_norm = (int) num; // Emergency speed in foreign regions arg = ec_arg(10); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; spb_emerg_foreign = (int) num; // Normal (non-emergency) speed in foreign regions arg = ec_arg(11); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; spb_norm_foreign = (int) num; // The regions and their geometries count = 0; list = ec_arg(12); while (ec_get_list(list, &head, &tail) == PSUCCEED){ // Region Index if (ec_get_list(head, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; idx = (int) num; // X1 lst = tl; if (ec_get_list(lst, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; regions[idx].x_botleft = (int) num; // Y1 lst = tl; if (ec_get_list(lst, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; regions[idx].y_botleft = (int) num; // X2 lst = tl; if (ec_get_list(lst, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; regions[idx].x_topright = (int) num; // Y2 lst = tl; if (ec_get_list(lst, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; regions[idx].y_topright = (int) num; // Next region, if any count++; list = tail; } region_count = count; // Bases count = 0; list = ec_arg(13); while (ec_get_list(list, &head, &tail) == PSUCCEED){ // Index if (ec_get_list(head, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; idx = (int) num; // X lst = tl; if (ec_get_list(lst, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; bases[idx].x = (int) num; // Y lst = tl; if (ec_get_list(lst, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; bases[idx].y = (int) num; // Next base, if any count++; list = tail; } base_count = count; // Hospitals count = 0; list = ec_arg(14); while (ec_get_list(list, &head, &tail) == PSUCCEED){ // Index if (ec_get_list(head, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; idx = (int) num; // X lst = tl; if (ec_get_list(lst, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; hosps[idx].x = (int) num; // Y lst = tl; if (ec_get_list(lst, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; hosps[idx].y = (int) num; // Next hosp, if any count++; list = tail; } hosp_count = count; // Cars count = 0; list = ec_arg(15); while (ec_get_list(list, &head, &tail) == PSUCCEED){ // Index if (ec_get_list(head, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; idx = (int) num; // X_base lst = tl; if (ec_get_list(lst, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; cars[idx].x_base = (int) num; // Y_base lst = tl; if (ec_get_list(lst, &hd, &tl) != PSUCCEED) return PFAIL; if (ec_get_double(hd, &num) != PSUCCEED) return PFAIL; cars[idx].y_base = (int) num; // Next car, if any count++; list = tail; } car_count = count; // Init and zero all data structs sim_reset(); if(debug_level >= 1){ fprintf(stderr, "\n"); fprintf(stderr, "\n"); fprintf(stderr, "Simulator initialized with: \n"); fprintf(stderr, "\n"); fprintf(stderr, "Regions:\n\n"); for(i = 1; i < region_count + 1; i++){ fprintf(stderr, " - %d: %d, %d, %d, %d\n", \ i, regions[i].x_botleft, regions[i].y_botleft, regions[i].x_topright, regions[i].y_topright); } fprintf(stderr, "\n"); fprintf(stderr, "Bases:\n\n"); for(i = 1; i < base_count + 1; i++){ fprintf(stderr, " - %d: %d, %d\n", \ i, bases[i].x, bases[i].y); } fprintf(stderr, "\n"); fprintf(stderr, "Hospitals:\n\n"); for(i = 1; i < hosp_count + 1; i++){ fprintf(stderr, " - %d: %d, %d\n", \ i, hosps[i].x, hosps[i].y); } fprintf(stderr, "\n"); fprintf(stderr, "Ambulances:\n\n"); for(i = 1; i < car_count + 1; i++){ fprintf(stderr, " - %d: %d, %d\n", \ i, cars[i].x_base, cars[i].y_base); } fprintf(stderr, "\n"); fprintf(stderr, "Other Parameters:\n\n"); fprintf(stderr, " - RequestRate = %d\n", request_rate); fprintf(stderr, " - CommFailRate = %lf\n", comm_fail_rate); fprintf(stderr, " - HospitalizeRate = %lf\n", hosp_rate); fprintf(stderr, " - DiagnosisTime = %d\n", diag_time); fprintf(stderr, " - UnloadingTime = %d\n", unload_time); fprintf(stderr, " - TirednessMarkupTime = %d\n", markup_time); fprintf(stderr, " - CrewRecoveryTime = %d\n", crew_recovery_time); fprintf(stderr, " - SPB Emerg Home = %d\n", spb_emerg); fprintf(stderr, " - SPB Normal Home = %d\n", spb_norm); fprintf(stderr, " - SPB Emerg Foreign = %d\n", spb_emerg_foreign); fprintf(stderr, " - SPB Normal Foreign = %d\n", spb_norm_foreign); fprintf(stderr, "\n"); } return PSUCCEED; } int sim_reset(){ int i, j; // Reset the Cars for(i = 1; i < car_count + 1; i++){ cars[i].x_start = -1; cars[i].y_start = -1; cars[i].time_start = -1; cars[i].x_inc = -1; cars[i].y_inc = -1; cars[i].time_arr_inc = -1; cars[i].time_leave_inc = -1; cars[i].x_hosp = -1; cars[i].y_hosp = -1; cars[i].time_arr_hosp = -1; cars[i].time_leave_hosp = -1; cars[i].time_arr_base = -1; cars[i].consec_trip_count = 0; cars[i].ready = TRUE; } curr_time = 0; for(i = 0; i < MAX_X; i++){ for(j = 0; j < MAX_Y; j++){ pending_request_count[i][j] = 0; } } next_request = 0; gen_next_request(); request_count = 0; late08_delay_count = 0; late08_travel_count = 0; late08_both_count = 0; late11_delay_count = 0; late11_travel_count = 0; late11_both_count = 0; due_events = NULL; return PSUCCEED; } int sim_set_request_rate(){ pword arg; double num; arg = ec_arg(1); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; request_rate = (int)num; return PSUCCEED; } int sim_set_debug_level(){ pword arg; double num; arg = ec_arg(1); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; debug_level = (int)num; return PSUCCEED; } int sim_noop(){ pword arg; double num; int t; arg = ec_arg(1); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; t = (int)num; // Time // curr_time = next_event(); < -- Don't !. if(debug_level >= 1){ fprintf(stderr, "NoOp: at time %d\n", t); fprintf(stderr, "\n"); } return PSUCCEED; } int sim_wait(){ pword arg; double num; int t; arg = ec_arg(1); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; t = (int)num; // Time curr_time = next_event(); if(debug_level >= 1){ fprintf(stderr, "Wait: from %d to %d\n", t, curr_time); fprintf(stderr, "\n"); } return PSUCCEED; } int sim_mobilize(){ pword arg; double num; int c, t, rt; struct coord org, inc, hosp, base; int ti, td, th, tu, tb; arg = ec_arg(1); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; c = (int)num; arg = ec_arg(2); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; org.x = (int)num; arg = ec_arg(3); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; org.y = (int)num; arg = ec_arg(4); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; inc.x = (int)num; arg = ec_arg(5); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; inc.y = (int)num; arg = ec_arg(6); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; t = (int)num; // mobilize time arg = ec_arg(7); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; rt = (int)num; // request time /* -------------------------------------------------------- */ // // Randomly decide the scenario of the service trip. // Two possible scenarios: // // 1. Patient needs to be carried to a hospital: // Arrive incident / Start onsite diag // Start to go hosp // Arrive hosp / start unload // Start go back to base // Arrive base // // 2. No need to go hosp: // Arrive incident / Start onsite diag // Start go back to base // Arrive base // // Please see accompanied documentation for a more detailed description // if (((double) rand() / (double)RAND_MAX) < hosp_rate){ hosp = local_hosp(inc); base.x = cars[c].x_base; base.y = cars[c].y_base; // // Calc the time required to do various tasks // ti = simu_drive_full(c, org, inc, spb_emerg, spb_emerg_foreign); td = (int) rand_gaussian_duration(diag_time); th = simu_drive_full(c, inc, hosp, spb_emerg, spb_emerg_foreign); tu = (int) rand_gaussian_duration(unload_time); tb = simu_drive_full(c, hosp, base, spb_norm, spb_norm_foreign); // // Record everthing // cars[c].x_start = org.x; cars[c].y_start = org.y; cars[c].time_start = t; cars[c].x_inc = inc.x; cars[c].y_inc = inc.y; cars[c].time_arr_inc = t + ti + cars[c].consec_trip_count * markup_time; cars[c].time_leave_inc = cars[c].time_arr_inc + td + (cars[c].consec_trip_count * markup_time / 2); cars[c].x_hosp = hosp.x; cars[c].y_hosp = hosp.y; cars[c].time_arr_hosp = cars[c].time_leave_inc + th; cars[c].time_leave_hosp = cars[c].time_arr_hosp + tu + (cars[c].consec_trip_count * markup_time / 2); cars[c].time_arr_base = cars[c].time_leave_hosp + tb + crew_recovery_time; // // Statistics // if(cars[c].time_arr_inc > rt + 480){ if(t > rt && ti > 480) late08_both_count++; else if(t > rt) late08_delay_count++; else if(ti > 480) late08_travel_count++; } if(cars[c].time_arr_inc > rt + 660){ if(t > rt && ti > 660) late11_both_count++; else if(t > rt) late11_delay_count++; else if(ti > 660) late11_travel_count++; } if(debug_level >= 1){ fprintf( \ stderr, \ "Mobilize: Car %d will arr I(%d, %d) at %d, rdy H(%d, %d) at %d, rdy B(%d, %d) at %d \n", \ c, cars[c].x_inc, cars[c].y_inc, cars[c].time_arr_inc, \ cars[c].x_hosp, cars[c].y_hosp, cars[c].time_leave_hosp, \ cars[c].x_base, cars[c].y_base, cars[c].time_arr_base \ ); fprintf(stderr, "\n"); } } else{ base.x = cars[c].x_base; base.y = cars[c].y_base; // // Calc the time required to do various tasks // ti = simu_drive_full(c, org, inc, spb_emerg, spb_emerg_foreign); td = (int) rand_gaussian_duration(diag_time); tb = simu_drive_full(c, inc, base, spb_norm, spb_norm_foreign); // // Record everthing // cars[c].x_start = org.x; cars[c].y_start = org.y; cars[c].time_start = t; cars[c].x_inc = inc.x; cars[c].y_inc = inc.y; cars[c].time_arr_inc = t + ti + cars[c].consec_trip_count * markup_time; cars[c].time_leave_inc = cars[c].time_arr_inc + td + (cars[c].consec_trip_count * markup_time / 2); cars[c].x_hosp = -1; cars[c].y_hosp = -1; cars[c].time_arr_hosp = -1; cars[c].time_leave_hosp = -1; cars[c].time_arr_base = cars[c].time_leave_inc + tb + crew_recovery_time; // // Statistics // if(cars[c].time_arr_inc > rt + 480){ if(t > rt && ti > 480) late08_both_count++; else if(t > rt) late08_delay_count++; else if(ti > 480) late08_travel_count++; } if(cars[c].time_arr_inc > rt + 660){ if(t > rt && ti > 660) late11_both_count++; else if(t > rt) late11_delay_count++; else if(ti > 660) late11_travel_count++; } if(debug_level >= 1){ fprintf( \ stderr, \ "Mobilize: Car %d will arr I(%d, %d) at %d, skip, rdy B(%d, %d) at %d \n", \ c, cars[c].x_inc, cars[c].y_inc, cars[c].time_arr_inc, \ cars[c].x_base, cars[c].y_base, cars[c].time_arr_base \ ); fprintf(stderr, "\n"); } } // Car becomes busy once mobilized cars[c].ready = FALSE; // Move the time forward curr_time = t; // Increase the trip count of the car cars[c].consec_trip_count++; return PSUCCEED; } int sim_sense_exo(){ int i; struct event *e, *p1, *p2; pword w, list; int tb; struct coord src, dst; // Is there a request that is due if (curr_time >= next_request){ e = (struct event *) malloc(sizeof(struct event)); e->type = RQT; e->time = curr_time; e->x = request_x; e->y = request_y; e->car = -1; insert_event(e); // Generate a new request gen_next_request(); // Statistic request_count++; } // Scan the cars for any additional event that are due for (i = 1; i < car_count + 1; i++){ if(debug_level >= 3){ fprintf( \ stderr, \ "sense_exo: time %d, car %d, arr %d, leaveinc %d, arrhosp %d, leavehosp %d\n", \ curr_time, i, cars[i].time_arr_inc, cars[i].time_leave_inc, cars[i].time_arr_hosp, cars[i].time_leave_hosp \ ); } // Check the car arrival time and // generate "reportArrival(inc)" if ((cars[i].time_arr_inc > 0) && (cars[i].time_arr_inc) <= curr_time){ e = (struct event *) malloc(sizeof(struct event)); e->car = i; e->type = ARR; e->time = cars[i].time_arr_inc; e->x = cars[i].x_inc; e->y = cars[i].y_inc; insert_event(e); // If other cars before us have took care of all the patients at this location // change the game plan and report ready if(pending_request_count[cars[i].x_inc][cars[i].y_inc] < 1){ // Time required to go back to the HOME base (from Incident) src.x = cars[i].x_inc; src.y = cars[i].y_inc; dst.x = cars[i].x_base; dst.y = cars[i].y_base; tb = simu_drive_full(i, src, dst, spb_norm, spb_norm_foreign); // Update the trip scenario cars[i].time_leave_inc = curr_time + 45; cars[i].x_hosp = -1; cars[i].y_hosp = -1; cars[i].time_arr_hosp = -1; cars[i].time_leave_hosp = -1; cars[i].time_arr_base = cars[i].time_leave_inc + tb + crew_recovery_time; } else{ pending_request_count[cars[i].x_inc][cars[i].y_inc]--; } cars[i].time_arr_inc = -1; } // Check the car ready time and generate either // "reportReady(Inc)" or "reportReady(Hosp)" if(cars[i].time_arr_hosp < 0){ // Become ready at the inc if ((cars[i].time_leave_inc > 0) && \ (cars[i].time_leave_inc <= curr_time)){ e = (struct event *) malloc(sizeof(struct event)); e->car = i; e->type = RDY; e->time = cars[i].time_leave_inc; e->x = cars[i].x_inc; e->y = cars[i].y_inc; insert_event(e); cars[i].time_leave_inc = -1; cars[i].ready = TRUE; } } else{ // Become ready at the hosp if ((cars[i].time_leave_hosp > 0) && (cars[i].time_leave_hosp) <= curr_time){ e = (struct event *) malloc(sizeof(struct event)); e->car = i; e->type = RDY; e->time = cars[i].time_leave_hosp; e->x = cars[i].x_hosp; e->y = cars[i].y_hosp; insert_event(e); cars[i].time_leave_hosp = -1; cars[i].ready = TRUE; } } // Check the car ready at base time and // generate "reportReady(base)" if ((cars[i].time_arr_base > 0) && (cars[i].time_arr_base) <= curr_time){ e = (struct event *) malloc(sizeof(struct event)); e->car = i; e->type = RDY; e->time = cars[i].time_arr_base; e->x = cars[i].x_base; e->y = cars[i].y_base; insert_event(e); cars[i].time_arr_base = -1; cars[i].consec_trip_count = 0; cars[i].ready = TRUE; // Now that the trip is completed cars[i].x_start = -1; cars[i].y_start = -1; cars[i].time_start = -1; } } // Return the events p1 = due_events; list = ec_nil(); if(debug_level >= 1){ if(p1){ printf("SenseExo: Due event at time %d:\n", curr_time); } else{ printf("SenseExo: No due event at time %d\n", curr_time); printf("\n"); } } while(p1){ if(debug_level >= 1){ if(p1->type == RQT){ printf(" - Request I(%d, %d) at %d \n", \ p1->x, p1->y, p1->time); } else if(p1->type == ARR){ printf(" - Car %d reports arrival (%d, %d) at %d \n", \ p1->car, p1->x, p1->y, p1->time); } else if(p1->type == RDY){ printf(" - Car %d report ready (%d, %d) at %d \n", \ p1->car, p1->x, p1->y, p1->time); } printf("\n"); } w = ec_list(ec_long(p1->type), \ ec_list(ec_long(p1->time), \ ec_list(ec_long(p1->x), \ ec_list(ec_long(p1->y), \ ec_list(ec_long(p1->car), \ ec_nil()))))); list = ec_list(w, list); p2 = p1; p1 = p1->next; free(p2); } due_events = NULL; return ec_unify(ec_arg(1), list); } int sim_ask_position(){ pword arg; double num; int c, t, delta_t; struct coord src, dst, endpoint; arg = ec_arg(1); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; c = (int)num; // Car number arg = ec_arg(2); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; t = (int)num; // Time // // If communication fails, the answer about the location of the car // is (-1, -1), which signifies "unclear". Otherwise, more works is // needed before the simulated current location of the car can be // returned. // if (comm_fail_poss(c, t) && \ (((double) rand() / (double)RAND_MAX) < comm_fail_rate)) { ec_unify(ec_arg(3), ec_long((long) -1)); ec_unify(ec_arg(4), ec_long((long) -1)); curr_time = t; return PSUCCEED; } // // Depends on which leg of the trip the car is in, its location // is determined differently // if(cars[c].time_start < 0){ // At base endpoint.x = cars[c].x_base; endpoint.y = cars[c].y_base; } else if((t > cars[c].time_start) && (t <= cars[c].time_arr_hosp)){ // First Leg: To inc src.x = cars[c].x_start; src.y = cars[c].y_start; dst.x = cars[c].x_inc; dst.y = cars[c].y_inc; delta_t = t - cars[c].time_start; endpoint = simu_drive_partial(c, src, dst, spb_emerg, spb_emerg_foreign, delta_t); } else if((t > cars[c].time_arr_inc) && (t <= cars[c].time_leave_inc)){ // At inc endpoint.x = cars[c].x_inc; endpoint.y = cars[c].y_inc; } else if((cars[c].time_arr_hosp > 0) && \ (t > cars[c].time_leave_inc) && (t <= cars[c].time_arr_hosp)){ // To hosp src.x = cars[c].x_inc; src.y = cars[c].y_inc; dst.x = cars[c].x_hosp; dst.y = cars[c].y_hosp; delta_t = t - cars[c].time_leave_inc; endpoint = simu_drive_partial(c, src, dst, spb_emerg, spb_emerg_foreign, delta_t); } else if((cars[c].time_arr_hosp > 0) && \ (t > cars[c].time_arr_hosp) && (t <= cars[c].time_leave_hosp)){ // At hosp endpoint.x = cars[c].x_hosp; endpoint.y = cars[c].y_hosp; } else if((cars[c].time_arr_hosp > 0) && \ (t > cars[c].time_leave_hosp) && (t <= cars[c].time_arr_base)){ // To base src.x = cars[c].x_hosp; src.y = cars[c].y_hosp; dst.x = cars[c].x_base; dst.y = cars[c].y_base; delta_t = t - cars[c].time_leave_hosp; endpoint = simu_drive_partial(c, src, dst, spb_norm, spb_norm_foreign, delta_t); } else if((cars[c].time_arr_hosp < 0) && \ (t > cars[c].time_leave_inc) && (t <= cars[c].time_arr_base)){ // To base src.x = cars[c].x_inc; src.y = cars[c].y_inc; dst.x = cars[c].x_base; dst.y = cars[c].y_base; delta_t = t - cars[c].time_leave_inc; endpoint = simu_drive_partial(c, src, dst, spb_norm, spb_norm_foreign, delta_t); } // Return the coords ec_unify(ec_arg(3), ec_long((long) endpoint.x)); ec_unify(ec_arg(4), ec_long((long) endpoint.y)); if(debug_level >= 1){ fprintf(stderr, "AskPosition: Car %d is at loc(%d, %d) at time %d\n", c, endpoint.x, endpoint.y, t); } // Move the time forward curr_time = t; return PSUCCEED; } int sim_ask_status(){ pword arg; double num; int c, t; arg = ec_arg(1); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; c = (int)num; // Car number arg = ec_arg(2); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; t = (int)num; // Time if(debug_level >= 2){ fprintf(stderr, "ask_status: time %d, car %d, time_start %d\n", curr_time, c, cars[c].time_start); } // // If communication fails, the answer will be -1, which // signifies "unknown". Otherwise, the answer is either 0 (ready), // or 1 (busy), depends on what the car is doing at time t // if (comm_fail_poss(c, t) && \ (((double) rand() / (double)RAND_MAX) < comm_fail_rate)) { ec_unify(ec_arg(3), ec_long((long) -1)); curr_time = t; if(debug_level >= 1){ printf("AskStatus: Car %d status unknown at time %d\n\n", c, t); } return PSUCCEED; } else{ ec_unify(ec_arg(3), ec_long((long) cars[c].ready)); curr_time = t; if(debug_level >= 1){ printf("AskStatus: Car %d status %d at time %d\n\n", c, cars[c].ready, t); } return PSUCCEED; } } int sim_print_stats(){ FILE *f; int late08_arr_count; int late11_arr_count; int arr_count; int i, cc; late08_arr_count = late08_delay_count + late08_travel_count + late08_both_count; late11_arr_count = late11_delay_count + late11_travel_count + late11_both_count; // How many car are still on their ways to the incident cc = 0; for(i = 1; i < car_count + 1; i++){ if(cars[i].time_arr_inc >= 0) cc++; } arr_count = request_count - cc; printf("\n"); printf("Simulation statistics:\n"); printf("---------------------\n"); printf("\n"); printf(" Total number of request: %d\n", request_count); printf(" Total number of arrivals: %d\n", arr_count); printf(" Total number of arrivals after 8 minutes: %d, in which:\n", late08_arr_count); printf(" %d are caused by long travel time.\n", late08_travel_count); printf(" %d are caused by delay in mobilization (ie, not enought cars).\n", late08_delay_count); printf(" %d are caused by both.\n", late08_both_count); printf(" Late percentage: %d \n", (int) (((double) late08_arr_count / (double) arr_count) * 100)); printf(" Total number of arrivals after 11 minutes: %d, in which:\n", late11_arr_count); printf(" %d are caused by long travel time.\n", late11_travel_count); printf(" %d are caused by delay in mobilization (ie, not enought cars).\n", late11_delay_count); printf(" %d are caused by both.\n", late11_both_count); printf(" Late percentage: %d \n", (int) (((double) late11_arr_count / (double) arr_count) * 100)); printf("\n"); f = fopen("statistics/stats.txt", "a"); fprintf(f, "%d\t", request_count); fprintf(f, "%d\t", arr_count); fprintf(f, "\t"); fprintf(f, "%d\t", late08_arr_count); fprintf(f, "%d\t", late08_travel_count); fprintf(f, "%d\t", late08_delay_count); fprintf(f, "%d\t", late08_both_count); fprintf(f, "%.2lf\t", (((double) late08_arr_count / (double) arr_count) * 100)); fprintf(f, "%.2lf\t", (((double) late08_travel_count / (double) arr_count) * 100)); fprintf(f, "%.2lf\t", (((double) late08_delay_count / (double) arr_count) * 100)); fprintf(f, "%.2lf\t", (((double) late08_both_count / (double) arr_count) * 100)); fprintf(f, "\t"); fprintf(f, "%d\t", late11_arr_count); fprintf(f, "%d\t", late11_travel_count); fprintf(f, "%d\t", late11_delay_count); fprintf(f, "%d\t", late11_both_count); fprintf(f, "%.2lf\t", (((double) late11_arr_count / (double) arr_count) * 100)); fprintf(f, "%.2lf\t", (((double) late11_travel_count / (double) arr_count) * 100)); fprintf(f, "%.2lf\t", (((double) late11_delay_count / (double) arr_count) * 100)); fprintf(f, "%.2lf\n", (((double) late11_both_count / (double) arr_count) * 100)); fclose(f); return PSUCCEED; } int sim_print_params(){ FILE *f; pword arg; double num; char *strategies[] = {"MANUAL", "AUTO", "OPTIMAL"}; int s; arg = ec_arg(1); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; s = (int)num; // Strategy used printf("\n\n\n%s - %d\n\n", strategies[s], request_rate); f = fopen("statistics/stats.txt", "a"); fprintf(f, "\n\n\n%s - %d\n\n", strategies[s], request_rate); fclose(f); return PSUCCEED; } int sim_print_info(){ FILE *f; time_t timer; char name[100]; int x; timer = time(NULL); x = gethostname(name, 100); printf("\n"); printf(" Simulation started on %s, %s", name, asctime(localtime(&timer))); printf(" Simulation Parameters:\n"); printf(" - CommFailRate = %lf\n", comm_fail_rate); printf(" - HospitalizeRate = %lf\n", hosp_rate); printf(" - DiagnosisTime = %d\n", diag_time); printf(" - UnloadingTime = %d\n", unload_time); printf(" - TirednessMarkupTime = %d\n", markup_time); printf(" - CrewRecoveryTime = %d\n", crew_recovery_time); printf(" - SPB Emerg Home = %d\n", spb_emerg); printf(" - SPB Normal Home = %d\n", spb_norm); printf(" - SPB Emerg Foreign = %d\n", spb_emerg_foreign); printf(" - SPB Normal Foreign = %d\n", spb_norm_foreign); printf("\n"); printf("---------------------------------------------------------------------\n"); printf("\n"); f = fopen("statistics/stats.txt", "a"); fprintf(f, "\n"); fprintf(f, " Simulation started on %s, %s.\n", name, asctime(localtime(&timer))); fprintf(f, " Simulation Parameters:\n"); fprintf(f, " - CommFailRate = %lf\n", comm_fail_rate); fprintf(f, " - HospitalizeRate = %lf\n", hosp_rate); fprintf(f, " - DiagnosisTime = %d\n", diag_time); fprintf(f, " - UnloadingTime = %d\n", unload_time); fprintf(f, " - TirednessMarkupTime = %d\n", markup_time); fprintf(f, " - CrewRecoveryTime = %d\n", crew_recovery_time); fprintf(f, " - SPB Emerg Home = %d\n", spb_emerg); fprintf(f, " - SPB Normal Home = %d\n", spb_norm); fprintf(f, " - SPB Emerg Foreign = %d\n", spb_emerg_foreign); fprintf(f, " - SPB Normal Foreign = %d\n", spb_norm_foreign); fprintf(f, "\n"); fprintf(f, "---------------------------------------------------------------------\n"); fprintf(f, "\n"); fclose(f); return PSUCCEED; } int sim_debug(){ pword arg; double num; int car; struct coord src, dst; double t; struct coord endpoint; arg = ec_arg(1); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; car = (int)num; arg = ec_arg(2); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; src.x = (int)num; arg = ec_arg(3); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; src.y = (int)num; arg = ec_arg(4); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; dst.x = (int)num; arg = ec_arg(5); if (ec_get_double(arg, &num) != PSUCCEED) return PFAIL; dst.y = (int)num; t = simu_drive_full(car, src, dst, spb_emerg, spb_emerg_foreign); endpoint = simu_drive_partial(car, src, dst, spb_emerg, spb_emerg_foreign, 300); return PSUCCEED; } // ------------------------------------------------------------ // Helper and Util Functions // ------------------------------------------------------------ int next_event(){ int i; int min; min = next_request; for(i = 1; i < car_count + 1; i++){ // First relevant time point: // Arrival at incident if((cars[i].time_arr_inc > curr_time) && \ (min > cars[i].time_arr_inc)){ min = cars[i].time_arr_inc; } // Second relevant time point: // Ready (after onsite diag or after unloading) if(cars[i].time_arr_hosp < 0){ // Skip hospital if((cars[i].time_leave_inc > curr_time) && \ (min > cars[i].time_leave_inc)){ min = cars[i].time_leave_inc; } } else{ // Go to hosp if((cars[i].time_leave_hosp > curr_time) && \ (min > cars[i].time_leave_hosp)){ min = cars[i].time_leave_hosp; } } // Third relevant time point: // Ready at the base if((cars[i].time_arr_base > curr_time) && \ (min > cars[i].time_arr_base)){ min = cars[i].time_arr_base; } } return min; } void insert_event(struct event *e){ struct event *tmp, *tmp1; if (due_events == NULL){ e->next = NULL; due_events = e; return; } if (due_events->time < e->time){ e->next = due_events; due_events = e; return; } tmp = due_events; while ((tmp->time < e->time) && (tmp->next)){ tmp1 = tmp; tmp = tmp->next; } if (tmp->time > e->time){ // Insert on the left e->next = tmp; tmp1->next = e; } else{ // Insert on the right e->next = tmp->next; tmp->next = e; } return; } int distance(int x1, int y1, int x2, int y2){ return abs(x2 - x1) + abs(y2 - y1); } void gen_next_request(){ int reg; double randnum; int i; // The time next_request += gsl_ran_poisson(r, (double) request_rate); // The region randnum = rand()/(RAND_MAX+1.0); for(i = 1; i < region_count + 1; i++){ if(randnum < ((double) i / (double) region_count)){ reg = i; break; } } // The coordinates // (MIN + (int) ((MAX - MIN) * rand() / RAND_MAX)) request_x = regions[reg].x_botleft + \ (int) ((double) (regions[reg].x_topright - regions[reg].x_botleft) * \ rand() / RAND_MAX); request_y = regions[reg].y_botleft + \ (int) ((double) (regions[reg].y_topright - regions[reg].y_botleft) * \ rand() / RAND_MAX); // Incidents can not occur at a base station and a hosp while(is_a_base(request_x, request_y) || is_a_hosp(request_x, request_y)){ request_x = regions[reg].x_botleft + \ (int) ((double) (regions[reg].x_topright - regions[reg].x_botleft) * \ rand() / RAND_MAX); request_y = regions[reg].y_botleft + \ (int) ((double) (regions[reg].y_topright - regions[reg].y_botleft) * \ rand() / RAND_MAX); } pending_request_count[request_x][request_y]++; if(debug_level >= 2){ fprintf(stderr, "gen_next_request: rand = %lf, reg = %d\n", randnum, reg); fprintf(stderr, "gen_next_request: %d %d\n", request_x, request_y); } } void simu_drive(int x1, int y1, int x2, int y2, int t, int spb, int *x, int *y){ int block_count; int xx, yy; // How many block should have has been covered during this time period t block_count = t / spb; xx = x1; yy = y1; while(block_count > 0){ if(valid_coord(a_step_closer(xx, x2), yy)){ xx = a_step_closer(xx, x2); block_count--; } if(valid_coord(xx, a_step_closer(yy, y2))){ yy = a_step_closer(yy, y2); block_count--; } } *x = xx; *y = yy; } // // simu_drive_full() // // Return the duration of the full trip from src to dst. // /* int simu_drive_full(int car, struct coord src, struct coord dst, int spb_home, int spb_foreign){ int x, y, xx, yy; double t = 0; char next_move = 'H'; if(debug_level >= 2){ fprintf( \ stderr, \ "simu_drive_full: Simulating the trip from (%d, %d) to (%d, %d) for car %d:\n", \ src.x, src.y, dst.x, dst.y, car \ ); } x = src.x; y = src.y; while(x != dst.x || y != dst.y){ xx = a_step_closer(x, dst.x); yy = a_step_closer(y, dst.y); if(in_home_region(car, x, yy) || in_home_region(car, xx, y)){ if(next_move == 'H'){ if(in_home_region(car, xx, y)){ x = xx; t = t + rand_gaussian_duration(spb_home); } next_move = 'V'; } else{ if(in_home_region(car, x, yy)){ y = yy; t = t + rand_gaussian_duration(spb_home); } next_move = 'H'; } if(debug_level >= 2){ fprintf(stderr, " reached (%d, %d), using home speed, at %lf\n", x, y, t); } } else{ if(next_move == 'H'){ if(valid_coord(xx, y)){ x = xx; t = t + rand_gaussian_duration(spb_foreign); } next_move = 'V'; } else{ if(valid_coord(x, yy)){ y = yy; t = t + rand_gaussian_duration(spb_foreign); } next_move = 'H'; } if(debug_level >= 2){ fprintf(stderr, " reached (%d, %d), using foreign speed, at %lf\n", x, y, t); } } } return (int) t; } */ int simu_drive_full(int car, struct coord src, struct coord dst, int spb_home, int spb_foreign){ int x, y, xx, yy; double t = 0; char next_move = 'H'; if(debug_level >= 2){ fprintf( \ stderr, \ "simu_drive_full: Simulating the trip from (%d, %d) to (%d, %d) for car %d:\n", \ src.x, src.y, dst.x, dst.y, car \ ); } x = src.x; y = src.y; while(x != dst.x || y != dst.y){ xx = a_step_closer(x, dst.x); yy = a_step_closer(y, dst.y); if(next_move == 'H'){ if(valid_coord(xx, y)){ x = xx; if(in_home_region(car, xx, y)) t = t + rand_gaussian_duration(spb_home); else t = t + rand_gaussian_duration(spb_foreign); } next_move = 'V'; } else{ if(valid_coord(x, yy)){ y = yy; if(in_home_region(car, x, yy)) t = t + rand_gaussian_duration(spb_home); else t = t + rand_gaussian_duration(spb_foreign); } next_move = 'H'; } if(debug_level >= 2){ fprintf(stderr, " reached (%d, %d) at %lf\n", x, y, t); } } return (int) t; } // // simu_drive_partial() // // Return the end point of the t seconds partial trip from src to dst // /* struct coord simu_drive_partial(int car, struct coord src, struct coord dst, int spb_home, int spb_foreign, int t){ int x, y, xx, yy; double elapsed = 0; char next_move = 'H'; struct coord endpoint; if(debug_level >= 2){ fprintf( \ stderr, \ "simu_drive_partial: Simulating the %d seconds partial trip from (%d, %d) to (%d, %d) for car %d:\n", \ t, src.x, src.y, dst.x, dst.y, car \ ); } x = src.x; y = src.y; while((elapsed < t) && (x != dst.x || y != dst.y)){ xx = a_step_closer(x, dst.x); yy = a_step_closer(y, dst.y); if(in_home_region(car, x, yy) || in_home_region(car, xx, y)){ if(next_move == 'H'){ if(in_home_region(car, xx, y)){ x = xx; elapsed = elapsed + rand_gaussian_duration(spb_home); } next_move = 'V'; } else{ if(in_home_region(car, x, yy)){ y = yy; elapsed = elapsed + rand_gaussian_duration(spb_home); } next_move = 'H'; } if(debug_level >= 2){ fprintf(stderr, " reached (%d, %d), using home speed, at %lf\n", x, y, elapsed); } } else{ if(next_move == 'H'){ if(valid_coord(xx, y)){ x = xx; elapsed = elapsed + rand_gaussian_duration(spb_foreign); } next_move = 'V'; } else{ if(valid_coord(x, yy)){ y = yy; elapsed = elapsed + rand_gaussian_duration(spb_foreign); } next_move = 'H'; } if(debug_level >= 2){ fprintf(stderr, " reached (%d, %d), using foreign speed, at %lf\n", x, y, elapsed); } } } endpoint.x = x; endpoint.y = y; return endpoint; } */ struct coord simu_drive_partial(int car, struct coord src, struct coord dst, int spb_home, int spb_foreign, int t){ int x, y, xx, yy; double elapsed = 0; char next_move = 'H'; struct coord endpoint; if(debug_level >= 2){ fprintf( \ stderr, \ "simu_drive_partial: Simulating the %d seconds partial trip from (%d, %d) to (%d, %d) for car %d:\n", \ t, src.x, src.y, dst.x, dst.y, car \ ); } x = src.x; y = src.y; while((elapsed < t) && (x != dst.x || y != dst.y)){ xx = a_step_closer(x, dst.x); yy = a_step_closer(y, dst.y); if(next_move == 'H'){ if(valid_coord(xx, y)){ if(in_home_region(car, xx, y)) elapsed = elapsed + rand_gaussian_duration(spb_home); else elapsed = elapsed + rand_gaussian_duration(spb_foreign); x = xx; } next_move = 'V'; } else{ if(valid_coord(x, yy)){ if(in_home_region(car, x, yy)) elapsed = elapsed + rand_gaussian_duration(spb_home); else elapsed = elapsed + rand_gaussian_duration(spb_foreign); y = yy; } next_move = 'H'; } if(debug_level >= 2){ fprintf(stderr, " reached (%d, %d) at %lf\n", x, y, elapsed); } } endpoint.x = x; endpoint.y = y; return endpoint; } int max_blocks_to_border(int car, struct coord src, struct coord dst){ int x, y, xx, yy; int i = 0; char next_move = 'H'; x = src.x; y = src.y; while(TRUE){ xx = a_step_closer(x, dst.x); yy = a_step_closer(y, dst.y); if(!(in_home_region(car, x, yy) || in_home_region(car, xx, y))){ break; } else{ if(next_move == 'H'){ if(in_home_region(car, xx, y)){ x = xx; i++; } next_move = 'V'; } else{ if(in_home_region(car, x, yy)){ y = yy; i++; } next_move = 'H'; } } } if(debug_level >= 2){ fprintf( \ stderr, \ "max_blocks_to_border: car %d, src(%d, %d), dst(%d, %d), lastpos(%d,%d), maxblock %d\n", \ car, src.x, src.y, dst.x, dst.y, x, y, i \ ); } return i; } int a_step_closer(int source, int dest){ // Give in_home_region() and valid_coord() a hint if(source == dest) return -1; if(source < dest) return source + 1; else return source - 1; } int valid_coord(int x, int y){ int i; for(i = 1; i < region_count + 1; i++){ if(x >= regions[i].x_botleft && x <= regions[i].x_topright && \ y >= regions[i].y_botleft && y <= regions[i].y_topright ){ return TRUE; } } return FALSE; } int in_home_region(int c, int x, int y){ // // Note: // in_home_region(c, x, y) implies valid_coord(x, y) // int i; int reg = -1; // Find the home region of the car for(i = 1; i < region_count + 1; i++){ // DBG // printf("reg %d: %d, %d, %d, %d, %d, %d\n", i, regions[i].x_botleft, regions[i].x_topright, regions[i].y_botleft, regions[i].y_topright, cars[c].x_base, cars[c].y_base); // fflush(stdout); if(regions[i].x_botleft <= cars[c].x_base && \ cars[c].x_base <= regions[i].x_topright && \ regions[i].y_botleft <= cars[c].y_base && \ cars[c].y_base <= regions[i].y_topright){ reg = i; break; } } if(reg < 1 || reg > region_count){ fprintf(stderr, "InHomeRegion: Invalid home region for a car found\n"); fprintf(stderr, "InHomeRegion: car=%d, x=%d, y=%d, foundreg=%d\n", c, x, y, reg); fprintf(stderr, "InHomeRegion: Going into infinite loop.\n"); while(TRUE){} } // Does loc(x, y) belong to reg if(regions[reg].x_botleft <= x && \ x <= regions[reg].x_topright && \ regions[reg].y_botleft <= y && \ y <= regions[reg].y_topright){ return TRUE; } else{ return FALSE; } } int is_a_base(int x, int y){ int i; for(i = 1; i < base_count + 1; i++){ if(x == bases[i].x && y == bases[i].y){ return TRUE; } } return FALSE; } int is_a_hosp(int x, int y){ int i; for(i = 1; i < hosp_count + 1; i++){ if(x == hosps[i].x && y == hosps[i].y){ return TRUE; } } return FALSE; } double rand_gaussian_duration(int mean){ double x = -1; while(x < 0){ x = gsl_ran_gaussian(r, 1) + mean; } return x; } int comm_fail_poss(int c, int t){ // // Comm can NOT fail if the car has not be mobilized OR, it has just // been momentarily mobilized from the base // if ((cars[c].time_start < 0) || \ (cars[c].x_start == cars[c].x_base && \ cars[c].y_start == cars[c].y_base && \ cars[c].time_start == t)) { return FALSE; } return TRUE; } struct coord local_hosp(struct coord loc){ int i; struct coord hosp; int reg; reg = containing_region(loc); for (i = 1; i < hosp_count + 1; i++){ hosp.x = hosps[i].x; hosp.y = hosps[i].y; if(containing_region(loc) == containing_region(hosp)){ return hosp; } } fprintf(stderr, "local_hosp: Can't find local hosp for %d %d\n", loc.x, loc.y); hosp.x = -1; hosp.y = -1; return hosp; } int containing_region(struct coord loc){ int i; for(i = 1; i < region_count + 1; i++){ if(loc.x >= regions[i].x_botleft && loc.x <= regions[i].x_topright && \ loc.y >= regions[i].y_botleft && loc.y <= regions[i].y_topright ){ return i; } } fprintf(stderr, "containing_region: An invalid coord was given: %d, %d\n", loc.x, loc.y); return -1; }