예제 #1
0
        // optimal cost of -1 represents no solution!
        private void TestSolver <TProblemState>(ISearchAlgorithm <TProblemState> solver, IProblem <TProblemState> problem, double optimalCost)
            where TProblemState : IProblemState <TProblemState>
        {
            output.WriteLine(solver.ToString());

            var    timer      = new Stopwatch();
            double lastTotalS = 0d;
            ulong  lastEvals  = 0UL;

            // https://docs.microsoft.com/en-us/dotnet/api/system.timers.timer?view=netframework-4.7.2
            var    reportingTimer     = new Timer(10_000);
            Action reportingHeartbeat = () => {
                var currentTotalS   = timer.Elapsed.TotalSeconds;
                var currentEvals    = solver.StatesEvaluated;
                var statesPerSecond = (currentEvals - lastEvals) / (currentTotalS - lastTotalS);
                output.WriteLine($"evals: {solver.StatesEvaluated:#,0}   ms: {timer.Elapsed.TotalMilliseconds}   S/s: {statesPerSecond:#,#.###}   cost: {solver.MaxCostEvaulated}");
                lastTotalS = currentTotalS;
                lastEvals  = currentEvals;
            };

            reportingTimer.Elapsed  += (Object source, ElapsedEventArgs e) => reportingHeartbeat();
            reportingTimer.AutoReset = true;
            reportingTimer.Enabled   = true;

            timer.Start();
            var solution = solver.Solve(problem);

            timer.Stop();
            reportingTimer.Enabled = false;

            reportingHeartbeat();
            output.WriteLine("Time: {0}", timer.Elapsed);

            if (solution == null)
            {
                Assert.True(optimalCost == -1d, "Found no solution but one should exist.");
            }
            else
            {
                var state = problem.GetInitialState();
                output.WriteLine("Initial State ----------------");
                output.WriteLine(state.ToString());
                int    i = 0;
                double stepCost, totalCost = 0d;
                foreach (var move in solution)
                {
                    i++;
                    (state, stepCost) = problem.ApplyAction(state, move);
                    totalCost        += stepCost;
                    //output.WriteLine(state.ToString());
                }
                output.WriteLine("Final State ({0} moves, {1} cost) ----------------", i, totalCost);
                output.WriteLine(state.ToString());
                Assert.True(problem.IsGoal(state), "Non-goal state claimed to be goal.");
                Assert.True(Math.Abs(optimalCost - totalCost) < 1e-8, "Found a non optimal cost: expected = " + optimalCost + "; actual = " + totalCost);
            }
        }
예제 #2
0
        public IProblemAction[] Solve(IProblem <TState> problem)
        {
            StatesEvaluated  = 0UL;
            MaxCostEvaulated = 0;

            var openSet   = new OpenSet <double, StateCost <TState> >();
            var closedSet = new HashSet <TState>();
            var cameFrom  = new Dictionary <TState, (TState parent, IProblemAction move)>();

            var initialState = problem.GetInitialState();

            openSet.PushOrImprove(0, new StateCost <TState>(initialState, 0));
            cameFrom.Add(initialState, (default(TState), null));

            while (!openSet.IsEmpty)
            {
                var next  = openSet.PopMin();
                var state = next.State;
                var cost  = next.Cost;
                closedSet.Add(state);
                StatesEvaluated++;
                MaxCostEvaulated = Math.Max(MaxCostEvaulated, cost);
                if (problem.IsGoal(state))
                {
                    return(RebuildSolution(cameFrom, state));
                }
                foreach (var move in problem.Expand(state))
                {
                    var(successor, stepCost) = problem.ApplyAction(state, move);
                    if (closedSet.Contains(successor))
                    {
                        continue;
                    }
                    var wasImprovement =
                        openSet.PushOrImprove(
                            cost + stepCost + heuristic(successor),
                            new StateCost <TState>(successor, cost + stepCost)
                            );
                    if (wasImprovement)
                    {
                        cameFrom[successor] = (state, move);
                    }
                }
            }
            return(null);
        }
예제 #3
0
        public IProblemAction[] Solve(IProblem <TState> problem)
        {
            StatesEvaluated  = 0UL;
            MaxCostEvaulated = 0;

            var openSet   = new OpenSet <double, StateCost <TState> >();
            var closedSet = new HashSet <TState>();
            var cameFrom  = new Dictionary <TState, (TState parent, IProblemAction move)>();

            var initialState = problem.GetInitialState();

            openSet.PushOrImprove(0, new StateCost <TState>(initialState, 0));
            cameFrom.Add(initialState, (default(TState), null));

            while (!openSet.IsEmpty)
            {
                var stateCost = openSet.PopMin();
                var state     = stateCost.State;
                var cost      = stateCost.Cost;
                closedSet.Add(state);
                StatesEvaluated++;
                MaxCostEvaulated = Math.Max(MaxCostEvaulated, cost);
                if (problem.IsGoal(state))
                {
                    return(RebuildSolution(cameFrom, state));
                }
                foreach (var move in problem.Expand(state))
                {
                    var(successor, stepCost) = problem.ApplyAction(state, move);
                    if (closedSet.Contains(successor))
                    {
                        continue;
                    }
                    // why is this 1 and not step cost? because that's how we enforce
                    // the BFS property of exploring on level fully before starting the next
                    var wasImprovement = openSet.PushOrImprove(cost + 1, new StateCost <TState>(successor, cost + 1));
                    if (wasImprovement)
                    {
                        cameFrom[successor] = (state, move);
                    }
                }
            }
            return(null);
        }
예제 #4
0
        private double Search(TState state, TState parent, double pathCost, Stack <IProblemAction> path, double bound)
        {
            var f = pathCost + heuristic(state);

            StatesEvaluated++;
            if (f > bound)
            {
                return(f);
            }
            if (problem.IsGoal(state))
            {
                return(FOUND);
            }
            var min     = double.MaxValue;
            var actions = problem.Expand(state);

            foreach (var action in actions)
            {
                var(successor, stepCost) = problem.ApplyAction(state, action);
                var successorPathCost = pathCost + stepCost;
                // TODO: so many assumptions here
                if (successor.Equals(parent))
                {
                    continue;
                }
                path.Push(action);
                var result = Search(successor, state, successorPathCost, path, bound);
                if (result == FOUND)
                {
                    return(FOUND);
                }
                min = Math.Min(min, result);
                path.Pop();
            }
            return(min);
        }