123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- using System.Collections.Concurrent;
- namespace AntColony.Algorithm;
- /// <summary>
- /// Алгоритм построения кратчайшего пути с помощью симуляции муравьиной колонии
- /// </summary>
- public class AntColonyOptimizer
- {
- private readonly int numberOfCities;
- private double[][] distances;
- private double[][] pheromones;
- private readonly double evaporationRate;
- private readonly int numberOfAnts;
- private readonly List<IAnt> xants = [];
- private IAnt[] ants;
- /// <summary>
- /// Инициализировать алгоритм
- /// </summary>
- /// <param name="distances">Матрица расстояний</param>
- /// <param name="numberOfAnts">Количество муравьев</param>
- /// <param name="evaporationRate">Скорость испарения</param>
- /// <param name="Q">Значение Q</param>
- public AntColonyOptimizer(double[][] distances, double evaporationRate = 0.1)
- {
- numberOfCities = distances.GetLength(0);
- this.distances = distances;
- this.evaporationRate = evaporationRate;
- // Строим стартовую матрицу феромонов
- pheromones = new double[numberOfCities][];
- for (int i = 0; i < numberOfCities; i++)
- {
- var r = new double[numberOfCities];
- for (int j = 0; j < numberOfCities; j++)
- {
- if (i != j)
- r[j] = 1.0; // Начальное значение
- }
- pheromones[i] = r;
- }
- }
- public AntColonyOptimizer AddAnts<T>(int count) where T : IAnt
- {
- for (int i = 0; i < count; i++)
- {
- xants.Add(Activator.CreateInstance<T>()!);
- }
- return this;
- }
- public AntColonyOptimizer ShuffleAnts()
- {
- ants = [.. xants];
- Random.Shared.Shuffle(ants);
- return this;
- }
- /// <summary>
- /// Обработчик ранней остановки работы алгоритма
- /// </summary>
- /// <returns>Лучший путь и его длину на текущий момент</returns>
- public (List<int> tour, double distance) EarlyExit() => (bestTourEver, bestDistanceEver);
- private List<int> bestTourEver = [];
- private double bestDistanceEver = double.PositiveInfinity;
- /// <summary>
- /// Решить задачу комивояжера (найти Гамильтонов цикл)
- /// </summary>
- /// <param name="maxIterations">Максимальное число итераций</param>
- /// <returns>Лучший путь и его расстояние</returns>
- public (List<int> bestTour, double bestDistance) Solve(int maxIterations)
- {
- // for (int iteration = 0; iteration < maxIterations; iteration++)
- for (int i = 0; i < maxIterations; i++)
- {
- ConcurrentBag<List<int>> antTours = [];
- ConcurrentBag<double> antDistances = [];
- Console.Write($"{i}/{maxIterations} - {bestDistanceEver}\r");
- // Каждый муравей строит путь
- var iterationTours = ants.AsParallel().Select(ant =>
- {
- var ct = ant.ConstructTour(ref distances, ref pheromones);
- if (!ct.HasValue) return ([], double.MaxValue);
- var (tour, distance) = ct.Value;
- antTours.Add(tour);
- antDistances.Add(distance);
- // Console.Write($"\r|- {i}/{numberOfAnts} - {distance}");
- return (tour, distance);
- });
- for (int j = 0; j < antTours.Count; j++)
- {
- ants[j].UpdatePheromones(ref pheromones);
- }
- // Console.Write(new string(' ', 20));
- // Console.CursorTop--;
- // Console.CursorLeft = 0;
- // Обновляем феромоны для всех путей
- EvaporatePheromones();
- // File.AppendAllText("./iteration-results", bestDistanceEver.ToString() + '\n');
- // }
- (List<int> Tour, double Distance) bestIterationTour = iterationTours.MinBy(x => x.distance);
- if (bestIterationTour.Distance < bestDistanceEver)
- {
- bestDistanceEver = bestIterationTour.Distance;
- bestTourEver = bestIterationTour.Tour;
- Console.WriteLine();
- }
- };
- return (bestTourEver, bestDistanceEver);
- }
- /// <summary>
- /// Обновить матрицу феромонов
- /// </summary>
- private void EvaporatePheromones()
- {
- // Испарение
- for (int i = 0; i < numberOfCities; i++)
- {
- for (int j = 0; j < numberOfCities; j++)
- {
- if (i != j)
- pheromones[i][j] *= 1.0 - evaporationRate;
- }
- }
- }
- }
|