protected RoutingModel ComposeRoutingModel(out List <int> failedNodes) { failedNodes = new List <int>(); int numberOfSites = Data.GetTimeMatrix().GetLength(0); // Create Routing Model. // [START routing_model] RoutingModel routing = new RoutingModel(manager); // [END routing_model] // Define cost of each arc. // [START arc_cost] int transitCallbackIndex = routing.RegisterTransitCallback(timeCallback); routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex); // [END arc_cost] // Add Distance constraint. // [START time_constraint] // Documentation at: https://github.com/google/or-tools/blob/3494afff17d3dc60daf5ebe6ff2ab4cbc7777163/ortools/constraint_solver/routing.h#L383 routing.AddDimension( transitCallbackIndex, // transit callback Data.getAllowWaitingTime(), // allow waiting time Data.getMaximumWorkerCapacity(), // vehicle maximum capacities false, // start cumul to zero "Time"); RoutingDimension timeDimension = routing.GetMutableDimension("Time"); // Add time window constraints for each location except depot // and 'copy' the slack var in the solution object (aka Assignment) to print it for (int i = 1; i < Data.GetTimeWindows().GetLength(0); ++i) { try { long index = manager.NodeToIndex(i); // TODO: To be replaced to allow mulible shifts similar to: // https://gist.github.com/Muhammad-Altabba/5e52cc1aee98e88f11a01181341f630e#file-vrpsolver-py-L121 timeDimension.CumulVar(index).SetRange( Data.GetTimeWindows()[i, 0], Data.GetTimeWindows()[i, 1]); routing.AddToAssignment(timeDimension.SlackVar(index)); } catch (System.ApplicationException ex) { //Possible cases: The site cannot be visited during the attendance time of the worker. // Or the starting time is after the end time... // Most likely a problem in timing for this node.. failedNodes.Add(i); Console.WriteLine("(Note: " + ex.Message + " to add for node " + i + ". Could be because the site cannot be visited during the attendance time of the workers. Or there is a time inconsistency for this node.)"); } } // Add time window constraints for each vehicle start node // and 'copy' the slack var in the solution object (aka Assignment) to print // it for (int i = 0; i < Data.GetVehicleNumber(); ++i) { long index = routing.Start(i); timeDimension.CumulVar(index).SetRange( Data.GetTimeWindows()[0, 0], Data.GetTimeWindows()[0, 1]); routing.AddToAssignment(timeDimension.SlackVar(index)); } // [END time_constraint] for (int i = 0; i < numberOfSites; i++) { CpInt64Vector v = new CpInt64Vector(); v.Add(manager.NodeToIndex(i)); routing.AddDisjunction(v, Data.GetDemands()[i]); } return(routing); }
public TimeCallback(DataModel data, RoutingIndexManager manager) { timeMatrix = data.GetTimeMatrix(); timeDemand_ = data.GetTimeDemandMatrix(); indexManager = manager; }