コード例 #1
0
        private SolverState PerformStandardTest(
            Puzzle puzzle,
            ExitConditions exit = null,
            Func <SolverNode, bool>?inspector = null
            )
        {
            exit = exit ?? new ExitConditions
            {
                Duration       = TimeSpan.FromSeconds(60),
                StopOnSolution = true,
                TotalNodes     = int.MaxValue,
                TotalDead      = int.MaxValue
            };
            // arrange
            var solver  = new SingleThreadedForwardReverseSolver(new SolverNodeFactoryTrivial());
            var command = new SolverCommand
            {
                Puzzle         = puzzle.Clone(),
                Report         = new XUnitOutput(outp),
                ExitConditions = exit,
                Inspector      = inspector
            };

            // act
            var result = solver.Init(command);

            solver.Solve(result);
            Console.WriteLine(result.ExitDescription);
            Console.WriteLine(SolverHelper.GenerateSummary(result));
            result.ThrowErrors();

            // assert
            Assert.NotNull(result);

            Assert.True(result.HasSolution);
            Assert.NotNull(result.Solutions);
            Assert.NotEmpty(result.Solutions);

            foreach (var sol in result.Solutions)
            {
                Console.WriteLine("Path: {0}", sol);
                string error = null;
                Assert.True(SolverHelper.CheckSolution(command.Puzzle, sol, out error),
                            "Solution is INVALID! " + error);
            }

            return(result);
        }
コード例 #2
0
        public void Assemble()
        {
            var exit = new ExitConditions
            {
                Duration       = TimeSpan.FromSeconds(1),
                StopOnSolution = true,
                TotalNodes     = int.MaxValue,
                TotalDead      = int.MaxValue
            };
            var command = new SolverCommand
            {
                Puzzle = Puzzle.Builder.DefaultTestPuzzle(),

                ExitConditions = exit
            };

            // act
            var solver = new SingleThreadedForwardSolver(new SolverNodeFactoryTrivial());
            var result = solver.Init(command);

            solver.Solve(result);
            result.ThrowErrors();

            var root     = ((SolverBaseState)result).Root;
            var allNodes = root.Recurse().ToArray();

            var mem    = new MemoryStream();
            var writer = new BinaryNodeSerializer();

            using (var sw = new BinaryWriter(mem, Encoding.Unicode, true))
            {
                writer.Write(sw, allNodes);
            }

            outp.WriteLine($"Memory Stream Size = {allNodes.Length}nodes => {mem.Length}b");

            Assert.Equal(allNodes.Length, root.CountRecursive());

            mem.Seek(0, SeekOrigin.Begin);

            using (var sr = new BinaryReader(mem))
            {
                var t = writer.AssembleTree(sr);

                Assert.True(t.RecursiveAll().Any(x => x.Status != SolverNodeStatus.UnEval));
                Assert.Equal(root.CountRecursive(), t.CountRecursive());
            }
        }
コード例 #3
0
        public void ForwardReverseSingle()
        {
            var solverCommand = new SolverCommand()
            {
                Puzzle         = Puzzle.Builder.DefaultTestPuzzle(),
                ExitConditions = ExitConditions.Default3Min(),
            };
            var solver      = new SingleThreadedForwardReverseSolver(new SolverNodeFactoryTrivial());
            var solverState = solver.Init(solverCommand);

            solver.Solve(solverState);
            if (!solverState.HasSolution)
            {
                throw new Exception();
            }
        }
コード例 #4
0
        private 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         = new XUnitOutput(outp),
                ExitConditions = exit
            };

            // act
            var result = solver.Init(command);

            solver.Solve(result);
            Console.WriteLine(result.ExitDescription);
            Console.WriteLine(SolverHelper.GenerateSummary(result));
            result.ThrowErrors();

            // assert
            Assert.NotNull(result);
            Assert.NotNull(result.Solutions);
            Assert.True(result.HasSolution);


            foreach (var sol in result.Solutions)
            {
                string error = null;
                Assert.True(SolverHelper.CheckSolution(command.Puzzle, sol, out error),
                            "Solution is INVALID! " + error);
            }
        }
コード例 #5
0
        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);
            }
        }
コード例 #6
0
        public void Exhause()
        {
            var command = new SolverCommand
            {
                Puzzle = Puzzle.Builder.FromLines(new[]
                {
                    "##########",
                    "#O....XP.#",
                    "#O.....X.#",
                    "#O....X..#",
                    "##########"
                }),
                Report         = new XUnitOutput(outp),
                ExitConditions = new ExitConditions()
                {
                    StopOnSolution = false,
                    Duration       = TimeSpan.FromHours(1)
                }
            };

            var solver = new SingleThreadedForwardSolver(new SolverNodeFactoryTrivial());
            var state  = solver.Init(command) as SolverBaseState;
            var result = solver.Solve(state);

            //
            //
            // using (var f = File.CreateText(nameof(Exhause) + ".dot"))
            // {
            //     // dot .\Exhause.dot -o file.svg -T svg
            //     new GraphVisRender().Render(state.Root.Recurse(), f);
            // }
            //

            Assert.NotEmpty(state.Solutions);
            Assert.NotEmpty(state.Root.Children);
            Assert.True(state.Root.Recurse().All(x => ((SolverNode)x).IsClosed ||
                                                 x.Status == SolverNodeStatus.Solution ||
                                                 x.Status == SolverNodeStatus.SolutionPath));

            Assert.Equal(ExitConditions.Conditions.ExhaustedTree, result);
        }
コード例 #7
0
        public IActionResult StartFromFile(string file)
        {
            var fileName = Path.GetFileName(file);
            var ident    = PuzzleIdent.Parse(fileName.Substring(0, fileName.IndexOf("-")));
            var p        = compLib.GetPuzzleWithCaching(ident);

            var solver        = new MultiThreadedForwardReverseSolver(new SolverNodeFactoryPoolingConcurrentBag("byteseq"));
            var solverCommand = new SolverCommand()
            {
                Puzzle         = p.Puzzle,
                ExitConditions = new ExitConditions()
                {
                    Duration       = TimeSpan.FromMinutes(0),
                    StopOnSolution = true
                }
            };
            var model = new SolverModel()
            {
                Token   = DateTime.Now.Ticks,
                Puzzle  = p,
                Command = solverCommand,
            };

            staticState[model.Token] = model;

            model.Task = Task.Run(() =>
            {
                var ser = new BinaryNodeSerializer();
                using (var f = System.IO.File.OpenRead(file))
                {
                    using (var br = new BinaryReader(f))
                    {
                        model.RootForward = ser.AssembleTree(br);
                    }
                }
                model.IsFinished = true;
            });

            return(RedirectToAction("SolveMem", new { id = ident.ToString(), token = model.Token }));
        }
コード例 #8
0
        public void NoSolutions_InvalidPuzzle()
        {
            var command = new SolverCommand
            {
                Puzzle = Puzzle.Builder.FromLines(new[]
                {
                    // More goals than crates - strictly not valid
                    "##########",
                    "#O...X..O#",
                    "#O..XPX.O#",
                    "#O..X.X.O#",
                    "##########"
                }),
                Report         = new XUnitOutput(outp),
                ExitConditions = ExitConditions.OneMinute()
            };

            var solver = new SingleThreadedForwardSolver(new SolverNodeFactoryTrivial());

            Assert.Throws <InvalidDataException>(() =>
            {
                var state = solver.Init(command) as SolverBaseState;
            });
        }
コード例 #9
0
        public IActionResult SolveStart(string id, bool stopOnSolution, double duration = 1)
        {
            var ident = PuzzleIdent.Parse(id);
            var p     = compLib.GetPuzzleWithCaching(ident);

            var solver        = new MultiThreadedForwardReverseSolver(new SolverNodeFactoryPoolingConcurrentBag("byteseq"));
            var solverCommand = new SolverCommand()
            {
                Puzzle         = p.Puzzle,
                ExitConditions = new ExitConditions()
                {
                    Duration       = TimeSpan.FromMinutes(duration),
                    StopOnSolution = true
                }
            };
            var model = new SolverModel()
            {
                Token   = DateTime.Now.Ticks,
                Puzzle  = p,
                Command = solverCommand,
                State   = solver.Init(solverCommand)
            };

            staticState[model.Token] = model;

            model.Task = Task.Run(() =>
            {
                model.RootForward = model.State.GetRootForward();
                model.RootReverse = model.State.GetRootReverse();
                solver.Solve(model.State);

                model.IsFinished = true;
            });

            return(RedirectToAction("SolveMem", new { id, token = model.Token }));
        }
コード例 #10
0
        public static int SolverRun(string puzzle,
                                    int min, int sec,
                                    string solver, string pool,
                                    double minR, double maxR,
                                    SolverRun solverRun)
        {
            var args =
                new FluentString(" ")
                .Append(puzzle).Sep()
                .Append($"--solver {solver}").Sep()
                .Append($"--pool {pool}").Sep()
                .If(min > 0, $"--min {min}").Sep()
                .If(sec > 0, $"--sec {sec}").Sep()
                .If(minR > 0, $"--min-rating {minR}").Sep()
                .If(maxR < 2000, $"--min-rating {maxR}");

            System.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(Path.Combine(outFolder, outFile));
            var tele = new FileInfo(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();
                System.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(solver, pool).ToList();
            var countStrat = 0;

            foreach (var strat in perm)
            {
                countStrat++;
                System.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(min).Add(TimeSpan.FromSeconds(sec)),
                        MemAvail       = DevHelper.GiB_1, // Stops the machine hanging / swapping to death
                        StopOnSolution = true,
                    },
                    AggProgress = new ConsoleProgressNotifier(repTele),
                    CheckAbort  = x => exitRequested,
                };

                var runner = new BatchSolveComponent(
                    report,
                    System.Console.Out,
                    solutionRepo,
                    runTracking,
                    5,
                    false);

                var solverInstance = SolverFactory(strat.Solver, ioc);
                var summary        = runner.Run(solverRun, solverCommand, solverInstance, false);
                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
        }