public static void SolveForAssignedDay(IDataInput dataInput, IDataOutput dataOutput, VrpProblem vrpProblem, Day day, ConfigParams cfg, int[] VCMinMax) { //TimeMatrixInit(day, cfg); //SaveTimeMatrix(day); //LoadTimeMatrix(day); CalculateTMWithHaversineFormula(day); //vrpProblem.SolveVrpProblem(day, cfg); int min = VCMinMax[0]; int max = VCMinMax[1]; while (day.LocationDropped && !day.InfeasibleNodes && max >= min) { day.SetVehicleNumber(min); day.ResetResults(); vrpProblem.SolveVrpProblem(day, cfg, vrpProblem, dataOutput, VCMinMax); dataOutput.PrintSolution(vrpProblem.day, vrpProblem.routing, vrpProblem.manager, vrpProblem.solution); dataOutput.PrintStatus(vrpProblem.routing); min++; } foreach (var item in day.DroppedLocations)//Remove unassigned locations from list { day.Locations.Remove(item); } return; }
public static void AssignAndSolveForDay(IDataInput dataInput, IDataOutput dataOutput, VrpProblem vrpProblem, Day day, ConfigParams cfg, int[] VCMinMax) { CalculateTMWithHaversineFormula(day); int min = VCMinMax[0]; int max = VCMinMax[1]; while (!day.InfeasibleNodes && max >= min) { day.SetVehicleNumber(min); day.ResetResults(); vrpProblem.SolveVrpProblem(day, cfg, vrpProblem, dataOutput, VCMinMax); if (day.Locations.Count > 1) { dataOutput.PrintSolution(vrpProblem.day, vrpProblem.routing, vrpProblem.manager, vrpProblem.solution); dataOutput.PrintStatus(vrpProblem.routing); } min++; } foreach (var item in day.DroppedLocations)//Remove unassigned locations from list { day.Locations.Remove(item); } foreach (var item in day.Locations) { if (!item.Infeasible) { item.VisitDay = day.DayNum; } } }
public static void Main(String[] args) { System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("En"); // Instantiate the data problem. DataInput dataInput = new DataInput(); //Config interface DataOutput dataOutput = new DataOutput(); //Output interface VrpProblem vrpProblem = new VrpProblem(); ConfigParams cfg = new ConfigParams(); //Period(x) => period for x days Period period = new Period(14); bool AssignToDays = true; int[] VCMinMax = new int[2];//Vehicle Count dataInput.GetVCMinMax(VCMinMax); if (AssignToDays == true) { LocationDB.ResetVisitDays(LocationDB.Locations); for (int i = 0; i < period.Days.Count; i++) { if (i == 6 || i == 13) { continue; } GetInput(dataInput, cfg, period.Days.ElementAt(i)); if (i < 6) { period.Days.ElementAt(i).SetDay(LocationDB.Locations.Where(x => x.VisitDay == 0 && x.Infeasible == false).ToList()); period.Days.ElementAt(i).DayNum = i + 1; AssignAndSolveForDay(dataInput, dataOutput, vrpProblem, period.Days.ElementAt(i), cfg, VCMinMax); } if (i > 6) { List <Location> locations = new List <Location>(); foreach (var item in period.Days.ElementAt(i - 7).Locations.Where(x => x.VisitPeriod == 7).ToList()) { item.Penalty = 1000000; locations.Add(item); } locations.AddRange(LocationDB.Locations.Where(x => x.VisitDay == 0 && x.VisitPeriod == 14 && x.Infeasible == false).ToList()); period.Days.ElementAt(i).SetDay(locations); period.Days.ElementAt(i).DayNum = i + 1; AssignAndSolveForDay(dataInput, dataOutput, vrpProblem, period.Days.ElementAt(i), cfg, VCMinMax); } } period.PrintSummary(); } else { SetLocationsForDays(period); LocationDB.GetLocationDataFromDB(); for (int i = 0; i < period.Days.Count; i++) { if (period.Days.ElementAt(i).Locations.Count != 0) { GetInput(dataInput, cfg, period.Days.ElementAt(i)); SolveForAssignedDay(dataInput, dataOutput, vrpProblem, period.Days.ElementAt(i), cfg, VCMinMax); } } period.PrintSummary(); } Console.ReadLine(); return; }
//IntVar x; //IntVar y;//Reduntant public void SolveVrpProblem(Day day, ConfigParams cfg, VrpProblem vrpProblem, IDataOutput dataOutput, int[] VCMinMax) { this.day = day; this.cfg = cfg; //Google Distance Matrix API (Duration matrix) // Create Routing Index Manager manager = new RoutingIndexManager( day.TimeMatrix.GetLength(0), day.Vehicles.Count, day.Depot); // Create Routing Model. routing = new RoutingModel(manager); // Create and register a transit callback. int transitCallbackIndex = routing.RegisterTransitCallback( (long fromIndex, long toIndex) => { // Convert from routing variable Index to distance matrix NodeIndex. var fromNode = manager.IndexToNode(fromIndex); var toNode = manager.IndexToNode(toIndex); return(day.TimeMatrix[fromNode, toNode]); } ); // Define cost of each arc. routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex); // Add Distance constraint. if (day.TimeWindowsActive != true) { routing.AddDimension(transitCallbackIndex, 0, 700000, true, // start cumul to zero "Distance"); RoutingDimension distanceDimension = routing.GetMutableDimension("Distance"); distanceDimension.SetGlobalSpanCostCoefficient(100); } else { routing.AddDimension( transitCallbackIndex, // transit callback 1000, // allow waiting time 600, // vehicle maximum capacities false, // start cumul to zero "Time"); TimeWindowInit(day, routing, manager);//Set Time Window Constraints } if (day.MaxVisitsActive != 0) { int demandCallbackIndex = routing.RegisterUnaryTransitCallback( (long fromIndex) => { // Convert from routing variable Index to demand NodeIndex. var fromNode = manager.IndexToNode(fromIndex); return(day.Demands[fromNode]); } ); routing.AddDimensionWithVehicleCapacity( demandCallbackIndex, 0, // null capacity slack day.VehicleCapacities, // vehicle maximum capacities true, // start cumul to zero "Capacity"); } // Allow to drop nodes. for (int i = 1; i < day.TimeMatrix.GetLength(0); ++i) { routing.AddDisjunction( new long[] { manager.NodeToIndex(i) }, day.Locations.ElementAt(i).Penalty); } // Setting first solution heuristic. RoutingSearchParameters searchParameters = operations_research_constraint_solver.DefaultRoutingSearchParameters(); searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathMostConstrainedArc; //metaheuristic searchParameters.LocalSearchMetaheuristic = LocalSearchMetaheuristic.Types.Value.GuidedLocalSearch; searchParameters.TimeLimit = new Duration { Seconds = cfg.SolutionDuration }; searchParameters.LogSearch = true; solver = routing.solver(); //TODO //Some location must be on same route. //solver.Add(routing.VehicleVar(manager.NodeToIndex(2)) == routing.VehicleVar(manager.NodeToIndex(5))); //One node takes precedence over the another. //routing.AddPickupAndDelivery(manager.NodeToIndex(2), manager.NodeToIndex(5)); //Constraint variable //x = solver.MakeIntVar(day.Vehicles.Count, day.Vehicles.Count, "x"); //Number of vehicle restriction - old version //solver.Add(x < 7); //Number of vehicle restriction -new version //y = solver.MakeIntVar(routing.Vehicles(), routing.Vehicles(), "y"); //solver.Add(y <= VCMinMax[1]);//Reduntant // Solve the problem. solution = routing.SolveWithParameters(searchParameters); day.LocationDropped = false; // Display dropped nodes. List <int> droppedNodes = new List <int>(); for (int index = 0; index < routing.Size(); ++index) { if (routing.IsStart(index) || routing.IsEnd(index)) { continue; } if (solution.Value(routing.NextVar(index)) == index) { droppedNodes.Add(manager.IndexToNode((int)index)); day.LocationDropped = true; } } day.DroppedLocations.Clear(); Console.WriteLine(day.Locations.ElementAt(0).Name); if (droppedNodes != null) { foreach (var item in droppedNodes) { Location location = LocationDB.Locations.Where(x => x.Position.strPos_ == day.Addresses[item]).ToList().ElementAt(0); if (location != null) { Console.WriteLine(location.Name); day.DroppedLocations.Add(location); } } } List <int> AssignedNodes = new List <int>(); Console.WriteLine(manager.GetNumberOfNodes()); //Inspect Infeasable Nodes for (int i = 0; i < day.Vehicles.Count; i++) { var index = routing.Start(i); int j = 0; while (routing.IsEnd(index) == false) { j++; index = solution.Value(routing.NextVar(index)); } if (j == 1) { day.InfeasibleNodes = true; foreach (var item in day.DroppedLocations) { LocationDB.Locations.Where(x => x.ClientRef == item.ClientRef).ToList().ElementAt(0).Infeasible = true; } if (day.Vehicles.Count - 1 >= 1) { day.SetVehicleNumber(day.Vehicles.Count - 1); day.ResetResults(); vrpProblem.SolveVrpProblem(day, cfg, vrpProblem, dataOutput, VCMinMax); } return; } } // Inspect solution. day.TotalDur = 0; day.MinDur = 100000; for (int i = 0; i < day.Vehicles.Count; i++) { long routeDuration = 0; var index = routing.Start(i); while (routing.IsEnd(index) == false) { var previousIndex = index; index = solution.Value(routing.NextVar(index)); routeDuration += routing.GetArcCostForVehicle(previousIndex, index, 0); } day.TotalDur += routeDuration; day.MaxDur = Math.Max(routeDuration, day.MaxDur); day.MinDur = Math.Min(routeDuration, day.MinDur); } day.AvgDur = day.TotalDur / day.Vehicles.Count; }