Skip to content

Instantly share code, notes, and snippets.

@c3c
Created March 22, 2013 17:30
Show Gist options
  • Save c3c/5223174 to your computer and use it in GitHub Desktop.
Save c3c/5223174 to your computer and use it in GitHub Desktop.
vrp with time window constraints (working)
/*********************************************
* OPL 12.5 Model
* Author: crash
* Creation Date: Mar 6, 2013 at 3:33:35 PM
*********************************************/
using CP;
// Nodes
tuple node { string name; 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 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 int arrival[Camions][cities] in 0..numCities-2;
dvar int+ tarrival[Camions][cities];
dvar int+ quantity[cities][Camions];
//dvar interval timeofdelivery[i in clients][m] in i.tmin..i.tmax size 30;
execute {
// cp.param.NoOverlapInferenceLevel = "Medium";
// cp.param.ElementInferenceLevel = "Low";
//cp.param.TemporalRelaxation = "Off";
cp.param.TimeMode = "ElapsedTime";
cp.param.TimeLimit = 10;
};
//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, 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 (j in cities, k in Camions)
// sum(i in cities : j!=i) x[<i,j>][k] == 1;
//
// forall (j in cities, k in Camions)
// sum(i in cities : j!=i) x[<j,i>][k] == 1;
//
// forall (d in Deliveries)
// y[<d.from,
//
forall (i in clients, k in Camions)
(quantity[i][k] >= 1) => y[k][i] == 1;
forall (i in cities)
((demand[i] + outgoing[i]) > 0) => 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;
// chaque véhicule entre et sort qu'un seul fois du dépôt
// forall (k in Camions)
// (sum(j in clients) x[<0,j>][k]) == 1;
//
// forall (k in Camions)
// (sum(i in clients) x[<i,0>][k]) == 1;
forall (k in Camions, <i,j> in Edges : i!=0 && j != 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) 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 (m in Camions)
sum(i in cities) quantity[i][m] <= m.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)>] + tempsservice) <= 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);
//
// Delivery at node 2 must be later than delivery at node 1
forall (<i,j> in Edges, d in Deliveries : d.destination == j && d.from == i, m in Camions)
(y[m][d.from] == 1 && y[m][d.destination] == 1) => (arrival[m][d.from] < arrival[m][d.destination]);
};
//execute {
// function recurse_results(k, i) {
// for (var t in y[k]) {
// if (y[k][t] == 1) {
// var temp = new Array(i,t);
// if (x[temp][k] == 1) {
// recurse_results(k, t);
// writeln(t + " -> ");
// break;
// }
//
// }
// }
// }
//
//
// for (var k in arrival) {
// var str = "Tour for camion "+k.id+": 0 -> ";
// recurse_results(k, 0);
// writeln(str + "0");
// }
//};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment