private void GenerateReports(SolverState state, ISolver solver) { var r = state.Command.Report; if (r == null) { return; } var renderer = new MapToReportingRendererText(); var finalStats = solver.Statistics; if (finalStats != null) { r.WriteLine("### Statistics ###"); MapToReporting.Create <SolverStatistics>() .AddColumn("Name", x => x.Name) .AddColumn("Nodes", x => x.TotalNodes) .AddColumn("Avg. Speed", x => x.NodesPerSec) .AddColumn("Duration (sec)", x => x.DurationInSec) .AddColumn("Duplicates", x => x.Duplicates < 0 ? null : (int?)x.Duplicates) .AddColumn("Dead", x => x.TotalDead < 0 ? null : (int?)x.TotalDead) .AddColumn("Current Depth", x => x.DepthCurrent < 0 ? null : (int?)x.DepthCurrent) .RenderTo(finalStats, renderer, Report); } var repDepth = MapToReporting.Create <SolverHelper.DepthLineItem>() .AddColumn("Depth", x => x.Depth) .AddColumn("Total", x => x.Total) .AddColumn("UnEval", x => x.UnEval) .AddColumn("Complete", x => (x.Total - x.UnEval) * 100 / x.Total, c => c.ColumnInfo.AsPercentage()); if (state is MultiThreadedSolverState multi) { r.WriteLine("### Forward Tree ###"); repDepth.RenderTo(SolverHelper.ReportDepth(multi.Root), renderer, r); r.WriteLine("### Reverse Tree ###"); repDepth.RenderTo(SolverHelper.ReportDepth(multi.RootReverse), renderer, r); } }
public int SolverRun(BatchArgs batchArgs, SolverRun run) { var args = new FluentString(" ") .Append(batchArgs.Puzzle).Sep() .Append($"--solver {batchArgs.Solver}").Sep() .Append($"--pool {batchArgs.Pool}").Sep() .If(batchArgs.Min > 0, $"--min {batchArgs.Min}").Sep() .If(batchArgs.Sec > 0, $"--sec {batchArgs.Sec}").Sep() .If(batchArgs.MinR > 0, $"--min-rating {batchArgs.MinR}").Sep() .If(batchArgs.MaxR < 2000, $"--min-rating {batchArgs.MaxR}"); batchArgs.Console.WriteLine($"Arguments: {args}"); var exitRequested = false; SolverCommand?executing = null; // Setup: Report and cancellation var benchId = DateTime.Now.ToString("s").Replace(':', '-'); var outFile = $"./benchmark--{benchId}.txt"; var outTele = $"./telemetry--{benchId}.csv"; var outFolder = "./results/"; if (!Directory.Exists(outFolder)) { Directory.CreateDirectory(outFolder); } var info = new FileInfo(System.IO.Path.Combine(outFolder, outFile)); var tele = new FileInfo(System.IO.Path.Combine(outFolder, outTele)); using var report = File.CreateText(info.FullName); using var repTele = File.CreateText(tele.FullName); System.Console.CancelKeyPress += (o, e) => { report.Flush(); batchArgs.Console.WriteLine("Ctrl+C detected; cancel requested"); if (executing != null) { executing.ExitConditions.ExitRequested = true; } exitRequested = true; }; ISokobanSolutionRepository?solutionRepo = File.Exists("./solutions.json") && !DevHelper.IsDebug() ? new JsonSokobanSolutionRepository("./solutions.json") : null; ISolverRunTracking?runTracking = null; var results = new List <(Strategy, List <SolverResultSummary>)>(); var perm = GetPermutations(batchArgs.Solver, batchArgs.Pool).ToList(); var countStrat = 0; foreach (var strat in perm) { countStrat++; batchArgs.Console.WriteLine($"(Strategy {countStrat}/{perm.Count}) {strat}"); var ioc = new SolverContainerByType(new Dictionary <Type, Func <Type, object> >() { { typeof(ISolverPool), _ => PoolFactory(strat.Pool) }, { typeof(ISolverQueue), _ => new SolverQueueConcurrent() }, { typeof(ISolverRunTracking), _ => runTracking }, { typeof(ISokobanSolutionRepository), _ => solutionRepo }, }); var solverCommand = new SolverCommand { ServiceProvider = ioc, ExitConditions = new ExitConditions() { Duration = TimeSpan.FromMinutes(batchArgs.Min).Add(TimeSpan.FromSeconds(batchArgs.Sec)), MemAvail = DevHelper.GiB_1 / 2, // Stops the machine hanging / swapping to death StopOnSolution = true, }, AggProgress = new ConsoleProgressNotifier(repTele), CheckAbort = x => exitRequested, }; var runner = new SingleSolverBatchSolveComponent( new TextWriterAdapter(report), batchArgs.Console, solutionRepo, runTracking, 5, false); var solverInstance = SolverFactory(strat.Solver, ioc); var summary = runner.Run(run, solverCommand, solverInstance, false, batchArgs); results.Add((strat, summary)); } // Header var extras = new Dictionary <string, string>() { { "Args", args }, { "Report", info.FullName } }; DevHelper.WriteFullDevelopmentContext(report, extras); DevHelper.WriteFullDevelopmentContext(System.Console.Out, extras); // Body var reportRow = GenerateReport(results).ToList(); MapToReporting.Create <SummaryLine>() .AddColumn("Solver", x => x.Strategy.Solver) .AddColumn("Pool", x => x.Strategy.Pool) .AddColumn("Puzzle", x => x.Result.Puzzle.Ident) .AddColumn("State", x => x.Result.Exited) .AddColumn("Solutions", x => (x.Result.Solutions?.Count ?? 0) == 0 ? null : (int?)x.Result.Solutions.Count) .AddColumn("Statistics", x => x.Result.Exited == ExitConditions.Conditions.Error ? x.Result.Exited.ToString() : x.Result.Statistics?.ToString(false, true) ) .RenderTo(reportRow, new MapToReportingRendererText(), report) .RenderTo(reportRow, new MapToReportingRendererText(), System.Console.Out); return(results.Any(x => x.Item2.Any(y => y.Exited == ExitConditions.Conditions.Error)) ? -1 : 0); // All exceptions }
public static void Run(string file, string report) { System.Console.WriteLine($"<file> {file} --report {report}"); var ser = new BinaryNodeSerializer(); if (report == "depth") { using (var f = System.IO.File.OpenRead(file)) { using (var br = new BinaryReader(f)) { System.Console.WriteLine($"Reading File..."); var root = ser.AssembleTree(br); var repDepth = MapToReporting.Create <SolverHelper.DepthLineItem>() .AddColumn("Depth", x => x.Depth) .AddColumn("Total", x => x.Total) .AddColumn("Growth Rate", x => x.GrowthRate) .AddColumn("UnEval", x => x.UnEval) .AddColumn("Complete", x => (x.Total - x.UnEval) * 100 / x.Total, c => c.ColumnInfo.AsPercentage()); repDepth.RenderTo(SolverHelper.ReportDepth(root), new MapToReportingRendererText(), System.Console.Out); } } } else if (report == "clash") { using (var f = File.OpenRead(file)) { var writer = new BinaryNodeSerializer(); var nodes = writer.ReadAll(new BinaryReader(f)); Dictionary <int, ClashLineItem> hash = new Dictionary <int, ClashLineItem>(); foreach (var n in nodes) { if (hash.TryGetValue(n.HashCode, out var c)) { c.Count++; if (c.First.CrateMap.Equals(n.CrateMap) && c.First.MoveMap.Equals(n.MoveMap)) { c.Dups++; } } else { hash[n.HashCode] = new ClashLineItem() { Hash = n.HashCode, Count = 1, First = n }; } } var items = hash.Where(x => x.Value.Count > 1).OrderByDescending(x => x.Value.Dups).ThenByDescending(x => x.Value.Count).Take(50).Select(x => x.Value); MapToReporting.Create <ClashLineItem>() .AddColumn("Hash", x => x.Hash) .AddColumn("Count", x => x.Count) .AddColumn("Dups", x => x.Dups) .RenderTo(items, new MapToReportingRendererText(), System.Console.Out); System.Console.WriteLine($"Total Dups: {hash.Values.Sum(x=>x.Dups)}"); } } else if (report == "dump") { using (var f = File.OpenRead(file)) { var writer = new BinaryNodeSerializer(); using (var br = new BinaryReader(f)) { foreach (var node in writer.ReadAll(br).OrderBy(x => x.SolverNodeId).Take(20)) { System.Console.WriteLine(node); } } } } else { throw new Exception($"Unknown Report: {report}"); } }