Source

RAS2012 / dispatching.mod

Full commit
# models of RAS 2012 problem

param M := 1440;
# define a graph
param N;    # number of nodes
set V := 0..N-1;
set E within {r in V, s in V: r < s};
set W := {r in V, s in V: (s,r) in E};
set A := E union W;
# MOW window
set F within E;
param mowstart {F};
param mowend {F};
# train parameters
set T;  # set of trains
param trainname {T} symbolic;
param traintype {T} symbolic;
param entrytime {T};
param orig {T};
param dest {T};
param traindir {T} symbolic;
param speedmult {T};
param trainleng {T};
param tonage {T};
param hazard {T};
param initdelay {T};
param termtime {T};
param twtstart {i in T} := termtime[i] - 60;
param twtend {i in T} := termtime[i] + 180;
param schedtime {T,V};
set I := {i in T: traindir[i] == "EASTBOUND"};
set J := {i in T: traindir[i] == "WESTBOUND"};
# track parameters
param maxspeedeast;
param maxspeedwest;
param maxspeedsl;
param maxspeedsw;
param edgetype {E} symbolic;
param edgeleng {E};
param tracktype {(r,s) in A} symbolic := if r < s then edgetype[r,s] else edgetype[s,r];
param trackleng {(r,s) in A} := if r < s then edgeleng[r,s] else edgeleng[s,r];
param trainspeed {i in T, (r,s) in A} :=
     if r < s and edgetype[r,s] == "0"  then 1/60 * speedmult[i] * maxspeedeast
else if r < s and edgetype[r,s] == "S"  then 1/60 * speedmult[i] * maxspeedsl
else if r < s and edgetype[r,s] == "SW" then 1/60 * speedmult[i] * maxspeedsw
else if r > s and edgetype[s,r] == "0"  then 1/60 * speedmult[i] * maxspeedwest
else if r > s and edgetype[s,r] == "S"  then 1/60 * speedmult[i] * maxspeedsl
else if r > s and edgetype[s,r] == "SW" then 1/60 * speedmult[i] * maxspeedsw;

# if i immediately precedes j on track (r,s)
var x {i in T, j in T, (r,s) in E: i <> j} binary;
# if i travel from r to s on track (r,s)
var f {i in T, (r,s) in A} binary;
# if i uses track (r,s) in E
var y {i in T, (r,s) in E} binary;
# if i go through track (r,s) before MOW
var g {i in T, (r,s) in F} binary;
# the arrival time on track (r,s)
var a {i in T, (r,s) in E} >= 0;
# the departure time on track (r,s)
var d {i in T, (r,s) in E} >= 0;
# the waiting time on track (r,s)
var b {i in T, (r,s) in E} >= 0;

# terminal want time deviance
set LAST := {i in T, (r,s) in E: dest[i] == s and i in I or dest[i] == r and i in J};
var early {LAST} >= 0;
var late  {LAST} >= 0;

# objective
minimize total_cost:
    # universal delay cost
    sum {i in T, (r,s) in E} b[i,r,s] + 
    # terminal want time deviance
    sum {(i,r,s) in LAST} 75/60 * (early[i,r,s] + late[i,r,s]);

# flow conservation constraints
# EASTBOUND
s.t. flow_cons_east {i in I, n in V: n <> orig[i] and n <> dest[i]}: 
    sum {(r,s) in E: s == n} f[i,r,s] = sum {(u,v) in E: u == n} f[i,u,v];
s.t. flow_orig_east {i in I}: sum {(r,s) in E: r == orig[i]} f[i,r,s] = 1;
s.t. flow_dest_east {i in I}: sum {(r,s) in E: s == dest[i]} f[i,r,s] = 1;
# WESTBOUND
s.t. flow_cons_west {j in J, n in V: n <> orig[j] and n <> dest[j]}: 
    sum {(r,s) in W: s == n} f[j,r,s] = sum {(u,v) in W: u == n} f[j,u,v];
s.t. flow_orig_west {j in J}: sum {(r,s) in W: r == orig[j]} f[j,r,s] = 1;
s.t. flow_dest_west {j in J}: sum {(r,s) in W: s == dest[j]} f[j,r,s] = 1;
# toal track flow
s.t. flow_total {i in T, (r,s) in E}: y[i,r,s] = f[i,r,s] + f[i,s,r];
# traffic flow and order
s.t. flow_row {j in T, (r,s) in E}: sum {i in T: i <> j} x[i,j,r,s] <= y[j,r,s];
s.t. flow_col {j in T, (r,s) in E}: sum {k in T: k <> j} x[j,k,r,s] <= y[j,r,s];
s.t. flow_sum {(r,s) in E}: 
    sum {i in T, j in T: i <> j} x[i,j,r,s] = sum {k in T} y[k,r,s] - 1;
# kinetic equations
s.t. train_stop {i in T, (r,s) in E}: 
    b[i,r,s] = d[i,r,s] - a[i,r,s] - trackleng[r,s]/trainspeed[i,r,s];
s.t. train_move {i in T, (r,s) in E}: b[i,r,s] >= (y[i,r,s] - 1) * M;
# block signal sections
# var mileage {I,A};
# s.t. train_mileage {i in I, (s,t) in A, r in V: (r,s) in A}: 
#     mileage[i,s,t] = mileage[i,r,s] + trackleng[s,t] * y[i,s,t];
# mileage[i,v] > mileage[i,s]
# mileage[i,v] < mileage[i,s] + trainleng[i]
s.t. train_control {i in T, j in T, (r,s) in E: i <> j}: 
    d[i,r,s] + trainleng[i] / trainspeed[i,r,s] <= a[j,r,s] + (1 - x[i,j,r,s]) * M;
# MOW windows
s.t. mow_early {i in T, (r,s) in F}: d[i,r,s] <= mowstart[r,s] + (1 - g[i,r,s]) * M;
s.t. mow_later {i in T, (r,s) in F}: a[i,r,s] >= mowstart[r,s] - g[i,r,s] * M;
# terminal want time deviance
s.t. terminal_early {(i,r,s) in LAST}: early[i,r,s] >= twtstart[i] - a[i,r,s] + (1 - y[i,r,s]) * M;
s.t. terminal_late  {(i,r,s) in LAST}: late[i,r,s]  >= a[i,r,s] - twtend[i] + (1 - y[i,r,s]) * M;