include "global_cardinality.mzn"; int: n; % Number of customers int: m; % Maximum number of vehicles int: capacity; % Capacity of each vehicle int: DEPOT = n+1; set of int: CUSTOMER = 1..n; set of int: LOCATION = 1..n+1; set of int: VEHICLE = 1..m; set of int: WORKINGDAY = ready_time[DEPOT]..due_time[DEPOT]; array[LOCATION,LOCATION] of int: distance; % Distance between locations array[LOCATION] of int: demand; % Demand of each location array[LOCATION] of int: service; % Duration of service array[LOCATION] of int: ready_time; % Start of time window of each location array[LOCATION] of int: due_time; % End of time window of each location array[CUSTOMER] of var LOCATION: pred; % predecessor, where do we come from? array[CUSTOMER] of var bool: last; % Is this customer the last one on the route (before the depot) array[CUSTOMER] of var 0..1: isPred; % isPred[c] = 1 <-> c is a predecessor of some other customer var VEHICLE: vehiclesUsed; % the number of vehicles actually used (aka number of routes) % number of vehicles used (aka number of routes) constraint vehiclesUsed = sum(last); % is customer c a predecessor of some other customer? constraint forall(c in CUSTOMER)(isPred[c] = 0 <-> last[c]); % c is not a predecessor iff it is last in route % if a customer is a predecessor of some other customer then it must occur exactly once in pred constraint global_cardinality(pred,CUSTOMER,isPred); % if n vehicles are used then there must be that number of customers that have pred[c] = DEPOT constraint global_cardinality(pred,[DEPOT],[vehiclesUsed]); % Capacity constraints array[LOCATION] of var 0..capacity: load; % load in vehicle required to get to customer c and its predecessors constraint load[DEPOT] = 0; constraint forall(c in CUSTOMER)(load[c] = demand[c] + load[pred[c]]); % objective var int: total_distance = sum(c in CUSTOMER)(distance[pred[c],c] + last[c]*distance[c,DEPOT]); solve::int_search(pred,smallest,indomain_min,complete) minimize total_distance; output["predecessor = \(pred)\n"] ++["last = \(last)\n"] ++["load at customer = \(load)\n"] ++["Number of used vehicles = \(vehiclesUsed)\n"] ++["total_distance = \(total_distance)\n"];