A set of benchmarks to compare a new prototype MiniZinc implementation
1%----------------------------------------------------------------------------% 2%----------------------------------------------------------------------------% 3% 4% We have n trains moving along a single track with m stations. There is a 5% non-zero constant flow of passengers arriving at all but the first and last 6% station who wish to travel to the final station. Trains are originally 7% scheduled so that they collect the passengers and drop them at the final 8% station. To this original schedule a disruption is introduced whereby a train 9% is delayed. Each of the trains (at the time of the delay) has knowledge of the 10% duration of the delay. The objective is to reschedule the trains to minimize 11% the average travel time of the passengers. Trains are not able to overtake 12% preceding trains, however they do have the option to 13% skip a station and wait longer at a station to collect more passengers. 14 15%----------------------------------------------------------------------------% 16%----------------------------------------------------------------------------% 17 18%include "globals.mzn"; 19 20int : n; 21int : m; 22 23int : maxTime; 24 250..maxTime : delayTime; 261..n : delayTrain; 270..maxTime : delayDuration; 28 29array [1..m-1] of 0..maxTime : distance; 30 31array [1..n, 1..m] of 0..maxTime : scheduledArrival; 32array [1..n, 1..m] of 0..maxTime : scheduledDeparture; 33 34array [1..m] of 0..maxTime : passengerStart; 35array [1..m] of 0..maxTime : passengerStop = [scheduledDeparture[n,j] | j in 1..m]; 36array [1..m] of int : passengerFlow; 37 38array [1..n, 1..m] of var 0..maxTime : departure; 39array [1..n, 1..m] of var 0..maxTime : arrival; 40 41array [1..n] of var 0..maxTime : finalArrival = [ arrival[i,m] | i in 1..n ]; 42 43array [1..n, 1..m] of var 0..maxTime : sigmaLower; 44array [1..n, 1..m] of var 0..maxTime : sigmaUpper; 45 46int : capacity; 47 48array [1..n, 1..m] of var 0..capacity : collect; 49array [1..n, 1..m] of var 0..capacity : load; 50 51% All trains "arrive" at the first station at time 0. 52constraint forall (i in 1..n) 53 (arrival[i,1] = 0); 54% ... and "depart" from the last station as soon as they arrive there. 55constraint forall (i in 1..n) 56 (departure[i,m] = arrival[i,m]); 57 58% Before the delay, everything runs to schedule. 59constraint forall (i in 1..n, j in 1..m-1) 60 (if scheduledDeparture[i,j] <= delayTime 61 then departure[i,j] = scheduledDeparture[i,j] 62 else true 63 endif); 64 65% If the train is in motion, then the arrival of the 66% delayed train is at least the departure time at the previous station 67% plus the ordinary travel time plus the duration of the delay. 68int : destinationWhenDelayed = min([j | j in 1..m where scheduledDeparture[delayTrain,j] > delayTime]); 69constraint if destinationWhenDelayed > 1 70 then if delayTime < scheduledDeparture[delayTrain,destinationWhenDelayed-1] + distance[destinationWhenDelayed-1] 71 then arrival[delayTrain,destinationWhenDelayed] >= 72 departure[delayTrain,destinationWhenDelayed-1] + delayDuration + distance[destinationWhenDelayed-1] 73 else true 74 endif 75 else true 76 endif; 77% The train's next departure is at least the delay time plus the delay 78% duration. 79constraint departure[delayTrain, destinationWhenDelayed] >= delayTime + delayDuration; 80 81% Trains depart after they arrive. 82constraint forall (i in 1..n, j in 1..m) 83 (departure[i,j] >= arrival[i,j]); 84 85% Trains never leave earlier than scheduled. 86constraint forall (i in 1..n, j in 1..m-1) 87 (departure[i,j] >= scheduledDeparture[i,j]); 88 89% There is a minimum travel time between stations. 90constraint forall (i in 1..n, j in 1..m-1) 91 (arrival[i,j+1] >= departure[i,j] + distance[j]); 92 93% At station 1, trains leave in order. 94constraint forall (i in 1..n-1) 95 (departure[i,1] < departure[i+1,1]); 96% At most one train dwelling at a station at a given time. 97constraint forall (i in 1..n-1, j in 2..m-1) 98 (departure[i,j] <= arrival[i+1,j]-2); 99 100% The sigma values partition time at each station. 101constraint forall (i in 1..n, j in 1..m) 102 (sigmaLower[i,j] <= sigmaUpper[i,j]); 103 104% For the first and last trains, the sigma values are equal to the 105% extreme times of passenger arrivals. 106constraint forall (j in 2..m-1) 107 ((sigmaLower[1,j] = passengerStart[j]) 108 /\ (sigmaUpper[n,j] = scheduledDeparture[n,j])); 109% The sigma values join together. 110constraint forall (i in 1..n-1, j in 1..m) 111 (sigmaUpper[i,j] = sigmaLower[i+1,j]); 112 113% You can't pick up people after you leave. 114constraint forall (i in 1..n-1, j in 1..m-1) 115 (sigmaUpper[i,j] <= departure[i,j]); 116constraint forall (j in 1..m-1) 117 (sigmaUpper[n,j] <= departure[n,j]); 118 119% Defines collect and load variables. 120constraint forall (i in 1..n, j in 1..m) 121 (collect[i,j] = (sigmaUpper[i,j]-sigmaLower[i,j])*passengerFlow[j]); 122 123constraint forall (i in 1..n) (load[i,1] = collect[i,1]); 124constraint forall (i in 1..n, j in 2..m) 125 (load[i,j] = load[i,j-1] + collect[i,j]); 126 127% If a train picks anyone up, then it must pick 128% everyone up (until it gets full). 129constraint forall (i in 1..n, j in 1..m-1) 130 (sigmaUpper[i,j] > sigmaLower[i,j] -> 131 ((sigmaUpper[i,j] = departure[i,j]) \/ 132 (sigmaUpper[i,j] = scheduledDeparture[n,j]) \/ 133 (load[i,j] + bool2int(sigmaUpper[i,j] < scheduledDeparture[n,j])*passengerFlow[j] > capacity))); 134 135% Boarding time. 136constraint forall (i in 1..n, j in 2..m) 137 (((capacity-load[i,j-1] < 100) -> (collect[i,j] <= dwell[i,j]*20)) /\ 138 ((capacity-load[i,j-1] >= 100) -> (collect[i,j] <= dwell[i,j]*50))); 139% (Redundant for j>=2 (but necessary for j=1)) 140constraint forall (i in 1..n, j in 1..m) 141 (collect[i,j] <= (departure[i,j]-arrival[i,j])*50); 142 143array [1..n, 1..m] of var 0..maxTime : dwell; 144constraint forall (i in 1..n, j in 1..m) (dwell[i,j] = departure[i,j] - arrival[i,j]); 145 146int: objective_min = lb(sum(i in 1..n)(load[i,m]*arrival[i,m])); 147int: objective_max = ub(sum(i in 1..n)(load[i,m]*arrival[i,m])); 148var objective_min..objective_max: objective = sum(i in 1..n)(load[i,m]*arrival[i,m]); 149 150solve 151 :: seq_search([ 152 int_search( 153 [arrival[i,m-j+1] | j in 1..m, i in 1..n] ++ 154 [departure[i,m-j+1] | j in 1..m, i in 1..n] ++ 155 [sigmaUpper[i,m-j+1] | j in 1..m, i in 1..n] ++ 156 [sigmaLower[i,m-j+1] | j in 1..m, i in 1..n], 157 input_order, indomain_min, complete 158 ), 159 int_search( 160 array1d(1..n*m, collect) ++ array1d(1..n*m, load) ++ array1d(1..n*m, dwell), 161 first_fail, indomain_min, complete 162 ) 163 ]) 164 minimize objective; 165 166output [ 167 "arrival = array2d(1..", show(n), ", 1..", show(m), ", ", show(arrival), ");\n", 168 "departure = array2d(1..", show(n), ", 1..", show(m), ", ", show(departure), ");\n", 169 "sigmaLower = array2d(1..", show(n), ", 1..", show(m), ", ", show(sigmaLower), ");\n", 170 "sigmaUpper = array2d(1..", show(n), ", 1..", show(m), ", ", show(sigmaUpper), ");\n", 171 "collect = array2d(1..", show(n), ", 1..", show(m), ", ", show(collect), ");\n", 172 "load = array2d(1..", show(n), ", 1..", show(m), ", ", show(load), ");\n", 173 "dwell = array2d(1..", show(n), ", 1..", show(m), ", ", show(dwell), ");\n", 174 "constraint objective = ", show(objective), ";\n" 175]; 176