DefaultAnt.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. namespace AntColony.Algorithm;
  2. /// <inheritdoc/>
  3. public class DefaultAnt : IAnt
  4. {
  5. private readonly double alpha = 1;
  6. private readonly double beta = 1;
  7. private readonly double Q = 100;
  8. private List<int> tour = [];
  9. private double distance = double.PositiveInfinity;
  10. /// <inheritdoc/>
  11. public (List<int> tour, double distance)? ConstructTour(ref double[][] distances, ref double[][] pheromones)
  12. {
  13. tour = [];
  14. distance = double.PositiveInfinity;
  15. var visited = new bool[distances.Length];
  16. var curCity = Random.Shared.Next(distances.Length);
  17. tour.Add(curCity);
  18. visited[curCity] = true;
  19. while (tour.Count < distances.Length)
  20. {
  21. var sel = SelectNextCity(curCity, ref visited, ref distances, ref pheromones);
  22. while (!sel.HasValue) sel = SelectNextCity(curCity, ref visited, ref distances, ref pheromones);
  23. if (sel is not { } nextCity) return null;
  24. tour.Add(nextCity);
  25. visited[nextCity] = true;
  26. curCity = nextCity;
  27. }
  28. if (distances[curCity][tour[0]] == 0) return null;
  29. tour.Add(tour[0]);
  30. distance = CalculateTourDistance(tour, ref distances);
  31. return (tour, distance);
  32. }
  33. /// <inheritdoc/>
  34. public void UpdatePheromones(ref double[][] pheromones)
  35. {
  36. double deposit = Q / distance;
  37. for (int i = 0; i < tour.Count - 1; i++)
  38. {
  39. int cityA = tour[i];
  40. int cityB = tour[i + 1];
  41. pheromones[cityA][cityB] += deposit;
  42. pheromones[cityB][cityA] += deposit; // Ненаправленный граф
  43. }
  44. }
  45. private static double CalculateTourDistance(List<int> tour, ref double[][] distances)
  46. {
  47. double distance = 0;
  48. for (int i = 0; i < tour.Count - 1; i++)
  49. {
  50. distance += distances[tour[i]][tour[i + 1]];
  51. }
  52. return distance;
  53. }
  54. private int? SelectNextCity(int currentCity, ref bool[] visited, ref double[][] distances, ref double[][] pheromones)
  55. {
  56. var probabilities = new double[distances.Length];
  57. double probabilitiesSum = 0;
  58. // Вероятности для каждого непосещенного города
  59. for (int i = 0; i < distances.Length; i++)
  60. {
  61. if (!visited[i])
  62. {
  63. if (distances[currentCity][i] == 0) continue;
  64. probabilities[i] = Math.Pow(pheromones[currentCity][i], alpha) *
  65. Math.Pow(1.0 / distances[currentCity][i], beta);
  66. probabilitiesSum += probabilities[i];
  67. }
  68. }
  69. // Случайно выбираем следующий город (по вероятностям)
  70. double randomValue = Random.Shared.NextDouble() * probabilitiesSum;
  71. //double sum = 0;
  72. for (int i = 0; i < distances.Length; i++)
  73. {
  74. if (!visited[i])
  75. {
  76. //sum += probabilities[i];
  77. if (probabilities[i] >= randomValue)
  78. {
  79. return i;
  80. }
  81. }
  82. }
  83. return null;
  84. }
  85. }