public override Solution executeStrategy(Solution toStartFrom) { var dayArray = Enum.GetValues(typeof(Days)); Days day = (Days)dayArray.GetValue(random.Next(1, dayArray.Length)); if (day.Equals(Days.None)) Console.WriteLine("Day is Days.None at RouteAddStrategy! FIX ME!"); routeCreated = new Route(day); var allClusters = toStartFrom.GetAllClusters(); int clusterIndex = random.Next(allClusters.Count); for (int i = 0; i < 16; i++) //64 -> 16 { clusterIndex = random.Next(allClusters.Count); if (allClusters[clusterIndex].AvailableOrdersInCluster.Count == 0) continue; int randomIndex = random.Next(allClusters[clusterIndex].AvailableOrdersInCluster.Count); Order order = allClusters[clusterIndex].AvailableOrdersInCluster[randomIndex]; if (!routeCreated.CanAddOrder(order)) continue; routeCreated.AddOrder(order); order.RemoveAvailableOrderFromCluster(); } if (routeCreated.Orders.Count > 1) // Does the route have orders added to it { toStartFrom.AddRoute(routeCreated); strategyHasExecuted = true; } return toStartFrom; }
public override Solution executeStrategy(Solution toStartFrom) { Planning = toStartFrom.GetRandomPlanning(); RoutesFromSolution = Planning.Item3; //save the begin route for rollback old_route = RoutesFromSolution[random.Next(RoutesFromSolution.Count)]; //copy the begin route for the 2-opt and create the route for the 2-opt check routeToWorkWith = new Route(Planning.Item1); new_route = new Route(Planning.Item1); foreach (Order order in old_route.Orders) { routeToWorkWith.AddOrder(order); new_route.AddOrder(order); } //start doing the opt-2 algorithm on the route list double best_traveltime = old_route.TravelTime; double new_traveltime = double.MaxValue; int improvestep = 0; while (improvestep < 50) { for (int i = 0; i < routeToWorkWith.Orders.Count - 2; i++) { for (int k = i + 1; k < routeToWorkWith.Orders.Count - 1; k++) { //swap the 2 coords swapOrders(routeToWorkWith.Orders[i], routeToWorkWith.Orders[k], routeToWorkWith); new_traveltime = routeToWorkWith.TravelTime; if (new_traveltime < best_traveltime) { improvestep = 0; new_route = routeToWorkWith; best_traveltime = new_traveltime; routeToWorkWith = new Route(Planning.Item1); foreach (Order order in new_route.Orders) routeToWorkWith.AddOrder(order); } } } improvestep++; } RoutesFromSolution.Remove(old_route); RoutesFromSolution.Add(new_route); toStartFrom.RemoveItemFromPlanning(Planning.Item1, Planning.Item2); toStartFrom.AddNewItemToPlanning(Planning.Item1, Planning.Item2, RoutesFromSolution); return toStartFrom; }
public override Solution undoStrategy(Solution toStartFrom) { if (!strategyHasExecuted) return toStartFrom; Route routeRestored = new Route(dayDestroyed); foreach (Order order in ordersDestroyed) { routeRestored.AddOrder(order); order.RemoveAvailableOrderFromCluster(); } toStartFrom.AddRoute(routeRestored); return toStartFrom; }
public override Solution executeStrategy(Solution toStartFrom) { Planning = toStartFrom.GetRandomPlanning(); if (Planning.Item3.Count == 0) return toStartFrom; old_route = Planning.Item3[random.Next(Planning.Item3.Count)]; if (old_route == null || old_route.Orders.Count < 4) return toStartFrom; // Could not find a valid route to shuffle new_route = new Route(Planning.Item1); foreach (Order order in old_route.Orders) new_route.AddOrder(order); int firstIndex = random.Next(old_route.Orders.Count - 1); int secondIndex = random.Next(old_route.Orders.Count - 1); int thirdIndex = random.Next(old_route.Orders.Count - 1); while (firstIndex == secondIndex || firstIndex == thirdIndex || secondIndex == thirdIndex) return toStartFrom; double timeLimit = 0.0d; // Check if route can be swapped traveltime-wise foreach (Route route in Planning.Item3) if (route != old_route) timeLimit += route.TravelTime; timeLimit = 43200.0d - timeLimit; if (new_route.CanHalfSwapOrder(old_route.Orders[firstIndex], old_route.Orders[thirdIndex], old_route.Orders[thirdIndex], timeLimit)) { new_route.HalfSwapOrders(old_route.Orders[firstIndex], old_route.Orders[thirdIndex], old_route.Orders[thirdIndex]); toStartFrom.AddRoute(new_route); toStartFrom.RemoveRouteFromPlanning(Planning.Item1, Planning.Item2, old_route); toStartFrom.AddRouteToPlanning(Planning.Item1, Planning.Item2, new_route); toStartFrom.RemoveRoute(old_route); strategyHasExecuted = true; } return toStartFrom; }
public override Solution executeStrategy(Solution toStartFrom) { planningForSelectedRoute = toStartFrom.GetRandomPlanning(); firstOriginalRoute = planningForSelectedRoute.Item3[random.Next(planningForSelectedRoute.Item3.Count)]; secondOriginalRoute = planningForSelectedRoute.Item3[random.Next(planningForSelectedRoute.Item3.Count)]; for (int index = 0; index < 5 && firstOriginalRoute != secondOriginalRoute; index++) secondOriginalRoute = planningForSelectedRoute.Item3[random.Next(planningForSelectedRoute.Item3.Count)]; double firstOriginalTravelTime = firstOriginalRoute.TravelTime; double secondOriginalTravelTime = secondOriginalRoute.TravelTime; int[] numOfSlices = new int[2] {random.Next(1, firstOriginalRoute.Orders.Count - 2), random.Next(1, secondOriginalRoute.Orders.Count - 2)}; List<int>[] sliceIndices = new List<int>[2]; for (int i = 0; i < sliceIndices.Length; i++) { sliceIndices[i] = new List<int>(); for (int j = 0; j < numOfSlices[i]; j++) { bool hasAddedAnIndex = false; do { int sliceIndex = random.Next(1, numOfSlices[i]); if (!sliceIndices[i].Contains(sliceIndex)) { sliceIndices[i].Add(sliceIndex); hasAddedAnIndex = true; } } while (!hasAddedAnIndex); } sliceIndices[i].Sort(); } // COMMENCE THE GENETIC EXPERIMENTS! // OPERATION SLICE & SPLICE AN ABOMINATION IS ACTIVE! List<Order>[][] orderSlices = new List<Order>[sliceIndices.Length][]; for (int index = 0; index < sliceIndices.Length; index++) { orderSlices[index] = new List<Order>[sliceIndices[index].Count]; for (int i = 0; i < sliceIndices[index].Count; i++) { orderSlices[index][i] = new List<Order>(); int startIndex = i == 0 ? 0 : sliceIndices[index][i - 1]; for (int j = startIndex; j < sliceIndices[index][i]; j++) if(index == 0) orderSlices[0][i].Add(firstOriginalRoute.Orders[j]); else orderSlices[1][i].Add(secondOriginalRoute.Orders[j]); } } // Now that you've sliced up the orders in the selected route, it is time for randomizing the slices and putting it back together firstAbominationRoute = new Route(planningForSelectedRoute.Item1); secondAbominationRoute = new Route(planningForSelectedRoute.Item1); List<int>[] slicesIndexPutBack = new List<int>[2]; for (int index = 0; index < sliceIndices.Length; index++) { slicesIndexPutBack[index] = new List<int>(); for (int i = 0; i < orderSlices[index].Length - 2; i++) { bool hasPutBackASlice = false; do { int sliceIndex = random.Next(1, orderSlices[index].Length - 1); if (!slicesIndexPutBack[index].Contains(sliceIndex)) { for (int j = 0; j < orderSlices[index][sliceIndex].Count; j++) if (orderSlices[index][sliceIndex][j].OrderNumber != 0) if (index == 0) firstAbominationRoute.AddOrder(orderSlices[index][sliceIndex][j]); else secondAbominationRoute.AddOrder(orderSlices[index][sliceIndex][j]); slicesIndexPutBack[index].Add(sliceIndex); hasPutBackASlice = true; } } while (!hasPutBackASlice); } } // COMMENCE THE GENETIC EXPERIMENTS PHASE TWO! // OPERATION DARWIN'S ABOMINATION REPRODUCTION IS NOW OPERATIONAL! int numOfGenerationsToMake = 64; Route bestBoyAbominationOffspring = firstAbominationRoute; Route bestGirlAbominationOffspring = secondAbominationRoute; int[] numberOfGenesThatAreTransferred = new int[2] { random.Next(firstAbominationRoute.Orders.Count / 4, // 25% firstAbominationRoute.Orders.Count / 2), // 50% random.Next(secondAbominationRoute.Orders.Count / 4, // 25% secondAbominationRoute.Orders.Count / 2)}; // 50% List<Order>[] ordersSelectedForGeneticSwap = new List<Order>[2] { new List<Order>(), new List<Order>() }; while (numOfGenerationsToMake > 0) { for (int i = 0; i < 2; i++) { ordersSelectedForGeneticSwap[i].Clear(); int orderIndex = -1; do { orderIndex = random.Next(orderSlices[i].Length - 1); Order randomOrder = null; if (i == 0) randomOrder = bestBoyAbominationOffspring.Orders[orderIndex]; else randomOrder = bestGirlAbominationOffspring.Orders[orderIndex]; if (ordersSelectedForGeneticSwap[i].Contains(randomOrder)) continue; ordersSelectedForGeneticSwap[i].Add(randomOrder); } while (ordersSelectedForGeneticSwap[i].Count * 2 < numberOfGenesThatAreTransferred[i] - 1); List<int> indicesToBeSwaped = new List<int>(); // FIX MEE foreach (Order order in ordersSelectedForGeneticSwap[i]) // TODO, not (exclusive) simularities, but just 'random' orders { indicesToBeSwaped.Add(bestBoyAbominationOffspring.Orders.FindIndex(o => o == order)); indicesToBeSwaped.Add(bestGirlAbominationOffspring.Orders.FindIndex(o => o == order)); } indicesToBeSwaped.Sort(); Route newBoyAbominationOffspring = new Route(planningForSelectedRoute.Item1); Route newGirlAbominationOffspring = new Route(planningForSelectedRoute.Item1); for (int index = 0; index < firstOriginalRoute.Orders.Count - 1; index++) // FIX MEE TOOO!! { if (indicesToBeSwaped.Contains(index)) { newBoyAbominationOffspring.AddOrder(bestGirlAbominationOffspring.Orders[index]); newGirlAbominationOffspring.AddOrder(bestBoyAbominationOffspring.Orders[index]); } else { newBoyAbominationOffspring.AddOrder(bestBoyAbominationOffspring.Orders[index]); newGirlAbominationOffspring.AddOrder(bestGirlAbominationOffspring.Orders[index]); } } Boolean newGirlAbominationOffspringIstheBest = newBoyAbominationOffspring.TravelTime <= newGirlAbominationOffspring.TravelTime; if (true) // if (boyAbominationIsTheBest) Find alternative! { if (newGirlAbominationOffspringIstheBest) { if (bestGirlAbominationOffspring.TravelTime < newGirlAbominationOffspring.TravelTime) { bestGirlAbominationOffspring = newGirlAbominationOffspring; if (bestBoyAbominationOffspring.TravelTime < newBoyAbominationOffspring.TravelTime) { bestBoyAbominationOffspring = newBoyAbominationOffspring; } } } else { if (bestGirlAbominationOffspring.TravelTime < newBoyAbominationOffspring.TravelTime) { bestGirlAbominationOffspring = newBoyAbominationOffspring; if (bestBoyAbominationOffspring.TravelTime < newGirlAbominationOffspring.TravelTime) { bestBoyAbominationOffspring = newGirlAbominationOffspring; } } } } else { if (newGirlAbominationOffspringIstheBest) { if (bestBoyAbominationOffspring.TravelTime < newGirlAbominationOffspring.TravelTime) { bestBoyAbominationOffspring = newGirlAbominationOffspring; if (bestGirlAbominationOffspring.TravelTime < newBoyAbominationOffspring.TravelTime) { bestGirlAbominationOffspring = newBoyAbominationOffspring; } } } else { if (bestBoyAbominationOffspring.TravelTime < newBoyAbominationOffspring.TravelTime) { bestBoyAbominationOffspring = newBoyAbominationOffspring; if (bestGirlAbominationOffspring.TravelTime < newGirlAbominationOffspring.TravelTime) { bestGirlAbominationOffspring = newGirlAbominationOffspring; } } } } } numOfGenerationsToMake--; } // PHASE 3 - INSERT THE ABOMINATION INTO THE PUBLIC! firstBestAbominationOffspringRoute = bestBoyAbominationOffspring; secondBestAbominationOffspringRoute = bestGirlAbominationOffspring; // secondBest? Console.WriteLine("First Route: Original Travel Time: {0}", firstOriginalTravelTime); // NEEDS FIXING Console.WriteLine("First Route: The First Abomination Travel Time: {0}", firstAbominationRoute.TravelTime); // NEEDS FIXING Console.WriteLine("First Route: Best Abomination Offspring Travel Time: {0}", firstBestAbominationOffspringRoute.TravelTime); // NEEDS FIXING Console.WriteLine("Second Route: Original Travel Time: {0}", secondOriginalTravelTime); // NEEDS FIXING Console.WriteLine("Second Route: The First Abomination Travel Time: {0}", secondAbominationRoute.TravelTime); // NEEDS FIXING Console.WriteLine("Second Route: Best Abomination Offspring Travel Time: {0}", secondBestAbominationOffspringRoute.TravelTime); // NEEDS FIXING planningForSelectedRoute.Item3.Remove(firstOriginalRoute); // NEEDS FIXING? planningForSelectedRoute.Item3.Add(firstBestAbominationOffspringRoute); // NEEDS FIXING? planningForSelectedRoute.Item3.Remove(secondOriginalRoute); // NEEDS FIXING? planningForSelectedRoute.Item3.Add(secondBestAbominationOffspringRoute); // NEEDS FIXING? toStartFrom.RemoveItemFromPlanning(planningForSelectedRoute.Item1, planningForSelectedRoute.Item2); // NEEDS FIXING toStartFrom.AddNewItemToPlanning(planningForSelectedRoute.Item1, planningForSelectedRoute.Item2, planningForSelectedRoute.Item3); // NEEDS FIXING return toStartFrom; }
public override Solution executeStrategy(Solution toStartFrom) { Planning = toStartFrom.GetRandomPlanning(); RoutesFromSolution = Planning.Item3; //save the begin route for rollback old_route = RoutesFromSolution[random.Next(RoutesFromSolution.Count)]; //copy the begin route for the 2-opt and create the route for the 2-opt check for (int i = 0; i < routesToWorkWith.Length; i++) routesToWorkWith[i] = new Route(Planning.Item1); new_route = new Route(Planning.Item1); foreach (Order order in old_route.Orders) { for (int i = 0; i < routesToWorkWith.Length; i++) routesToWorkWith[i].AddOrder(order); new_route.AddOrder(order); } //start doing the opt-3 algorithm on the route list double best_traveltime = old_route.TravelTime; double[] new_traveltime = new double[NumberOfRoutesCreated]; for (int i = 0; i < new_traveltime.Length; i++) new_traveltime[i] = double.MaxValue; int improvestep = 0; while (improvestep < 10) { for (int i = 0; i < old_route.Orders.Count - 3; i++) { for (int j = i + 1; j < old_route.Orders.Count - 2; j++) { for (int k = j + 1; k < old_route.Orders.Count - 1; k++) { //swap the 2 coords Order[] initialRouteI = new Order[NumberOfRoutesCreated]; for (int index = 0; index < initialRouteI.Length; index++) initialRouteI[index] = routesToWorkWith[index].Orders[i]; Order[] initialRouteJ = new Order[NumberOfRoutesCreated]; for (int index = 0; index < initialRouteJ.Length; index++) initialRouteJ[index] = routesToWorkWith[index].Orders[j]; Order[] initialRouteK = new Order[NumberOfRoutesCreated]; for (int index = 0; index < initialRouteK.Length; index++) initialRouteK[index] = routesToWorkWith[index].Orders[k]; for (int index = 0; index < routesToWorkWith.Length; index++) { swapOrders(initialRouteI[index], initialRouteK[index], routesToWorkWith[index]); swapOrders(initialRouteI[index], initialRouteJ[index], routesToWorkWith[index]); new_traveltime[index] = routesToWorkWith[index].TravelTime; } bool hasABetterTime = false; for (int index = 0; index < new_traveltime.Length; index++) { if (new_traveltime[index] < best_traveltime) { improvestep = 0; hasABetterTime = true; new_route = routesToWorkWith[index]; best_traveltime = new_traveltime[index]; } } if (hasABetterTime) { for (int index = 0; index < routesToWorkWith.Length; index++) routesToWorkWith[index] = new Route(Planning.Item1); foreach (Order order in old_route.Orders) for (int index = 0; index < routesToWorkWith.Length; index++) routesToWorkWith[index].AddOrder(order); } } } } improvestep++; } RoutesFromSolution.Remove(old_route); RoutesFromSolution.Add(new_route); toStartFrom.RemoveItemFromPlanning(Planning.Item1, Planning.Item2); toStartFrom.AddNewItemToPlanning(Planning.Item1, Planning.Item2, RoutesFromSolution); return toStartFrom; }
public override Solution executeStrategy(Solution toStartFrom) { planningForSelectedRoute = toStartFrom.GetRandomPlanning(); originalRoute = planningForSelectedRoute.Item3[random.Next(planningForSelectedRoute.Item3.Count)]; double originalTravelTime = originalRoute.TravelTime; int numOfSlices = random.Next(1, originalRoute.Orders.Count - 2); List<int> sliceIndices = new List<int>(); for (int i = 1; i < numOfSlices; i++) { bool hasAddedAnIndex = false; do { int sliceIndex = random.Next(1, numOfSlices); if (!sliceIndices.Contains(sliceIndex)) { sliceIndices.Add(sliceIndex); hasAddedAnIndex = true; } } while (!hasAddedAnIndex); } sliceIndices.Sort(); // COMMENCE THE GENETIC EXPERIMENTS! // OPERATION SLICE & SPLICE AN ABOMINATION IS ACTIVE! List<Order>[] orderSlices = new List<Order>[sliceIndices.Count]; for (int i = 0; i < sliceIndices.Count; i++) { orderSlices[i] = new List<Order>(); int startIndex = i == 0 ? 0 : sliceIndices[i - 1]; for (int j = startIndex; j < sliceIndices[i]; j++) orderSlices[i].Add(originalRoute.Orders[j]); } // Now that you've sliced up the orders in the selected route, it is time for randomizing the slices and putting it back together Route firstAbominationRoute = new Route(originalRoute.Day); List<int> slicesIndexPutBack = new List<int>(); for (int i = 0; i < orderSlices.Length - 2; i++) { bool hasPutBackASlice = false; do { int sliceIndex = random.Next(1, orderSlices.Length - 1); if (!slicesIndexPutBack.Contains(sliceIndex)) { for (int j = 0; j < orderSlices[sliceIndex].Count; j++) if (orderSlices[sliceIndex][j].OrderNumber != 0) firstAbominationRoute.AddOrder(orderSlices[sliceIndex][j]); slicesIndexPutBack.Add(sliceIndex); hasPutBackASlice = true; } } while (!hasPutBackASlice); } // COMMENCE THE GENETIC EXPERIMENTS PHASE TWO! // OPERATION DARWIN'S ABOMINATION REPRODUCTION IS NOW OPERATIONAL! Route bestBoyAbominationOffspring = originalRoute; Route bestGirlAbominationOffspring = firstAbominationRoute; Boolean boyAbominationIsTheBest = bestBoyAbominationOffspring.TravelTime >= bestGirlAbominationOffspring.TravelTime; int numberOfGenesThatAreTransferred = originalRoute.Orders.Count / 2; List<Order> ordersSelectedForGeneticSwap = new List<Order>(); for (int numOfGenerationsToMake = 64; numOfGenerationsToMake > 0; numOfGenerationsToMake--) { ordersSelectedForGeneticSwap.Clear(); int orderIndex = -1; do { orderIndex = random.Next(orderSlices.Length - 1); // What? Order randomOrder = null; if (boyAbominationIsTheBest) randomOrder = bestBoyAbominationOffspring.Orders[orderIndex]; else randomOrder = bestGirlAbominationOffspring.Orders[orderIndex]; if (ordersSelectedForGeneticSwap.Contains(randomOrder)) continue; ordersSelectedForGeneticSwap.Add(randomOrder); } while (ordersSelectedForGeneticSwap.Count * 2 < numberOfGenesThatAreTransferred - 1); List<int> indicesToBeSwaped = new List<int>(); // Change into a array [2], to keep track which index belongs where foreach (Order order in ordersSelectedForGeneticSwap) { indicesToBeSwaped.Add(bestBoyAbominationOffspring.Orders.FindIndex(o => o == order)); indicesToBeSwaped.Add(bestGirlAbominationOffspring.Orders.FindIndex(o => o == order)); } indicesToBeSwaped.Sort(); Route newBoyAbominationOffspring = new Route(originalRoute.Day); Route newGirlAbominationOffspring = new Route(originalRoute.Day); for (int index = 0; index < originalRoute.Orders.Count - 1; index++) { if (indicesToBeSwaped.Contains(index)) // Erm.. What? { newBoyAbominationOffspring.AddOrder(bestGirlAbominationOffspring.Orders[index]); newGirlAbominationOffspring.AddOrder(bestBoyAbominationOffspring.Orders[index]); } else { newBoyAbominationOffspring.AddOrder(bestBoyAbominationOffspring.Orders[index]); newGirlAbominationOffspring.AddOrder(bestGirlAbominationOffspring.Orders[index]); } } if (newBoyAbominationOffspring.isValid() && !newGirlAbominationOffspring.isValid()) // One is allowed if (bestBoyAbominationOffspring.TravelTime < bestGirlAbominationOffspring.TravelTime) bestGirlAbominationOffspring = newBoyAbominationOffspring; else bestBoyAbominationOffspring = newBoyAbominationOffspring; else if (!newBoyAbominationOffspring.isValid() && newGirlAbominationOffspring.isValid()) // Other one allowed if (bestBoyAbominationOffspring.TravelTime < bestGirlAbominationOffspring.TravelTime) bestGirlAbominationOffspring = newGirlAbominationOffspring; else bestBoyAbominationOffspring = newGirlAbominationOffspring; else if (!newBoyAbominationOffspring.isValid() && !newGirlAbominationOffspring.isValid()) // Neither is allowed { numOfGenerationsToMake--; continue; } bool newGirlAbominationOffspringIstheBest = newBoyAbominationOffspring.TravelTime <= newGirlAbominationOffspring.TravelTime; if (boyAbominationIsTheBest) { if (newGirlAbominationOffspringIstheBest) { if (bestGirlAbominationOffspring.TravelTime < newGirlAbominationOffspring.TravelTime) { bestGirlAbominationOffspring = newGirlAbominationOffspring; if (bestBoyAbominationOffspring.TravelTime < newBoyAbominationOffspring.TravelTime) { bestBoyAbominationOffspring = newBoyAbominationOffspring; } } } else { if (bestGirlAbominationOffspring.TravelTime < newBoyAbominationOffspring.TravelTime) { bestGirlAbominationOffspring = newBoyAbominationOffspring; if (bestBoyAbominationOffspring.TravelTime < newGirlAbominationOffspring.TravelTime) { bestBoyAbominationOffspring = newGirlAbominationOffspring; } } } } else { if (newGirlAbominationOffspringIstheBest) { if (bestBoyAbominationOffspring.TravelTime < newGirlAbominationOffspring.TravelTime) { bestBoyAbominationOffspring = newGirlAbominationOffspring; if (bestGirlAbominationOffspring.TravelTime < newBoyAbominationOffspring.TravelTime) { bestGirlAbominationOffspring = newBoyAbominationOffspring; } } } else { if (bestBoyAbominationOffspring.TravelTime < newBoyAbominationOffspring.TravelTime) { bestBoyAbominationOffspring = newBoyAbominationOffspring; if (bestGirlAbominationOffspring.TravelTime < newGirlAbominationOffspring.TravelTime) { bestGirlAbominationOffspring = newGirlAbominationOffspring; } } } } boyAbominationIsTheBest = bestBoyAbominationOffspring.TravelTime >= bestGirlAbominationOffspring.TravelTime; numOfGenerationsToMake--; } // PHASE 3 - INSERT THE ABOMINATION INTO THE PUBLIC! bestAbominationOffspringRoute = boyAbominationIsTheBest ? bestBoyAbominationOffspring : bestGirlAbominationOffspring; Console.WriteLine("Original Travel Time: {0}", originalTravelTime); // These three lines are temporarily here Console.WriteLine("The First Abomination Travel Time: {0}", firstAbominationRoute.TravelTime); Console.WriteLine("Best Abomination Offspring Travel Time: {0}", bestAbominationOffspringRoute.TravelTime); toStartFrom.RemoveRouteFromPlanning(planningForSelectedRoute.Item1, planningForSelectedRoute.Item2, originalRoute); toStartFrom.AddRouteToPlanning(planningForSelectedRoute.Item1, planningForSelectedRoute.Item2, bestAbominationOffspringRoute); return toStartFrom; }