123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- namespace AntColony.Algorithm;
- /// <inheritdoc/>
- public class DefaultAnt : IAnt
- {
- private readonly double alpha = 1;
- private readonly double beta = 1;
- private readonly double Q = 100;
- private List<int> tour = [];
- private double distance = double.PositiveInfinity;
- /// <inheritdoc/>
- public (List<int> tour, double distance)? ConstructTour(ref double[][] distances, ref double[][] pheromones)
- {
- tour = [];
- distance = double.PositiveInfinity;
- var visited = new bool[distances.Length];
- var curCity = Random.Shared.Next(distances.Length);
- tour.Add(curCity);
- visited[curCity] = true;
- while (tour.Count < distances.Length)
- {
- var sel = SelectNextCity(curCity, ref visited, ref distances, ref pheromones);
- while (!sel.HasValue) sel = SelectNextCity(curCity, ref visited, ref distances, ref pheromones);
- if (sel is not { } nextCity) return null;
- tour.Add(nextCity);
- visited[nextCity] = true;
- curCity = nextCity;
- }
- if (distances[curCity][tour[0]] == 0) return null;
- tour.Add(tour[0]);
- distance = CalculateTourDistance(tour, ref distances);
- return (tour, distance);
- }
- /// <inheritdoc/>
- public void UpdatePheromones(ref double[][] pheromones)
- {
- double deposit = Q / distance;
- for (int i = 0; i < tour.Count - 1; i++)
- {
- int cityA = tour[i];
- int cityB = tour[i + 1];
- pheromones[cityA][cityB] += deposit;
- pheromones[cityB][cityA] += deposit; // Ненаправленный граф
- }
- }
- private static double CalculateTourDistance(List<int> tour, ref double[][] distances)
- {
- double distance = 0;
- for (int i = 0; i < tour.Count - 1; i++)
- {
- distance += distances[tour[i]][tour[i + 1]];
- }
- return distance;
- }
- private int? SelectNextCity(int currentCity, ref bool[] visited, ref double[][] distances, ref double[][] pheromones)
- {
- var probabilities = new double[distances.Length];
- double probabilitiesSum = 0;
- // Вероятности для каждого непосещенного города
- for (int i = 0; i < distances.Length; i++)
- {
- if (!visited[i])
- {
- if (distances[currentCity][i] == 0) continue;
- probabilities[i] = Math.Pow(pheromones[currentCity][i], alpha) *
- Math.Pow(1.0 / distances[currentCity][i], beta);
- probabilitiesSum += probabilities[i];
- }
- }
- // Случайно выбираем следующий город (по вероятностям)
- double randomValue = Random.Shared.NextDouble() * probabilitiesSum;
- //double sum = 0;
- for (int i = 0; i < distances.Length; i++)
- {
- if (!visited[i])
- {
- //sum += probabilities[i];
- if (probabilities[i] >= randomValue)
- {
- return i;
- }
- }
- }
- return null;
- }
- }
|