public void SingleThreadedForwardSolver_TreePoolPerformance() { // IDEA: This puzzle has a relatively large amount of FLOOR space, which will create lots of Nodes in the TreePool // arrange var solver = new SingleThreadedForwardSolver(); var command = new SolverCommand() { Puzzle = new Puzzle(new String[] { "##########", "#O.......#", "#O.......#", "#O.......#", "#....X...#", "#...XPX..#", "#........#", "##########" }), Report = Console.Out, ExitConditions = ExitConditions.OneMinute }; // act var result = solver.Init(command) as SolverBase.CommandResult; solver.Solve(result); Console.WriteLine(result.ExitDescription); Console.WriteLine(SolverHelper.Summary(result)); result.ThrowErrors(); // assert Assert.That(result, Is.Not.Null); }
public void SingleThreadedForwardSolver_BaseLine_Quick() { // arrange var solver = new SingleThreadedForwardSolver(); var command = new SolverCommand() { Puzzle = new Puzzle(), Report = Console.Out, ExitConditions = new ExitConditions() { Duration = TimeSpan.FromSeconds(10), StopOnSolution = true, TotalNodes = 10000 } }; // act var result = solver.Init(command) as SolverBase.CommandResult; solver.Solve(result); Console.WriteLine(result.ExitDescription); Console.WriteLine(SolverHelper.Summary(result)); result.ThrowErrors(); // assert Assert.That(result, Is.Not.Null); }
public void BasicThreading() { var pTxt = @"###########~ #P..#..#..#~ #..X#X...X#~ ##..#OO#..#~ ~#..#OO#..#~ ~#..#OO#..## ~#X...X#X..# ~#..#..#...# ~###########"; var puzzle = new Puzzle(pTxt); var exit = new ExitConditions() { Duration = TimeSpan.FromSeconds(60), StopOnSolution = true, TotalNodes = int.MaxValue, TotalDead = int.MaxValue }; // arrange var solver = new MultiThreadedForwardReverseSolver(); var command = new SolverCommand() { Puzzle = new Puzzle(puzzle), Report = Console.Out, ExitConditions = exit, Progress = new ConsoleProgressNotifier() }; // act var result = solver.Init(command); solver.Solve(result); Assert.That(result, Is.Not.Null); Console.WriteLine(result.ExitDescription); Console.WriteLine(SolverHelper.Summary(result)); result.ThrowErrors(); // assert Assert.That(result, Is.Not.Null); }
private SolverCommandResult PerformStandardTest(Puzzle puzzle, ExitConditions exit = null) { exit = exit ?? new ExitConditions() { Duration = TimeSpan.FromSeconds(60), StopOnSolution = true, TotalNodes = int.MaxValue, TotalDead = int.MaxValue }; // arrange var solver = new SingleThreadedForwardReverseSolver(); var command = new SolverCommand() { Puzzle = new Puzzle(puzzle), Report = Console.Out, ExitConditions = exit }; // act var result = solver.Init(command); solver.Solve(result); Console.WriteLine(result.ExitDescription); Console.WriteLine(SolverHelper.Summary(result)); result.ThrowErrors(); // assert Assert.That(result, Is.Not.Null); Assert.That(result.HasSolution, Is.True); Assert.That(result.GetSolutions(), Is.Not.Null); Assert.That(result.GetSolutions(), Is.Not.Empty); foreach (var sol in result.GetSolutions()) { Console.WriteLine("Path: {0}", sol); string error = null; Assert.That(SolverHelper.CheckSolution(command.Puzzle, sol, out error), "Solution is INVALID! " + error); } return result; }
public virtual SolverCommandResult Init(SolverCommand command) { var state = new CommandResult() { Command = command, Solutions = new List<SolverNode>(), SolutionsWithReverse = new List<SolutionChain>(), Forward = new SolverData() { Evaluator = new ForwardEvaluator(), Queue = new SolverQueue(), PoolForward = new SolverNodeLookup() }, Reverse = new SolverData() { Evaluator = new ReverseEvaluator(), Queue = new SolverQueue(), PoolReverse = new SolverNodeLookup() } }; state.Forward.PoolReverse = state.Reverse.PoolReverse; state.Reverse.PoolForward = state.Forward.PoolForward; state.StaticMaps = StaticAnalysis.Generate(command.Puzzle); state.StaticMaps.DeadMap = DeadMapAnalysis.FindDeadMap(state.StaticMaps); state.Forward.Root = state.Forward.Evaluator.Init(command.Puzzle, state.Forward.Queue); state.Reverse.Root = state.Reverse.Evaluator.Init(command.Puzzle, state.Reverse.Queue); Statistics = new SolverStatistics[] { state.Statistics, state.Forward.PoolForward.Statistics, state.Reverse.PoolReverse.Statistics, state.Forward.Queue.Statistics, state.Reverse.Queue.Statistics }; return state; }
public SolverCommand(SolverCommand rhs) { if (rhs == null) throw new ArgumentNullException("rhs"); Puzzle = rhs.Puzzle; Report = rhs.Report; ExitConditions = rhs.ExitConditions; CheckAbort = rhs.CheckAbort; Progress = rhs.Progress; Debug = rhs.Debug; }
public List<Result> Run(SolverRun run, SolverCommand baseCommand, ISolver solver = null) { if (solver == null) { solver = new SingleThreadedForwardSolver(); } Report.WriteLine("Puzzle Exit Conditions: {0}", run.PuzzleExit); Report.WriteLine("Batch Exit Conditions : {0}", run.BatchExit); Report.WriteLine("Solver : {0}", SolverHelper.Describe(solver)); Report.WriteLine("CPU : {0}", DebugHelper.GetCPUDescription()); Report.WriteLine("Machine : {0} {1}", Environment.MachineName, Environment.Is64BitProcess ? "x64" : "x32"); Report.WriteLine(); var res = new List<Result>(); var start = new SolverStatistics() { Started = DateTime.Now }; SolverCommandResult result = null; int pp = 0; int consecutiveFails = 0; foreach (var puzzle in run) { if (baseCommand.CheckAbort(baseCommand)) { Progress.WriteLine("EXITING..."); break; } try { pp++; Progress.WriteLine("Attempting: {0} ({2}/{3}); Rating: {1}", PuzzleHelper.GetName(puzzle), StaticAnalysis.CalculateRating(puzzle), pp, run.Count); var libPuzzle = puzzle as LibraryPuzzle; Report.WriteLine(" Name: {0}", PuzzleHelper.GetName(puzzle)); Report.WriteLine(" Ident: {0}", libPuzzle != null ? libPuzzle.Ident : null); Report.WriteLine(" Rating: {0}", StaticAnalysis.CalculateRating(puzzle)); Report.WriteLine("Starting Memory: {0}", Environment.WorkingSet); Report.WriteLine(puzzle.ToString()); PuzzleDTO dto = null; if (Repository != null) { dto = Repository.Get(puzzle); if (dto == null) { dto = Repository.ToDTO(puzzle); Repository.Store(dto); } dto.Solutions = Repository.GetSolutions(dto.PuzzleId); } if (SkipPuzzlesWithSolutions) { if (dto != null && dto.Solutions.Exists(x=>x.HostMachine == Environment.MachineName && x.SolverType == solver.GetType().Name)) { Progress.WriteLine("Skipping... (SkipPuzzlesWithSolutions)"); continue; } } Report.WriteLine(); result = solver.Init(new SolverCommand(baseCommand) { Report = Report, ExitConditions = run.PuzzleExit, Puzzle = puzzle, }); if (Tracking != null) Tracking.Begin(result); solver.Solve(result); var r = new Result() { Summary = SolverHelper.Summary(result), Exited = result.Exit, Solutions = result.GetSolutions() }; res.Add(r); start.TotalNodes += result.Statistics.TotalNodes; start.TotalDead += result.Statistics.TotalDead; if (r.Solutions.Any()) { int cc = 0; foreach (var p in r.Solutions.ToArray()) { string error = null; var check = SolverHelper.CheckSolution(puzzle, p, out error); Report.WriteLine("Solution #{0} [{1}] =>\n{2}", cc++, check ? "Valid":"INVALID!"+error, p); if (!check) { r.Solutions.Remove(p); r.Summary += " (INVALID SOLUTION)"; } } // Write to DB? if (dto != null) { if (Repository != null) { StoreSolution(solver, dto, r.Solutions); } } } if (r.Solutions.Any()) // May have been removed above { consecutiveFails = 0; } else { consecutiveFails++; if (StopOnConsecutiveFails != 0 && consecutiveFails > StopOnConsecutiveFails) { Progress.WriteLine("ABORTING... StopOnConsecutiveFails"); break; } } var finalStats = solver.Statistics; if (finalStats != null) { foreach (var fs in finalStats) { Report.WriteLine("Statistics | {0}", fs); } } if (Tracking != null) Tracking.End(result); Report.WriteLine("[DONE] {0}", r.Summary); if (result.Exception != null) { Report.WriteLine("[EXCEPTION]"); WriteException(Report, result.Exception); } Progress.WriteLine(); Progress.WriteLine("Completed: {0} ==> {1}", PuzzleHelper.GetName(puzzle), r.Summary); Progress.WriteLine(); if (result.Exit == ExitConditions.Conditions.Aborted) { Progress.WriteLine("ABORTING..."); WriteSummary(res, start); return res; } if (start.DurationInSec > run.BatchExit.Duration.TotalSeconds) { Progress.WriteLine("BATCH TIMEOUT..."); WriteSummary(res, start); return res; } Progress.WriteLine(); } catch (Exception ex) { if (result != null) result.Exception = ex; Progress.WriteLine("ERROR: "+ex.Message); WriteException(Report, ex); } finally { result = null; Report.WriteLine("Ending Memory: {0}", Environment.WorkingSet); GC.Collect(); Report.WriteLine("Post-GC Memory: {0}", Environment.WorkingSet); Report.WriteLine("==================================="); Report.WriteLine(); } Report.Flush(); } WriteSummary(res, start); return res; }
protected virtual bool Tick(SolverCommand command, CommandResult state, ISolverQueue queue, out SolverCommandResult solve) { state.Statistics.DepthCompleted = queue.Statistics.DepthCompleted; state.Statistics.DepthMax = queue.Statistics.DepthMax; if (command.Progress != null) { command.Progress.Update(this, state, state.Statistics); } if (command.CheckAbort != null) { if (command.CheckAbort(command)) { state.Exit = ExitConditions.Conditions.Aborted; state.EarlyExit = true; state.Statistics.Completed = DateTime.Now; solve = state; return true; } } var check = command.ExitConditions.ShouldExit(state); if (check != ExitConditions.Conditions.Continue) { state.EarlyExit = true; state.Statistics.Completed = DateTime.Now; state.Exit = check; solve = state; return true; } solve = null; return false; }
public virtual SolverCommandResult Init(SolverCommand command) { var state = SolverHelper.Init(new CommandResult(), command); state.Statistics.Name = GetType().Name;; state.Pool = new SolverNodeLookup() { Report = command.Report }; state.Evaluator = evaluator; state.Queue= new SolverQueue(); state.Root = state.Evaluator.Init(command.Puzzle, state.Queue); Statistics = new SolverStatistics[] { state.Statistics, state.Pool.Statistics, state.Queue.Statistics }; return state; }
public void SingleThreadedForwardSolver_TreePoolPerformance_Large() { Console.WriteLine("IDEA: This puzzle has a relatively large amount of FLOOR space, which will create lots of Nodes in the TreePool"); Console.WriteLine("[WILLOW: Started prep for multi-threading] 52000 nodes at 851.658640168867 nodes/sec. Exited EARLY. Time => Nodes: 52000, Dead: 0, Duration: 61.0573269 sec., Duplicates: 236306"); Console.WriteLine("[WILLOW: Collection optimistion] 59000 nodes at 980.895125589307 nodes/sec. Exited EARLY. Time => Nodes: 59000, Dead: 0, Duration: 60.1491418 sec., Duplicates: 274401"); Console.WriteLine("[Added Buffered inserts] 68000 nodes at 1129.36134313775 nodes/sec. Exited EARLY. Time => Nodes: 68000, Dead: 0, Duration: 60.2110214 sec., Duplicates: 476102"); // arrange var solver = new SingleThreadedForwardSolver(); var command = new SolverCommand() { Puzzle = new Puzzle(new String[] { "##########", "#O.......#", "#O.....X.#", "#O.......#", "#........#", "#........#", "#....X...#", "#...XPX..#", "#....O...#", "##########" }), Report = Console.Out, ExitConditions = new ExitConditions() { Duration = TimeSpan.FromMinutes(1), TotalNodes = int.MaxValue, TotalDead = int.MaxValue, StopOnSolution = false // !!!!!! }, Progress = new ConsoleProgressNotifier() }; // act var result = solver.Init(command) as SolverBase.CommandResult; solver.Solve(result); Console.WriteLine(SolverHelper.Summary(result)); result.ThrowErrors(); Console.WriteLine("All Nodes"); Console.WriteLine( (result as SingleThreadedForwardSolver.CommandResult).Pool.ToString()); // assert Assert.That(result, Is.Not.Null); }
void PuzzleShouldHaveSolution(ISolver solver, Puzzle puzzle, ExitConditions exit = null, bool verbose = false) { if (exit == null) { exit = new ExitConditions() { Duration = TimeSpan.FromSeconds(60), StopOnSolution = true, TotalNodes = int.MaxValue, TotalDead = int.MaxValue }; } var command = new SolverCommand() { Puzzle = puzzle, Report = Console.Out, Progress = new ConsoleProgressNotifier(), ExitConditions = exit }; // act var result = solver.Init(command); solver.Solve(result); Console.WriteLine(result.ExitDescription); Console.WriteLine(SolverHelper.Summary(result)); result.ThrowErrors(); // assert Assert.That(result, Is.Not.Null); Assert.That(result.HasSolution, Is.True); foreach (var sol in result.GetSolutions()) { Console.WriteLine("Path: {0}", sol); string error = null; Assert.That(SolverHelper.CheckSolution(command.Puzzle, sol, out error), "Solution is INVALID! "+error); } }
public SolverCommandResult Init(SolverCommand command) { var prog = command.Progress; command.Progress = null; var poolForward = new ThreadSafeSolverNodeLookupWrapper(); poolForward.Statistics.Name = "Forward Pool"; var poolReverse = new ThreadSafeSolverNodeLookupWrapper(); poolReverse.Statistics.Name = "Reverse Pool"; var queueForward = new ThreadSafeSolverQueueWrapper(new SolverQueue()); queueForward.Statistics.Name = "Forward Queue"; var queueReverse = new ThreadSafeSolverQueueWrapper(new SolverQueue()); queueReverse.Statistics.Name = "Reverse Queue"; current = new CommandResult() { PoolForward = poolForward, PoolReverse = poolReverse, Command = command, Statistics = new SolverStatistics() { Name = GetType().Name, Started = DateTime.Now }, StatsInner = new List<SolverStatistics>(), Workers = new List<Worker> { // First Pair new ForwardWorker() { Name = "F1", Command = command, Pool = poolForward, PoolSolution = poolReverse, Queue = queueForward }, new ForwardWorker() { Name = "F2", Command = command, Pool = poolForward, PoolSolution = poolReverse, Queue = queueForward }, new ForwardWorker() { Name = "F3", Command = command, Pool = poolForward, PoolSolution = poolReverse, Queue = queueForward }, new ForwardWorker() { Name = "F4", Command = command, Pool = poolForward, PoolSolution = poolReverse, Queue = queueForward }, new ReverseWorker() { Name = "R1", Command = command, Pool = poolReverse, PoolSolution = poolForward, Queue =queueReverse }, new ReverseWorker() { Name = "R2", Command = command, Pool = poolReverse, PoolSolution = poolForward, Queue = queueReverse }, new ReverseWorker() { Name = "R3", Command = command, Pool = poolReverse, PoolSolution = poolForward, Queue = queueReverse }, new ReverseWorker() { Name = "R4", Command = command, Pool = poolReverse, PoolSolution = poolForward, Queue = queueReverse } }, }; current.StatsInner.Add(current.Statistics); current.StatsInner.Add(poolForward.Statistics); current.StatsInner.Add(poolReverse.Statistics); current.StatsInner.Add(current.Statistics); current.StatsInner.Add(queueForward.Statistics); current.StatsInner.Add(queueReverse.Statistics); var tmp = command.Progress; command.Progress = null; foreach (var worker in current.Workers) { worker.Owner = this; worker.OwnerState = current; worker.Init(); if (worker.Solver.Statistics != null) { current.StatsInner.AddRange(worker.Solver.Statistics); } worker.Task = new Task<Worker>(x => Execute((Worker)x), worker, TaskCreationOptions.LongRunning); } command.Progress = tmp; // Init queues current.Workers.First(X => X.Evaluator is ForwardEvaluator).Evaluator.Init(command.Puzzle, queueForward); current.Workers.First(X => X.Evaluator is ReverseEvaluator).Evaluator.Init(command.Puzzle, queueReverse); current.Progress = new ProgressUpater(this, current); current.ProgressTask = new Task(current.Progress.Worker); command.Progress = prog; return current; }
private bool CheckWorkerAbort(SolverCommand arg) { return !Worker.OwnerState.IsRunning; }
public override SolverCommandResult Init(SolverCommand command) { var state = SolverHelper.Init(new CommandResult(), command); state.Command.Progress = null; state.Command.Parent = Worker.Owner; state.Command.CheckAbort = CheckWorkerAbort; state.Statistics.Name = GetType().Name; ; state.Pool = Worker.Pool; state.Evaluator = new ReverseEvaluator(); state.Queue = Worker.Queue; Statistics = new SolverStatistics[] { state.Statistics }; return state; }
public override SolverCommandResult Init(SolverCommand command) { var state = SolverHelper.Init(new CommandResult(), command); state.Command.Parent = Worker.Owner; state.Command.CheckAbort = x => !Worker.OwnerState.IsRunning; state.Statistics.Name = GetType().Name; state.Pool = Worker.Pool; state.Evaluator = new ForwardEvaluator(); state.Queue = Worker.Queue; Statistics = new SolverStatistics[] { state.Statistics}; return state; }