// Add an order to the list // Keep in mind: The Travel Time is in seconds! public RouteSim AddOrder(Order destination, int location = -1) { RouteSim result = new RouteSim (); Route obj = this; if (this.Orders.Count == 0) { if (this.Clearings.Count == 0) { this.Clearings.AddLast(new GarbageStop ()); } result.getRoute = () => { RouteStop stop = new RouteStop(); stop.Order = destination; stop.Node = obj.Orders.AddLast(stop); stop.NextClearing = obj.Clearings.Last; stop.NextClearing.Value.Amount = stop.Order.CompressedVolume; stop.NextClearing.Value.Last = stop.Node; obj.EnRouteTime = Program.afstandenMatrix [287, destination.MatrixID].TravelTime + destination.LoadTime + Program.afstandenMatrix [destination.MatrixID, 287].TravelTime + 1800; return obj; }; result.time = Program.afstandenMatrix [287, destination.MatrixID].TravelTime + destination.LoadTime + Program.afstandenMatrix [destination.MatrixID, 287].TravelTime + 1800; if (result.time > dayTimeSec) { throw new OverflowException ("Too much!"); } return result; } if (location == -1) { Random rnd = new Random (); location = rnd.Next(this.Orders.Count); } RouteStop next = this.Orders.ElementAt(location); int prevID; if (next.Node.Previous != null) { prevID = next.Node.Previous.Value.Order.MatrixID; } else { prevID = 287; // The garbage disposal location } int curID = destination.MatrixID; int nextID = next.Order.MatrixID; float EnRouteTime = this.EnRouteTime; EnRouteTime -= Program.afstandenMatrix [prevID, nextID].TravelTime; EnRouteTime += Program.afstandenMatrix [prevID, curID].TravelTime; EnRouteTime += Program.afstandenMatrix [curID, nextID].TravelTime; EnRouteTime += destination.LoadTime; var nextClearing = next.NextClearing; RouteStop stop2 = new RouteStop(); stop2.Order = destination; stop2.Node = obj.Orders.AddBefore (next.Node, stop2); stop2.NextClearing = nextClearing; var fixSim = FixClearings (nextClearing, destination.CompressedVolume, false); obj.Orders.Remove (stop2.Node); EnRouteTime += fixSim.delta; result.getRoute = () => { //fixSim.getRoute(); // Get the new time and distance required obj.EnRouteTime = EnRouteTime; stop2.Node = obj.Orders.AddBefore (next.Node, stop2); obj = fixSim.getRoute(); return obj; }; result.time = EnRouteTime; if (result.time > dayTimeSec) { throw new OverflowException ("Too much!"); } return result; }
// 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; }
// O(n) time to remove a specified node public RouteSim RemoveOrder(RouteStop order) { RouteSim result = new RouteSim (); if (this.Orders.Count == 1 && this.Orders.First.Value == order) { result.time = 0; result.getRoute = () => { return new Route(this.GarbageTruck, this.DayId); }; return result; } float EnRouteTime = this.EnRouteTime; EnRouteTime -= order.Order.LoadTime; int prevID = 287; int nextID = 287; int curID = order.Order.MatrixID; if (order.Node.Previous != null) { prevID = order.Node.Previous.Value.Order.MatrixID; } if (order.NextClearing.Value.Last.Value != order) { nextID = order.Node.Next.Value.Order.MatrixID; } EnRouteTime -= Program.afstandenMatrix [curID, nextID].TravelTime; EnRouteTime -= Program.afstandenMatrix [prevID, curID].TravelTime; EnRouteTime += Program.afstandenMatrix [prevID, nextID].TravelTime; var next = order.Node.Next; bool changedClearing = false; if (order.NextClearing.Value.Last.Value == order) { order.NextClearing.Value.Last = order.Node.Previous; changedClearing = true; } this.Orders.Remove (order.Node); var fixSim = FixClearings (order.NextClearing, order.Order.CompressedVolume, true); if (next != null) { this.Orders.AddBefore (next, order.Node); } else { this.Orders.AddLast (order.Node); } if (changedClearing) { order.NextClearing.Value.Last = order.Node; } EnRouteTime += fixSim.delta; result = new RouteSim (); Route obj = this; result.getRoute = () => { if (order.NextClearing.Value.Last == order.Node) { order.NextClearing.Value.Last = order.Node.Previous; } obj.Orders.Remove(order.Node); obj.EnRouteTime = EnRouteTime; obj = fixSim.getRoute(); return obj; }; result.time = 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; }