/// <summary> /// Calculates an efficient path between all waypoints based on time or distance. /// </summary> /// <param name="matrix">A precalculated distance matrix (n x n).</param> /// <param name="tspOptimization">The metric in which to base the TSP algorithm.</param> /// <returns>An efficient path between all waypoints based on time or distance.</returns> public override async Task <TspResult> Solve(DistanceMatrix matrix, TspOptimizationType tspOptimization) { return(await Task <TspResult> .Run <TspResult>(() => { var tour = new int[matrix.Origins.Count]; for (var i = 0; i < matrix.Origins.Count; i++) { tour[i] = i; } double minWeight = double.MaxValue; double weight; int[] minTour = tour; while (NextPermutation(tour)) { //Break out if the first location isn't in the first position. if (tour[0] != 0) { break; } if (tspOptimization == TspOptimizationType.TravelTime) { weight = matrix.GetEdgeTime(tour, true); } else { weight = matrix.GetEdgeDistance(tour, true); } if (weight < minWeight) { minWeight = weight; minTour = (int[])tour.Clone(); } } return new TspResult() { DistanceMatrix = matrix, OptimizedWeight = minWeight, OptimizedWaypoints = GetOptimizedWaypoints(matrix.Origins, minTour) }; })); }
///<summary> /// Solves the travelling salesmen problem. /// </summary> /// <param name="matrix">A precalculated distance matrix (n x n).</param> /// <param name="tspOptimization">The metric in which to base the TSP algorithm.</param> /// <returns>An efficient path between all waypoints based on time or distance.</returns> public static async Task <TspResult> Solve(DistanceMatrix matrix, TspOptimizationType tspOptimization) { return(await GetTspAlgorithm(matrix.Origins).Solve(matrix, tspOptimization).ConfigureAwait(false)); }
/// <summary> /// Calculates an efficient path between all waypoints based on time or distance. /// </summary> /// <param name="matrix">A precalculated distance matrix (n x n).</param> /// <param name="tspOptimization">The metric in which to base the TSP algorithm.</param> /// <returns>An efficient path between all waypoints based on time or distance.</returns> public override async Task <TspResult> Solve(DistanceMatrix matrix, TspOptimizationType tspOptimization) { return(await Task <TspResult> .Run <TspResult>(() => { int population = matrix.Origins.Count; double[] weight = new double[population]; var minTour = new int[population]; int[,] chromosome = new int[population, population]; double minWeight = double.MaxValue; for (int p = 0; p < population; p++) { bool[] used = new bool[population]; int[] currentOrder = new int[population]; for (int n = 0; n < population; n++) { used[n] = false; } for (int n = 0; n < population; n++) { int i; do { i = random.Next(population); }while (used[i]); used[i] = true; currentOrder[n] = i; } for (int n = 0; n < population; n++) { chromosome[p, n] = currentOrder[n]; } if (tspOptimization == TspOptimizationType.TravelTime) { weight[p] = matrix.GetEdgeTime(currentOrder, true); } else { weight[p] = matrix.GetEdgeDistance(currentOrder, true); } if (weight[p] < minWeight) { minWeight = weight[p]; for (int n = 0; n < population; n++) { minTour[n] = chromosome[p, n]; } } } for (int g = 0; g < Generations; g++) { if (random.NextDouble() < MutationRate) { int i, j, parent1, parent2; int[] p1 = new int[population]; int[] p2 = new int[population]; int[] o1 = new int[population]; int[] o2 = new int[population]; i = random.Next(population); j = random.Next(population); if (weight[i] < weight[j]) { parent1 = i; } else { parent1 = j; } i = random.Next(population); j = random.Next(population); if (weight[i] < weight[j]) { parent2 = i; } else { parent2 = j; } for (i = 0; i < population; i++) { p1[i] = chromosome[parent1, i]; p2[i] = chromosome[parent2, i]; } int cp1 = -1, cp2 = -1; do { cp1 = random.Next(population); cp2 = random.Next(population); } while (cp1 == cp2 || cp1 > cp2); Crossover(cp1, cp2, p1, p2, o1, o2, population, random); double o1Fitness; if (tspOptimization == TspOptimizationType.TravelTime) { o1Fitness = matrix.GetEdgeTime(o1, true); } else { o1Fitness = matrix.GetEdgeDistance(o1, true); } if (o1Fitness < weight[parent1]) { for (i = 0; i < population; i++) { chromosome[parent1, i] = o1[i]; } } double o2Fitness; if (tspOptimization == TspOptimizationType.TravelTime) { o2Fitness = matrix.GetEdgeTime(o2, true); } else { o2Fitness = matrix.GetEdgeDistance(o2, true); } if (o2Fitness < weight[parent2]) { for (i = 0; i < population; i++) { chromosome[parent2, i] = o2[i]; } } for (int p = 0; p < population; p++) { if (weight[p] < minWeight) { minWeight = weight[p]; for (int n = 0; n < population; n++) { minTour[n] = chromosome[p, n]; } } } } else { int i, j, p; int[] child = new int[population]; i = random.Next(population); j = random.Next(population); if (weight[i] < weight[j]) { p = i; } else { p = j; } double childWeight; for (int n = 0; n < population; n++) { child[n] = chromosome[p, n]; } do { i = random.Next(population); j = random.Next(population); }while (i == j); int t = child[i]; child[i] = child[j]; child[j] = t; if (tspOptimization == TspOptimizationType.TravelTime) { childWeight = matrix.GetEdgeTime(child, true); } else { childWeight = matrix.GetEdgeDistance(child, true); } int maxIndex = int.MaxValue; double maxD = double.MinValue; for (int q = 0; q < population; q++) { if (weight[q] >= maxD) { maxIndex = q; maxD = weight[q]; } } int[] index = new int[population]; int count = 0; for (int q = 0; q < population; q++) { if (weight[q] == maxD) { index[count++] = q; } } maxIndex = index[random.Next(count)]; if (childWeight < weight[maxIndex]) { weight[maxIndex] = childWeight; for (int n = 0; n < population; n++) { chromosome[maxIndex, n] = child[n]; } if (childWeight < minWeight) { minWeight = childWeight; for (int n = 0; n < population; n++) { minTour[n] = child[n]; } } } } } //Ensure first point is the starting point. Indicies form a cycle, so just need to shift. if (minTour[0] != 0) { var minTourList = minTour.ToList(); var startIdx = minTourList.IndexOf(0); var order = new List <int>(); order.AddRange(minTourList.GetRange(startIdx, minTourList.Count - startIdx)); order.AddRange(minTourList.GetRange(0, startIdx)); minTour = order.ToArray(); } return new TspResult() { DistanceMatrix = matrix, OptimizedWeight = minWeight, OptimizedWaypoints = GetOptimizedWaypoints(matrix.Origins, minTour) }; })); }
/// <summary> /// Calculates an efficient path between all waypoints based on time or distance. /// </summary> /// <param name="matrix">A precalculated distance matrix (n x n).</param> /// <param name="tspOptimization">The metric in which to base the TSP algorithm.</param> /// <returns>An efficient path between all waypoints based on time or distance.</returns> #pragma warning disable 1998 public virtual async Task <TspResult> Solve(DistanceMatrix matrix, TspOptimizationType tspOptimization) { throw new NotImplementedException(); }