import <h7> // enable this macro for the benchmark // #define BENCH module ferry { constant int BENCH_SAMPLES = 100; constant double SIM_DURATION = 24.0*60.0*7.0; constant double HARBOR_DISTANCE = 10.0; constant double FERRY_TIMEOUT = 5.0; constant int FERRY_CAPACITY = 5; constant int FERRY_COUNT = 2; constant int HARBOR_COUNT = 4; random_variable ferry_cargo_len; random_variable ferry_load_time; random_variable car_wait_time; passive class Car(double duration) { double arrival_time = time; double load_duration = duration; } class Pier { rn_stream rng; set(Car) ranked FIFO landing_site; actions { double load_duration; forever { advance rv_expo(rng, 10.0); do load_duration = rv_normal(rng, 0.5, 0.2); while (load_duration < 0.0); place new Car(load_duration) into landing_site; } } } class Ferry(int _capacity, double _timeout, double _travel_time) { pointer(Car) cargo[_capacity]; double timeout = _timeout; double travel_time = _travel_time; set(Pier) ranked FIFO piers; pointer(Pier) pier; pointer(Car) car; actions { double begin_loading, begin_waiting; int len = 0; int i; forever { for (pier = each Pier in piers) { // unload the cars for (i = 1; i <= len; ++i) { advance cargo[i]->load_duration; } len = 0; begin_loading = time; // wait until new cars arrive or a timeout occurs while (len < array_upper_bound(cargo, 1)) { begin_waiting = time; wait until pier->landing_site.size > 0 || time >= begin_waiting + timeout; car = first Car in pier->landing_site; if (car != NULL) { // a car arrived in time remove car from pier->landing_site; tabulate car_wait_time = time - car->arrival_time; advance car->load_duration; cargo[++len] = car; } else { // the timeout has been triggered break; } } tabulate ferry_load_time = time - begin_loading; tabulate ferry_cargo_len = len; // travel to the next harbor advance travel_time; } } } } procedure ferry(double duration, int ferries, int harbors) { pointer(Pier) ports[harbors]; pointer(Ferry) ferry; pointer(Car) car; int i, j; // create all of the harbors for (i = 1; i <= harbors; ++i) { ports[i] = new Pier; activate ports[i]; } // create all of the ferries for (i = 1; i <= ferries; ++i) { ferry = new Ferry(FERRY_CAPACITY, FERRY_TIMEOUT, HARBOR_DISTANCE); for (j = 1; j <= harbors; ++j) place ports[(i + j - 2) % harbors + 1] into ferry->piers; activate ferry; } // await the end of the simulation advance duration; // take cars into account that weren't picked up by a ferry for (i = 1; i <= harbors; ++i) { for (car = each Car in ports[i]->landing_site) { tabulate car_wait_time = time - car->arrival_time; } } } procedure main(int argc, string(*) argv[*]) { // interpret the optional command line arguments for simulation // duration and number of timed runs in this batch double sim_duration = SIM_DURATION; int bench_samples = BENCH_SAMPLES; if (argc > 1) { read string = argv[1] (sim_duration); if (argc > 2) { read string = argv[2] (bench_samples); } } #ifdef BENCH random_variable samples; double real_start, real_end; int i; // remove the random variable from the system as to prevent resets on 'clear system' remove &samples from random_variable_set; for (i = 1; i <= bench_samples; ++i) { real_start = real_time(); ferry(sim_duration, FERRY_COUNT, HARBOR_COUNT); real_end = real_time(); tabulate samples = real_end - real_start; empty rn_stream_set; clear system; } print(sample_sum(samples)) "_.________"; #else ferry(sim_duration, FERRY_COUNT, HARBOR_COUNT); report system; #endif } }