public void SavePath(string outPathFileName, PathDesc pathDesc) { string outFileDir = Path.GetDirectoryName(outPathFileName); if (!Directory.Exists(outFileDir)) { Directory.CreateDirectory(outFileDir); } string[] items = { pathDesc.Cost.ToString(), string.Join(", ", pathDesc.Path) }; File.WriteAllLines(outPathFileName, items); }
public static void RunAlgorithm(string fileName, int repetitions, bool reportMemoryUsage, string outFileName, string outPathFileName) { Logger.GetLogger.LogNewFile(fileName); Graph graph = new Graph(fileName); Logger.GetLogger.LogGraph(graph); int bestCost = int.MaxValue; long bestTime = long.MaxValue; long avgTime = 0; long avgMemory = 0; for (int i = 0; i < repetitions; i++) { Stopwatch sw = Stopwatch.StartNew(); PathDesc result = FindBestCycle(graph, reportMemoryUsage, out long peakMemory); sw.Stop(); long timeMikros = sw.Elapsed.Ticks / (TimeSpan.TicksPerMillisecond / 1000); if (reportMemoryUsage) { Logger.GetLogger.Log(string.Format("Peak memory use: {0}", peakMemory)); } Logger.GetLogger.LogResult(result.Cost, timeMikros); Logger.GetLogger.LogPath(result); avgTime += timeMikros; avgMemory += peakMemory; if (result.Cost < bestCost) { bestCost = result.Cost; } if (timeMikros < bestTime) { bestTime = timeMikros; } if (i == repetitions - 1) { Logger.GetLogger.SavePath(outPathFileName, result); } } avgTime /= repetitions; avgMemory /= repetitions; Logger.GetLogger.SaveResults(graph.Name, outFileName, bestCost, bestTime, avgTime, avgMemory, graph.VertexCount); Logger.GetLogger.LogFinalResults(bestCost, bestTime, avgTime); }
public void LogPath(PathDesc pathDesc) { Console.WriteLine("Path:"); Console.WriteLine("Cost: {0}", pathDesc.Cost); Console.WriteLine(string.Join(", ", pathDesc.Path)); }
// Main loop of DP algorithm // Note: Start and end vertex is n - 1, not 0 public static PathDesc FindBestCycle(Graph graph, bool reportMemoryUsage, out long maxBytesMemory) { maxBytesMemory = 0; int n = graph.VertexCount; int cycleStart = graph.VertexCount - 1; Solution[] currentSolutions = new Solution[n - 1]; // Initialization for all paths i-j-cycleStart for (int i = 0; i < cycleStart; i++) { Solution sol = new Solution(); for (int j = 0; j < i; j++) { HashSet <int> vertexSet = new HashSet <int>(new List <int>() { j }); List <int> path = new List <int>() { i, j, cycleStart }; sol[vertexSet] = new PathDesc(graph[i, j] + graph[j, cycleStart], path); } for (int j = i + 1; j < cycleStart; j++) { HashSet <int> vertexSet = new HashSet <int>(new List <int>() { j }); List <int> path = new List <int>() { i, j, cycleStart }; sol[vertexSet] = new PathDesc(graph[i, j] + graph[j, cycleStart], path); } currentSolutions[i] = sol; } // k == number of edges on each path from the previous iteration for (int k = 2; k < n - 1; k++) { Solution[] nextSolutions = new Solution[n - 1]; for (int i = 0; i < cycleStart; i++) { Solution sol = new Solution(); // Iterate over all k-sized subsets of [n - 1]\{i, cycleStart} // (all previously found paths from jm to cycleStart of length k). // i is the start of the longer (k + 1 edges) path. // Find best shorter path jm...cycleStart to join i to. foreach ( HashSet <int> vertexSet in CombinationsWithout(cycleStart - 1, k, i)) { sol[vertexSet] = FindBestPath(graph, currentSolutions, i, vertexSet); } nextSolutions[i] = sol; } currentSolutions = nextSolutions; if (reportMemoryUsage) { var memory = GC.GetTotalMemory(true); if (memory > maxBytesMemory) { maxBytesMemory = memory; } } } // Get the final solution - join cycleStart to best (n - 1)-sized // jm...cycleStart path. HashSet <int> fullVertexSet = new HashSet <int>(Enumerable.Range(0, n - 1)); PathDesc bestCycle = FindBestPath(graph, currentSolutions, cycleStart, fullVertexSet); return(bestCycle); }