public void WriteDefaultForwardSolution() { var exit = new ExitConditions { Duration = TimeSpan.FromSeconds(10), StopOnSolution = true, TotalNodes = int.MaxValue, TotalDead = int.MaxValue }; var command = new SolverCommand { Puzzle = Puzzle.Builder.DefaultTestPuzzle(), ExitConditions = exit, Inspector = (s) => { if (s.GetHashCode() == 30759) { outp.WriteLine(s.ToString()); return(true); } return(false); } }; // act var solver = new SingleThreadedForwardSolver(new SolverNodeFactoryTrivial()); var result = solver.Init(command); solver.Solve(result); result.ThrowErrors(); Assert.True(result.HasSolution); var root = ((SolverBaseState)result).Root; using (var f = File.Create(Path.Combine(TestHelper.GetDataPath(), "./SavedState/SQ1~P1-default.ssbn"))) { var writer = new BinaryNodeSerializer(); writer.WriteTree(new BinaryWriter(f), root); } }
public List <SolverResultSummary> Run( SolverRun run, SolverCommand baseCommand, ISolver solver, bool showSummary, BatchSolveComponent.BatchArgs?batchArgs = null) { if (run == null) { throw new ArgumentNullException(nameof(run)); } if (baseCommand == null) { throw new ArgumentNullException(nameof(baseCommand)); } if (solver == null) { throw new ArgumentNullException(nameof(solver), "See: " + nameof(SingleThreadedForwardSolver)); } Report.WriteLine("Puzzle Exit Conditions: {0}", run.PuzzleExit); Report.WriteLine("Batch Exit Conditions : {0}", run.BatchExit); Report.WriteLine("Environment : {0}", DevHelper.RuntimeEnvReport()); Report.WriteLine("Solver Environment : v{0} -- {1}", SolverHelper.VersionUniversal, SolverHelper.VersionUniversalText); Report.WriteLine("Started : {0}", DateTime.Now.ToString("u")); Report.WriteLine(); var res = new List <SolverResultSummary>(); var start = new SolverStatistics { Started = DateTime.Now }; SolverState?state = null; var pp = 0; var consecutiveFails = 0; foreach (var puzzle in run) { if (baseCommand.CheckAbort(baseCommand)) { Progress.WriteLine("EXITING..."); break; } try { pp++; Progress.WriteLine($"(Puzzle {pp}/{run.Count}) Attempting: {puzzle.Ident} \"{puzzle.Name}\", R={StaticAnalysis.CalculateRating(puzzle.Puzzle)}. Stopping on [{baseCommand.ExitConditions}] ..."); Report.WriteLine(" Name: {0}", puzzle); Report.WriteLine(" Ident: {0}", puzzle.Ident); Report.WriteLine(" Rating: {0}", StaticAnalysis.CalculateRating(puzzle.Puzzle)); Report.WriteLine(puzzle.Puzzle.ToString()); // Adds 2x line feeds IReadOnlyCollection <SolutionDTO> existingSolutions = null; if (SkipPuzzlesWithSolutions && Repository != null) { existingSolutions = Repository.GetPuzzleSolutions(puzzle.Ident); if (existingSolutions != null && existingSolutions.Any( x => x.MachineName == Environment.MachineName && x.SolverType == solver.GetType().Name)) { Progress.WriteLine("Skipping... (SkipPuzzlesWithSolutions)"); continue; } } // #### Main Block Start -------------------------------------- var memStart = GC.GetTotalMemory(false); var attemptTimer = new Stopwatch(); attemptTimer.Start(); state = solver.Init(new SolverCommand(baseCommand) { Report = Report, Puzzle = puzzle.Puzzle }); var propsReport = GetPropReport(solver, state); Tracking?.Begin(state); try { solver.Solve(state); } catch (Exception e) { state.Exception = e; state.Exit = ExitConditions.Conditions.Error; state.EarlyExit = true; } var memEnd = GC.GetTotalMemory(false); state.Statistics.MemUsed = memEnd; var memDelta = memEnd - memStart; var bytesPerNode = memDelta / state.Statistics.TotalNodes; var maxNodes = (ulong)0; if (DevHelper.TryGetTotalMemory(out var totalMem)) { maxNodes = totalMem / (ulong)bytesPerNode; } Report.WriteLine($"Memory Used: {Humanise.SizeSuffix(memEnd)}, delta: {Humanise.SizeSuffix(memDelta)} ~ {bytesPerNode:#,##0} bytes/node => max nodes:{maxNodes:#,##0}"); attemptTimer.Stop(); // #### Main Block End ------------------------------------------ state.Summary = new SolverResultSummary( puzzle, state.Solutions, state.Exit, SolverHelper.GenerateSummary(state), attemptTimer.Elapsed, state.Statistics ); res.Add(state.Summary); start.TotalNodes += state.Statistics.TotalNodes; start.TotalDead += state.Statistics.TotalDead; Report.WriteLine("[DONE] {0}", state.Summary.Text); Progress.WriteLine($" -> {state.Summary.Text}"); if (batchArgs != null && batchArgs.Save != null) { Console.WriteLine(" -> Saving..."); var binSer = new BinaryNodeSerializer(); var rootForward = state.GetRootForward(); if (rootForward != null) { var outState = System.IO.Path.Combine(batchArgs.Save, $"{puzzle.Ident}-forward.ssbn"); using (var f = File.Create(outState)) { using (var bw = new BinaryWriter(f)) { binSer.WriteTree(bw, rootForward); } } Report.WriteLine($"\tSaving State: {outState}"); Progress.WriteLine($"\tSaving State: {outState}"); } var rootReverse = state.GetRootReverse(); if (rootReverse != null) { var outState = System.IO.Path.Combine(batchArgs.Save, $"{puzzle.Ident}-reverse.ssbn"); using (var f = File.Create(outState)) { using (var bw = new BinaryWriter(f)) { binSer.WriteTree(bw, rootReverse); } } Report.WriteLine($"\tSaving State: {outState}"); Progress.WriteLine($"\tSaving State: {outState}"); } } // Add Depth Reporting Console.WriteLine(" -> Generating Reports..."); GenerateReports(state, solver); if (Repository != null) { var id = StoreAttempt(solver, puzzle, state, propsReport.ToString()); if (id >= 0) { var solTxt = $"Checking against known solutions. SolutionId={id}"; Report.WriteLine(solTxt); Console.WriteLine(solTxt); } } else { Report.WriteLine($"Solution Repository not available: Skipping."); } if (state?.Summary?.Solutions != null && state.Summary.Solutions.Any()) // May have been removed above { consecutiveFails = 0; } else { consecutiveFails++; if (StopOnConsecutiveFails != 0 && consecutiveFails > StopOnConsecutiveFails) { Progress.WriteLine("ABORTING... StopOnConsecutiveFails"); break; } } Tracking?.End(state); if (state.Exception != null) { Report.WriteLine("[EXCEPTION]"); WriteException(Report, state.Exception); } if (state.Exit == ExitConditions.Conditions.Aborted) { Progress.WriteLine("ABORTING..."); if (showSummary) { WriteSummary(res, start); } return(res); } if (start.DurationInSec > run.BatchExit.Duration.TotalSeconds) { Progress.WriteLine("BATCH TIMEOUT..."); if (showSummary) { WriteSummary(res, start); } return(res); } Progress.WriteLine(); } catch (Exception ex) { if (state != null) { state.Exception = ex; } Progress.WriteLine("ERROR: " + ex.Message); WriteException(Report, ex); } finally { state = null; if (puzzle != run.Last()) { GC.Collect(); } } } if (showSummary) { WriteSummary(res, start); } Report.WriteLine("Completed : {0}", DateTime.Now.ToString("u")); return(res); }