// Should be Solution solution public static void Save(Route solution) { string dir = Directory.GetCurrentDirectory(); string outputFile = "Solution.txt"; File.WriteAllLines(dir + outputFile, solution.ToStrings()); }
// Should be Solution solution public static void Save(Route[,] solution) { string dir = Directory.GetCurrentDirectory(); string outputFile = "/Solution.txt"; List<string> output = new List<string>(); foreach (var route in solution) { if (route != null) output.AddRange(route.ToStrings()); } File.WriteAllLines(dir + outputFile, output); }
public static Route HillclimbingSearch(Route route) { int baseFitness = route.FitnessValue(); int prevFitness = int.MaxValue; // Do 2opt. // for a list of 12 values that would be... (i=[0..12], k=[i+1..12]) => O(n!) // or taking the first positive change would be... o(n!)... which isn't muuch better while (prevFitness > baseFitness) { for (int i = 0; i < route.Orders.Count; i++) for (int k = i + 1; k < route.Orders.Count; k++) { var tmp = Opt_2_Swap(route, i, k); if (tmp.FitnessValue() < baseFitness) { baseFitness = tmp.FitnessValue(); route = tmp; } } prevFitness = baseFitness; } return route; }
// Swaps 2 orders in the Route with eachother. public static Route Opt_2_Swap(Route route, int i, int k) { Order[] oldRoute = route.Orders.ToArray(); Queue<Order> newRoute = new Queue<Order>(); // Add the first part first to last // so 0 till i-1 will be in the queue for (int j = 0; j < i - 1; j++) newRoute.Enqueue(oldRoute[j]); int routeTime = 0; int routeDistance = 0; // The part between the old connections needs to be added in reverse // so instead from i -> k it is now k -> i for (int j = k; j > i; j--) { newRoute.Enqueue(oldRoute[j]); // Calculate the time of the part that will be changed routeTime -= Program.afstandenMatrix[oldRoute[j - 1].MatrixID, oldRoute[j].MatrixID].TravelTime; routeTime += Program.afstandenMatrix[oldRoute[j].MatrixID, oldRoute[j - 1].MatrixID].TravelTime; // And the same for the distance routeDistance -= Program.afstandenMatrix[oldRoute[j - 1].MatrixID, oldRoute[j].MatrixID].Dist; routeDistance += Program.afstandenMatrix[oldRoute[j].MatrixID, oldRoute[j - 1].MatrixID].Dist; } // And then the last part shold be normal again for (int j = k + 1; j < oldRoute.Length; j++) newRoute.Enqueue(oldRoute[j]); route.UpdateRoute(newRoute, routeTime, routeDistance); return route; }
// Is not threadsafe // Changes order from: {0 -> .. -> i} -> {i+1 -> .. -> k} -> {k+1 -> .. -> j} -> {j+1 -> ..end} // To a random new combination of the sections, with {m -> .. -> n} being a section (m != 0, n != end) // Sections CAN be reversed, so there are 3 feasible options: // X) Reverse {i+1 -> k}, Keep {k+1 ->j} -> 2Opt // X) Keep {i+1 -> k}, Reverse {k+1 ->j} -> 2Opt // X) Reverse {i+1 -> k} and {k+1 ->j} -> 2*2Opt // 1) Swap them // 2) Swap them, but Reverse {k+1 ->j} // 3) Swap them, but Reverse {i+1 ->k} // X) Swap them, and Reverse {i+1 ->k} and {k+1 ->j} -> 2Opt // X) Do nothing -> Kinda pointless, eh? // The first and last sections are still in their original place public RouteSim Opt_3_Swap(int i, int k, int j, int variation) { Route newRoute = new Route (this.GarbageTruck, this.DayId); //LinkedList<RouteStop> newRoute = new LinkedList<RouteStop>(); Order order; // Part 1 is normal (from begin to first node to swap) for (int pos = 0; pos < i; pos++) { order = new Order (this.Orders.ElementAt(pos).Order.OrderID, this.Orders.ElementAt(pos).Order.LoadTime, this.Orders.ElementAt(pos).Order.VolumePerContainer, this.Orders.ElementAt(pos).Order.ContainerAmt, this.Orders.ElementAt(pos).Order.Frequency, this.Orders.ElementAt(pos).Order.X, this.Orders.ElementAt(pos).Order.Y, this.Orders.ElementAt(pos).Order.MatrixID); newRoute = newRoute.AddOrder (order).getRoute(); } // Easy // Now part 2 and 3: switch (variation) { case 0: // Swap the sections for (int pos = k; pos < j; pos++) { order = new Order (this.Orders.ElementAt (pos).Order.OrderID, this.Orders.ElementAt (pos).Order.LoadTime, this.Orders.ElementAt (pos).Order.VolumePerContainer, this.Orders.ElementAt (pos).Order.ContainerAmt, this.Orders.ElementAt (pos).Order.Frequency, this.Orders.ElementAt (pos).Order.X, this.Orders.ElementAt (pos).Order.Y, this.Orders.ElementAt (pos).Order.MatrixID); newRoute = newRoute.AddOrder (order).getRoute (); } for (int pos = i; pos < k; pos++) { order = new Order (this.Orders.ElementAt (pos).Order.OrderID, this.Orders.ElementAt (pos).Order.LoadTime, this.Orders.ElementAt (pos).Order.VolumePerContainer, this.Orders.ElementAt (pos).Order.ContainerAmt, this.Orders.ElementAt (pos).Order.Frequency, this.Orders.ElementAt (pos).Order.X, this.Orders.ElementAt (pos).Order.Y, this.Orders.ElementAt (pos).Order.MatrixID); newRoute = newRoute.AddOrder (order).getRoute (); } break; case 1: // Swap the sections reverse latter (now the first one) for (int pos = j - 1; pos >= k; pos--){ order = new Order (this.Orders.ElementAt (pos).Order.OrderID, this.Orders.ElementAt (pos).Order.LoadTime, this.Orders.ElementAt (pos).Order.VolumePerContainer, this.Orders.ElementAt (pos).Order.ContainerAmt, this.Orders.ElementAt (pos).Order.Frequency, this.Orders.ElementAt (pos).Order.X, this.Orders.ElementAt (pos).Order.Y, this.Orders.ElementAt (pos).Order.MatrixID); newRoute = newRoute.AddOrder (order).getRoute (); } for (int pos = i; pos < k; pos++){ order = new Order (this.Orders.ElementAt (pos).Order.OrderID, this.Orders.ElementAt (pos).Order.LoadTime, this.Orders.ElementAt (pos).Order.VolumePerContainer, this.Orders.ElementAt (pos).Order.ContainerAmt, this.Orders.ElementAt (pos).Order.Frequency, this.Orders.ElementAt (pos).Order.X, this.Orders.ElementAt (pos).Order.Y, this.Orders.ElementAt (pos).Order.MatrixID); newRoute = newRoute.AddOrder (order).getRoute (); } // What is the diff in travel time etc? // time -= {i -> i+1} + {k -> k+1} + {k+1 -> .. -> j} + {j -> j+1} // time += {i -> j} + {k+1-> i+1} + {j -> .. -> k+1} + {k+1 -> j+1} break; case 2: // Swap the sections reverse former (now the second one) for (int pos = k; pos < j; pos++){ order = new Order (this.Orders.ElementAt (pos).Order.OrderID, this.Orders.ElementAt (pos).Order.LoadTime, this.Orders.ElementAt (pos).Order.VolumePerContainer, this.Orders.ElementAt (pos).Order.ContainerAmt, this.Orders.ElementAt (pos).Order.Frequency, this.Orders.ElementAt (pos).Order.X, this.Orders.ElementAt (pos).Order.Y, this.Orders.ElementAt (pos).Order.MatrixID); newRoute = newRoute.AddOrder (order).getRoute (); } for (int pos = k - 1; pos >= i; pos--){ order = new Order (this.Orders.ElementAt (pos).Order.OrderID, this.Orders.ElementAt (pos).Order.LoadTime, this.Orders.ElementAt (pos).Order.VolumePerContainer, this.Orders.ElementAt (pos).Order.ContainerAmt, this.Orders.ElementAt (pos).Order.Frequency, this.Orders.ElementAt (pos).Order.X, this.Orders.ElementAt (pos).Order.Y, this.Orders.ElementAt (pos).Order.MatrixID); newRoute = newRoute.AddOrder (order).getRoute (); } break; } // Lastly part 4: for (int pos = j; pos < this.Orders.Count; pos++){ order = new Order (this.Orders.ElementAt (pos).Order.OrderID, this.Orders.ElementAt (pos).Order.LoadTime, this.Orders.ElementAt (pos).Order.VolumePerContainer, this.Orders.ElementAt (pos).Order.ContainerAmt, this.Orders.ElementAt (pos).Order.Frequency, this.Orders.ElementAt (pos).Order.X, this.Orders.ElementAt (pos).Order.Y, this.Orders.ElementAt (pos).Order.MatrixID); newRoute = newRoute.AddOrder (order).getRoute (); } RouteSim result = new RouteSim (); result.getRoute = () => { return newRoute; }; result.time = newRoute.EnRouteTime; return result; }
// Is not threadsafe /// <summary> /// /// </summary> /// <param name="i"></param> /// <param name="k"> should be between 0 and Orders.length - 2 (inclusive) </param> public RouteSim Opt_2_Swap(int i, int k) { Route newRoute = new Route (this.GarbageTruck, this.DayId); /*LinkedList<RouteStop> newRoute = new LinkedList<RouteStop>(); int changeTime = 0; changeTime -= Program.afstandenMatrix[oldRoute[i].Order.MatrixID, oldRoute[i + 1].Order.MatrixID].TravelTime + Program.afstandenMatrix[oldRoute[k].Order.MatrixID, oldRoute[k + 1].Order.MatrixID].TravelTime; changeTime += Program.afstandenMatrix[oldRoute[i].Order.MatrixID, oldRoute[k + 1].Order.MatrixID].TravelTime + Program.afstandenMatrix[oldRoute[i + 1].Order.MatrixID, oldRoute[k + 1].Order.MatrixID].TravelTime;*/ // Time -= {i -> i+1} + {k -> k+1} + {i+1 -> .. -> k} // Time += {i -> k+1} + {i+1 -> k+1} + { k -> .. -> i+1} Order order; // Part 1 is normal (from begin to first node to swap) for (int j = 0; j < i; j++) { order = new Order (this.Orders.ElementAt(j).Order.OrderID, this.Orders.ElementAt(j).Order.LoadTime, this.Orders.ElementAt(j).Order.VolumePerContainer, this.Orders.ElementAt(j).Order.ContainerAmt, this.Orders.ElementAt(j).Order.Frequency, this.Orders.ElementAt(j).Order.X, this.Orders.ElementAt(j).Order.Y, this.Orders.ElementAt(j).Order.MatrixID); newRoute = newRoute.AddOrder (order).getRoute(); } // Part 2, reverse {i+1 -> .. -> k} for (int j = k - 1; j >= i; j--) { order = new Order (this.Orders.ElementAt(j).Order.OrderID, this.Orders.ElementAt(j).Order.LoadTime, this.Orders.ElementAt(j).Order.VolumePerContainer, this.Orders.ElementAt(j).Order.ContainerAmt, this.Orders.ElementAt(j).Order.Frequency, this.Orders.ElementAt(j).Order.X, this.Orders.ElementAt(j).Order.Y, this.Orders.ElementAt(j).Order.MatrixID); newRoute = newRoute.AddOrder (order).getRoute(); /* // Verwijder de oude tijd changeTime -= Program.afstandenMatrix[oldRoute[j - 1].Order.MatrixID, oldRoute[j].Order.MatrixID].TravelTime; // Voeg de nieuwe tijd toe changeTime += Program.afstandenMatrix[oldRoute[j].Order.MatrixID, oldRoute[j - 1].Order.MatrixID].TravelTime;*/ } // Part 3, the rest for (int j = k; j < this.Orders.Count; j++) { order = new Order (this.Orders.ElementAt(j).Order.OrderID, this.Orders.ElementAt(j).Order.LoadTime, this.Orders.ElementAt(j).Order.VolumePerContainer, this.Orders.ElementAt(j).Order.ContainerAmt, this.Orders.ElementAt(j).Order.Frequency, this.Orders.ElementAt(j).Order.X, this.Orders.ElementAt(j).Order.Y, this.Orders.ElementAt(j).Order.MatrixID); newRoute = newRoute.AddOrder (order).getRoute(); } //int EnRouteTime = this.EnRouteTime + changeTime; RouteSim result = new RouteSim (); //Route obj = this; result.getRoute = () => { return newRoute; }; result.time = newRoute.EnRouteTime; return result; }