public void partialTwoOpt() { bool startAgain = false; PathCalculator calc = new PathCalculator(); int iterations = 0; int bestDistance = length; do { startAgain = false; for (int i = 1; i < path.Count - 1; i++) { if (startAgain) { break; } for (int j = i + 1; j < path.Count - 2; j++) { int dist = Params.distances[path[i - 1], path[i]] + Params.distances[path[j], path[j + 1]] - Params.distances[path[i - 1], path[j]] - Params.distances[path[i], path[j + 1]]; if (dist > 0) { path = modifyPath(path, i, j); bestDistance -= dist; startAgain = true; break; } } } iterations++; } while (startAgain && iterations < 5); }
public static List <int> tryInserting(List <int> path, HashSet <int> usedTowns) { List <int> currentPath = new List <int>(path); HashSet <int> availableTowns = new HashSet <int>(aT); foreach (int k in usedTowns) { availableTowns.Remove(k); } PathCalculator PO = new PathCalculator(); double currentPathLength = PO.calculateDistance(currentPath); double currentProfit = 0; foreach (int i in currentPath) { currentProfit += Parameters.profits[i]; availableTowns.Remove(i); } double bestPossibleGain = 0; int bestPossibleGainIndex = -1; int bestPossibleGainTown = -1; double bestPossibleGainLengthInc = 0; int iterations = 0; do { iterations++; bestPossibleGain = 0; bestPossibleGainIndex = 0; bestPossibleGainTown = -1; foreach (int i in availableTowns) { for (int x = 0; x < currentPath.Count - 1; x++) { double dist = Parameters.distances[currentPath[x], i] + Parameters.distances[i, currentPath[x + 1]] - Parameters.distances[currentPath[x], currentPath[x + 1]]; if (currentPathLength + dist <= Parameters.maxLength) { if (Parameters.profits[i] * Parameters.profits[i] * Parameters.profits[i] / (currentPathLength + dist) * Parameters.maxLength / (currentPathLength + dist) > bestPossibleGain) { bestPossibleGainLengthInc = Parameters.distances[currentPath[x], i] + Parameters.distances[i, currentPath[x + 1]] - Parameters.distances[currentPath[x], currentPath[x + 1]]; bestPossibleGain = Parameters.profits[i] * Parameters.profits[i] * Parameters.profits[i] / (currentPathLength + dist) * Parameters.maxLength / (currentPathLength + dist); bestPossibleGainIndex = x; bestPossibleGainTown = i; } } } } if (bestPossibleGainTown != -1) { currentPath.Insert(bestPossibleGainIndex + 1, bestPossibleGainTown); currentProfit += bestPossibleGain; availableTowns.Remove(bestPossibleGainTown); currentPathLength = PO.calculateDistance(currentPath); } } while (bestPossibleGain != 0 && currentPathLength <= Parameters.maxLength && iterations < Parameters.rand.Next(1)); return(currentPath); }
public static List <int> trySwapping(List <int> path) { List <int> currentPath = new List <int>(path); HashSet <int> availableTowns = new HashSet <int>(aT); PathCalculator PO = new PathCalculator(); List <int> added = new List <int>(); List <int> removed = new List <int>(); int currentPathLength = PO.calculateDistance(currentPath); double currentProfit = 0; foreach (int i in currentPath) { currentProfit += Params.profits[i]; availableTowns.Remove(i); } for (int i = 2; i < currentPath.Count - 1; i++) { if (currentPath[i] == 1) { continue; } foreach (int k in availableTowns) { if (Params.profits[k] >= Params.profits[path[i]]) { if (Params.profits[k] == Params.profits[path[i]]) { if (Params.distances[currentPath[i - 1], currentPath[i]] + Params.distances[currentPath[i], currentPath[i + 1]] > Params.distances[currentPath[i - 1], k] + Params.distances[k, currentPath[i + 1]]) { added.Add(currentPath[i]); removed.Add(k); currentPath[i] = k; } } else { if (currentPathLength - Params.distances[currentPath[i - 1], currentPath[i]] - Params.distances[currentPath[i], currentPath[i + 1]] + Params.distances[currentPath[i - 1], k] + Params.distances[k, currentPath[i + 1]] <= Params.maxLength) { added.Add(path[i]); removed.Add(k); currentPath[i] = k; } } } } foreach (int x in added) { availableTowns.Add(x); } foreach (int x in removed) { availableTowns.Remove(x); } added.Clear(); removed.Clear(); } return(currentPath); }
public void generateFixedIndividual(int startingTown, HashSet <int> usedTowns) { HashSet <int> availableTowns = new HashSet <int>(); ContainerForDuos bestTowns = new ContainerForDuos(5); PathCalculator calc = new PathCalculator(); double pathDistance = 0; for (int i = 0; i <= Parameters.numberOfTowns; i++) { if (i == startingTown || usedTowns.Contains(i)) { continue; } availableTowns.Add(i); } List <int> newPath = new List <int>(); newPath.Add(startingTown); profit = 0; profit += Parameters.profits[startingTown]; do { int k = Parameters.rand.Next(Parameters.To, Parameters.Td); bestTowns = new ContainerForDuos(k); foreach (int i in availableTowns) { double value = calculateValue(newPath[newPath.Count - 1], i, pathDistance, startingTown); if (value != -1) { bestTowns.Add(new Duo(value, i)); } } if (bestTowns.Count == 0) { pathDistance += Parameters.distances[newPath[newPath.Count - 1], startingTown]; newPath.Add(startingTown); break; } else { int t = Parameters.rand.Next(bestTowns.Count - 1); pathDistance += Parameters.distances[newPath[newPath.Count - 1], bestTowns.town(t)]; newPath.Add(bestTowns.town(t)); profit += Parameters.profits[bestTowns.town(t)]; availableTowns.Remove(bestTowns.town(t)); } }while (newPath[newPath.Count - 1] != startingTown); length = pathDistance; path = newPath; insertCapital(); partialTwoOpt(5); evaluatePath(); }
public static List <int> tryMoving(List <int> path) { List <int> bestPath = new List <int>(path); PathCalculator calc = new PathCalculator(); double bestPathProfit; double newProfit = 0; int bestPathDist; evaluatePath(bestPath, out bestPathDist, out bestPathProfit); for (int i = 1; i < bestPath.Count - 2; i++) { for (int j = 1; j < bestPath.Count - 3; j++) { if (i == j) { continue; } int newDist = bestPathDist; newProfit = 0; if (j == i + 1) { newDist = newDist - Params.distances[bestPath[i - 1], bestPath[i]] + Params.distances[bestPath[i - 1], bestPath[j]] + Params.distances[bestPath[i], bestPath[j + 1]] - Params.distances[bestPath[j], bestPath[j + 1]]; } else if (i == j + 1) { newDist += -Params.distances[bestPath[j - 1], bestPath[j]] + Params.distances[bestPath[j - 1], bestPath[j + 1]] + Params.distances[bestPath[j], bestPath[j + 1]]; } else if (i > j) { newDist = newDist - Params.distances[bestPath[i - 1], bestPath[i]] - Params.distances[bestPath[i], bestPath[i + 1]] - Params.distances[bestPath[j], bestPath[j + 1]] + Params.distances[bestPath[i - 1], bestPath[i + 1]] + Params.distances[bestPath[j], bestPath[i]] + Params.distances[bestPath[i], bestPath[j + 1]]; } else if (j > i) { newDist += -Params.distances[bestPath[j - 1], bestPath[j]] - Params.distances[bestPath[j], bestPath[j + 1]] - Params.distances[bestPath[i - 1], bestPath[i]] + Params.distances[bestPath[j - 1], bestPath[j + 1]] + Params.distances[bestPath[i - 1], bestPath[j]] + Params.distances[bestPath[j], bestPath[i]]; } if (newDist >= Params.maxLength) { continue; } List <int> newPath = new List <int>(bestPath); int tmp = newPath[i]; newPath.Remove(newPath[i]); newPath.Insert(j, tmp); newPath = tryInserting(newPath); evaluatePath(newPath, out newDist, out newProfit); if (newProfit > bestPathProfit) { bestPath = newPath; bestPathProfit = newProfit; bestPathDist = newDist; } } } return(bestPath); }