using System.Diagnostics; using System.Text.Json; using AntColony.Algorithm; namespace AntColony; class Program { /// /// Путь до файла с ребрами /// Файл представлен в формате JSON вместо TSV /// Файл содержит заголовок /// Количество итераций /// Количество муравьев /// Значение α (определяет вес феромонов) /// Значение β (определяет вес расстояния) /// Скорость испарения феромонов /// Значение Q public static void Main(FileInfo file, bool json = false, bool hasHeader = false, int iterations = 100, int ants = 20, double alpha = 1, double beta = 2, double evaporationRate = 0.1, double q = 100) { Console.Write("Чтение файла..."); var sw = new Stopwatch(); sw.Start(); double[][] distances = json ? ParseEdgeJsonAsync(file.FullName).Result! : ParseEdgeFile(file.FullName, hasHeader); Console.WriteLine($"\rСчитано {distances.Length} вершин за {sw.Elapsed} ({sw.ElapsedMilliseconds} мс).\n"); var aco = new AntColonyOptimizer( distances: distances, evaporationRate: evaporationRate ).AddAnts(1500).ShuffleAnts(); Console.CancelKeyPress += (e, f) => { var res = aco.EarlyExit(); Console.WriteLine($"\nРанняя остановка.\nЛучший путь: {string.Join(" -> ", res.tour)}\nДлина: {res.distance}"); }; sw.Restart(); var (bestTour, bestDistance) = aco.Solve(iterations); Console.WriteLine($"Задача решена за {sw.Elapsed} ({sw.ElapsedMilliseconds} мс)."); if (bestTour.Count == 0) { Console.WriteLine("Гамильтонов цикл не найден."); return; } Console.WriteLine($"Лучший путь: {string.Join(" -> ", bestTour)}."); Console.WriteLine($"Итоговое расстояние: {bestDistance}."); } private static async Task ParseEdgeJsonAsync(string filePath) { using var s = File.OpenRead(filePath); return await JsonSerializer.DeserializeAsync(s); } private static double[][] ParseEdgeFile(string filePath, bool skipHeader) { List lines = [.. File.ReadAllLines(filePath)]; if (skipHeader) lines.RemoveAt(0); HashSet vertices = []; int maxVertex = 0; foreach (string line in lines) { string[] parts = line.Split(); if (parts.Length != 3) continue; if (int.TryParse(parts[0], out int v1)) vertices.Add(v1); if (int.TryParse(parts[1], out int v2)) vertices.Add(v2); maxVertex = int.Max(maxVertex, v1); maxVertex = int.Max(maxVertex, v2); } double[][] adjacencyMatrix = new double[maxVertex + 1][]; for (int i = 0; i < maxVertex + 1; i++) { adjacencyMatrix[i] = new double[maxVertex + 1]; for (int j = 0; j < maxVertex + 1; j++) { adjacencyMatrix[i][j] = 0.0; } } foreach (string line in lines) { string[] parts = line.Split(); if (parts.Length != 3) continue; if (int.TryParse(parts[0], out int v1) && int.TryParse(parts[1], out int v2) && double.TryParse(parts[2], out double distance)) { adjacencyMatrix[v1][v2] = distance; adjacencyMatrix[v2][v1] = distance; } } return adjacencyMatrix; } }