Ejemplo n.º 1
0
        public TowerOfHanoiTest()
        {
            // S ==> S
            // M ==> M
            // L ==> L
            // A  B  C
            //
            // Peg  = {A,B,C}
            // Disc = {S,M,L}

            hanoiDomain = new Domain().BuildLogic((domain, state) =>
            {
                state.Relations.Add(new Tuple<string, string, string>("Object Relation", "Disc Small", "Disc Medium"));
                state.Relations.Add(new Tuple<string, string, string>("Object Relation", "Disc Medium", "Disc Large"));
                state.Relations.Add(new Tuple<string, string, string>("Object Relation", "Disc Large", "Peg A"));

                Dictionary<string, int> ObjectRelativeOrder = new Dictionary<string, int>()
                {
                    {"Peg A", 0},
                    {"Peg B", 0},
                    {"Peg C", 0},
                    {"Disc Large", 1},
                    {"Disc Medium", 2},
                    {"Disc Small", 3}
                };
                Func<string, string, bool> IsValidConfiguration = (above, below) =>
                {
                    return (ObjectRelativeOrder[above] > ObjectRelativeOrder[below]);
                };

                Func<State, string, string> PeekStack = (State s, string peg) =>
                {
                    string item = null;
                    bool abort = false;
                    while (!abort)
                    {
                        try
                        {
                            peg = s.Relations.Find(rel => rel.Item1 == "Object Relation" && rel.Item3 == peg).Item2;
                            item = peg;
                        }
                        catch
                        {
                            abort = true;
                        }
                    }
                    if (item == null) return peg;
                    return item;
                };

                Func<State, string, string, bool> IsValidMove = (State st, string fromPeg, string toPeg) =>
                {
                    var itemToBeMoved = PeekStack(st, fromPeg);
                    // Only discs can be moved.
                    if (!itemToBeMoved.Contains("Disc")) return false;
                    return IsValidConfiguration(itemToBeMoved, PeekStack(st, toPeg));
                };

                Func<State, string, string, string> PopStack = (State s, string peg, string ontop) =>
                {
                    string item = null;
                    while (peg != null)
                    {
                        try
                        {
                            peg = s.Relations.Find(rel => rel.Item1 == "Object Relation" && rel.Item3 == peg).Item2;
                            item = peg;
                        }
                        catch
                        {
                            peg = null;
                        }
                    }
                    s.Relations.Remove(s.Relations.Find(rel => rel.Item1 == "Object Relation" && rel.Item2 == item));
                    return item;
                };

                Action<State, string, string> PushStack = (State st, string disc, string toPeg) =>
                {
                    st.Relations.Add(new Tuple<string, string, string>("Object Relation", disc, PeekStack(st, toPeg)));
                };

                Action<State, string, string> MoveItem = (State s, string fromPeg, string toPeg) =>
                {
                    PushStack(s, PopStack(s, fromPeg, null), toPeg);
                };

                state.PlanningActions.Add(new PlanningAction("Move A to B")
                                        .AssignPrejudicate(st => IsValidMove(st, "Peg A", "Peg B"))
                                        .AssignPostAction(st => MoveItem(st, "Peg A", "Peg B"))
                                       );
                state.PlanningActions.Add(new PlanningAction("Move A to C")
                                       .AssignPrejudicate(st => IsValidMove(st, "Peg A", "Peg C"))
                                       .AssignPostAction(st => MoveItem(st, "Peg A", "Peg C"))
                                       );
                state.PlanningActions.Add(new PlanningAction("Move B to A")
                                       .AssignPrejudicate(st => IsValidMove(st, "Peg B", "Peg A"))
                                       .AssignPostAction(st => MoveItem(st, "Peg B", "Peg A"))
                                       );
                state.PlanningActions.Add(new PlanningAction("Move B to C")
                                       .AssignPrejudicate(st => IsValidMove(st, "Peg B", "Peg C"))
                                       .AssignPostAction(st => MoveItem(st, "Peg B", "Peg C"))
                                       );
                state.PlanningActions.Add(new PlanningAction("Move C to A")
                                       .AssignPrejudicate(st => IsValidMove(st, "Peg C", "Peg A"))
                                       .AssignPostAction(st => MoveItem(st, "Peg C", "Peg A"))
                                       );
                state.PlanningActions.Add(new PlanningAction("Move C to B")
                                       .AssignPrejudicate(st => IsValidMove(st, "Peg C", "Peg B"))
                                       .AssignPostAction(st => MoveItem(st, "Peg C", "Peg B"))
                                       );
            }).AssignGoal(
                     new Goal("Solve Hanoi").RelationalTarget("Object Relation", "Disc Large", "Peg C")
                                            .RelationalTarget("Object Relation", "Disc Medium", "Disc Large")
                                            .RelationalTarget("Object Relation", "Disc Small", "Disc Medium")
            );
        }
Ejemplo n.º 2
0
        public void Solve()
        {
            puzzle = new Domain().BuildLogic((domain, state) =>
            {
                //
                //    01 02 03 04
                //    05 06 07 08
                //    09 10 11 12
                //    13 14 15
                //
                //
                string[] invalid_north = new string[] { "1", "2", "3", "4" };
                string[] invalid_east = new string[] { "4", "8", "12", "16" };
                string[] invalid_south = new string[] { "13", "14", "15", "16" };
                string[] invalid_west = new string[] { "1", "5", "9", "13" };

                Func<State, string> BlankPosition = (st) => { return st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item2 == "Blank").Item3; };
                Func<State, bool> CanFlipNorth = (st) => { return !invalid_north.Contains(BlankPosition(st)); };
                Func<State, bool> CanFlipEast = (st) => { return !invalid_east.Contains(BlankPosition(st)); };
                Func<State, bool> CanFlipSouth = (st) => { return !invalid_south.Contains(BlankPosition(st)); };
                Func<State, bool> CanFlipWest = (st) => { return !invalid_west.Contains(BlankPosition(st)); };

                Action<State> FlipNorth = (State st) =>
                {
                    var slot = st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item2 == "Blank").Item3;
                    int pos = int.Parse(slot);
                    string brick = st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item3 == (pos - 4).ToString()).Item2;
                    st.Relations.Remove(st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item3 == (pos - 4).ToString()));
                    st.Relations.Remove(st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item3 == (pos).ToString()));
                    st.Relations.Add(new Tuple<string, string, string>("Board", brick, pos.ToString()));
                    st.Relations.Add(new Tuple<string, string, string>("Board", "Blank", (pos - 4).ToString()));
                };
                Action<State> FlipEast = (State st) =>
                {
                    var slot = st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item2 == "Blank").Item3;
                    int pos = int.Parse(slot);
                    string brick = st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item3 == (pos + 1).ToString()).Item2;
                    st.Relations.Remove(st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item3 == (pos + 1).ToString()));
                    st.Relations.Remove(st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item3 == (pos).ToString()));
                    st.Relations.Add(new Tuple<string, string, string>("Board", brick, pos.ToString()));
                    st.Relations.Add(new Tuple<string, string, string>("Board", "Blank", (pos + 1).ToString()));
                };
                Action<State> FlipSouth = (State st) =>
                {
                    var slot = st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item2 == "Blank").Item3;
                    int pos = int.Parse(slot);
                    string brick = st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item3 == (pos + 4).ToString()).Item2;
                    st.Relations.Remove(st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item3 == (pos + 4).ToString()));
                    st.Relations.Remove(st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item3 == (pos).ToString()));
                    st.Relations.Add(new Tuple<string, string, string>("Board", brick, pos.ToString()));
                    st.Relations.Add(new Tuple<string, string, string>("Board", "Blank", (pos + 4).ToString()));
                };
                Action<State> FlipWest = (State st) =>
                {
                    var slot = st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item2 == "Blank").Item3;
                    int pos = int.Parse(slot);
                    string brick = st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item3 == (pos - 1).ToString()).Item2;
                    st.Relations.Remove(st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item3 == (pos - 1).ToString()));
                    st.Relations.Remove(st.Relations.Find(rel => rel.Item1 == "Board" && rel.Item3 == (pos).ToString()));
                    st.Relations.Add(new Tuple<string, string, string>("Board", brick, pos.ToString()));
                    st.Relations.Add(new Tuple<string, string, string>("Board", "Blank", (pos - 1).ToString()));
                };

                state.PlanningActions.Add(new PlanningAction("Flip North")
                                       .AssignPrejudicate(st => CanFlipNorth(st))
                                       .AssignPostAction(st => FlipNorth(st))
                                      );
                state.PlanningActions.Add(new PlanningAction("Flip East")
                                         .AssignPrejudicate(st => CanFlipEast(st))
                                         .AssignPostAction(st => FlipEast(st))
                                        );
                state.PlanningActions.Add(new PlanningAction("Flip South")
                                         .AssignPrejudicate(st => CanFlipSouth(st))
                                         .AssignPostAction(st => FlipSouth(st))
                                        );
                state.PlanningActions.Add(new PlanningAction("Flip West")
                                         .AssignPrejudicate(st => CanFlipWest(st))
                                         .AssignPostAction(st => FlipWest(st))
                                        );

                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 1", "1"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 2", "2"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 3", "13"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 4", "12"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 5", "11"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 6", "10"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 7", "9"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 8", "8"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 9", "7"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 10", "6"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 11", "5"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 12", "4"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 13", "3"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 14", "14"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Brick 15", "15"));
                state.Relations.Add(new Tuple<string, string, string>("Board", "Blank", "16"));
            }
            ).AssignGoal(
                new Goal("Solve Puzzle").RelationalTarget("Board", "Brick 15", "16")
            );

            // Todo: write custom goal that uses Manhattan Distance
            var cg =  new CustomGoal().AssignGoal(delegate(State x) { return 0.0; });
            var cg2 = new CustomGoal().AssignGoal( state => { return 0.0; });

            //puzzle.State.PlanningActions[0].Execute(puzzle.State);

            IPlan p = new DFSPlan().SetMaxSearchDepth(10);
            p.Search(puzzle.State, puzzle.Goal);

            Assert.GreaterOrEqual(puzzle.Goal.Fulfillment(p.GetFinalState()), 1.0);
        }