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;
}
}