Skip to content

Instantly share code, notes, and snippets.

@c3c
Created March 26, 2013 14:55
Show Gist options
  • Save c3c/5245985 to your computer and use it in GitHub Desktop.
Save c3c/5245985 to your computer and use it in GitHub Desktop.
Working SD
/*********************************************
* OPL 12.5 Model
* Author: crash
* Creation Date: Mar 6, 2013 at 3:33:35 PM
*********************************************/
using CP;
// Nodes
tuple node { string name; float lat; float lon; int x; int y; int tmin; int tmax; }
{node} AllNodes = ...;
int N = card(AllNodes);
range nodes = 0..N-1;
// Edges
tuple edge {int i; int j;}
setof(edge) AllEdges = { <i,j> | i,j in nodes : i != j }; // not filtered!
setof(edge) OrderedEdges = { <i,j> | ordered i,j in nodes};
int Dist[OrderedEdges] = ...;
// Deliveries
tuple delivery {int destination; int from; int numpalettes;}
{delivery} Deliveries = ...;
// Remove superfluous thingies
sorted {int} clients = { d.from | d in Deliveries : d.numpalettes > 0 } union { d.destination | d in Deliveries : d.numpalettes > 0 };
sorted {int} cities = {0} union clients;
int numCities = card(cities);
int demand[t in cities] = sum (d in Deliveries : d.destination == t) d.numpalettes;
int outgoing[t in cities] = sum (d in Deliveries : d.from == t) d.numpalettes;
int orders[from in cities, dest in cities] = sum (d in Deliveries : d.from == from && d.destination == dest) d.numpalettes;
int tmin[t in cities] = item(AllNodes, t).tmin;
int tmax[t in cities] = item(AllNodes, t).tmax;
setof(edge) Edges = { <i,j> | i,j in cities : i != j }; // filtered! :)
//
//execute {
// writeln(AllEdges);
// writeln(tmin);
// writeln(tmax);
//}
// Camions
tuple camion {key int id;int capacity; int maxweight; int maxtime;}
{camion} Camions = ...;
// Travel time
int vitesse = 65; // km/h
int tempstrajet[<i,j> in OrderedEdges] = ftoi(round(Dist[<i,j>]/vitesse*60));
int tempsservice = 30;
// Decision variables
dvar boolean x[Edges,Camions];
dvar boolean y[Camions,cities];
dvar boolean takenby[Deliveries][Camions];
dvar int arrival[Camions][cities] in 1..numCities-1;
dvar int+ tarrival[Camions][cities];
dvar int+ quantity[cities][Camions];
//dexpr int r[w in cities][k in Camions] = sum (i in cities, j in cities : i!=j) ((y[k][i] + y[k][j] == 2 && arrival[k][i] <= arrival[k][w]) ? (orders[i][j] + orders[j][i]) : 0);
//sum(i in cities) (y[k][i] == 1 ? ((arrival[k][i] < arrival[k][j]) ? quantity[i][k] : 0) : 0);
//dvar interval timeofdelivery[i in clients][m] in i.tmin..i.tmax size 30;
edge E = <0,1>; // intermediary object
execute {
// cp.param.NoOverlapInferenceLevel = "Medium";
// cp.param.ElementInferenceLevel = "Low";
//cp.param.TemporalRelaxation = "Off";
cp.param.TimeMode = "ElapsedTime";
cp.param.TimeLimit = 20;
};
//tuple Subtour {
// int ssize;
// camion truck;
// int subtour[cities];
//};
//{Subtour} subtours = ...;
minimize sum (<i,j> in Edges, m in Camions) Dist[<minl(i,j), maxl(i,j)>]*x[<i,j>,m];
subject to {
forall (k in Camions, i in cities)
y[k][i] == (((sum(<i,j> in Edges) x[<i,j>][k]) + (sum(<j,i> in Edges) x[<j,i>][k])) > 0);
forall (k in Camions, j in cities)
(sum(i in cities : j!=i) x[<i,j>][k]) == y[k][j];
forall (k in Camions, j in cities)
(sum(i in cities : j!=i) x[<j,i>][k]) == y[k][j];
forall (d in Deliveries)
sum (k in Camions) takenby[d][k] >= 1;
forall (d in Deliveries, k in Camions)
(takenby[d][k] == 1) => (y[k][d.from] == 1 && y[k][d.destination] == 1);
// forall (i in clients, k in Camions)
// (quantity[i][k] >= 1) => y[k][i] == 1;
//
// forall (i in clients)
// ((demand[i] + outgoing[i]) >= 1) == (sum(k in Camions) y[k][i] >= 1);
// continuité
forall (p in cities, k in Camions)
((sum(i in cities : i!=p) x[<i,p>][k]) - (sum(j in cities : j!=p) x[<p,j>][k])) == 0;
forall (k in Camions, <i,j> in Edges : i!=0)
(x[<i,j>][k] == 1) => (arrival[k][i] + 1 == arrival[k][j]);
// For each client, the aggregated quantity of all trucks must match the demand
forall (i in cities)
sum (k in Camions, d in Deliveries : d.destination == i) takenby[d][k] * d.numpalettes == demand[i];
forall (d in Deliveries)
sum (k in Camions) takenby[d][k]*k.capacity >= d.numpalettes;
// forall (i in cities)
// sum(k in Camions) quantity[i][k] == demand[i];
//
// // The amount of palettes the truck is going to deliver must be inferior|equal to his capacity
// // (perhaps include dvar (c12)
// forall (k in Camions)
// sum(i in cities) quantity[i][k] <= k.capacity;
// respect timewindows
// forall(j in clients, k in Camions)
// (x[<0,j>][k] == 1) => (tarrival[k][j] >= (tempstrajet[<0,j>] + tmin[0]));
//
// forall (<i,j> in Edges : i!=0, k in Camions)
// (x[<i,j>][k] == 1) => ((tarrival[k][i] + tempstrajet[<minl(i,j), maxl(i,j)>] + (15 + 3*(quantity[i][k]))) <= tarrival[k][j]);
//
// min max timeframe for entry at client
// forall(i in cities, k in Camions)
// (y[k][i] ==1) => ((tmin[i] <= tarrival[k][i]) && (tarrival[k][i] <= tmax[i]));
// truck can't be longer than e.g. 12h on route
forall (m in Camions)
m.maxtime >= ((sum (<i,j> in Edges) x[<i,j>,m]*(tempstrajet[<minl(i,j),maxl(i,j)>]+tempsservice))-tempsservice);
// pickup is before delivery, by same truck
forall (d in Deliveries, m in Camions)
(takenby[d][m] == 1) => (arrival[m][d.from] <= arrival[m][d.destination]);
};
execute {
var unused = "We didn't use the following trucks: ";
var nUnused = 0;
for (var k in arrival) {
var num = 0;
var last = 0;
var timetotal = 0;
var str = "- Camion "+k.id+": 0 -> ";
for (var f = 1; f <= numCities-1; f++) {
for (var i in y[k]) {
if (y[k][i] == 1 && arrival[k][i] == f) {
if (!(last == 0 && i == 0)) {
E.i = Math.min(last, i);
E.j = Math.max(i, last);
timetotal += tempstrajet[E] + tempsservice;
last = i;
if (i!=0) {
str += i+" -> ";
}
}
num++;
}
}
}
timetotal -= tempsservice;
if (num > 0) {
writeln(str + "0 (total time: "+timetotal+")");
} else {
nUnused++;
unused += "c"+k.id + " ";
}
}
if (nUnused > 0) {
writeln(unused);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment