namespace AntColony.Algorithm; /// public class DefaultAnt : IAnt { private readonly double alpha = 1; private readonly double beta = 1; private readonly double Q = 100; private List tour = []; private double distance = double.PositiveInfinity; /// public (List 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); } /// 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 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; } }