The Eight Puzzle - Who is Robert S. Goldstein?

advertisement
The Eight Puzzle
By: Robert Goldstein
Prepared for CS661- Artificial Intelligence I
Professor Tony Grgas
Table of Contents
0.
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Test System____________________________________________________
Introduction____________________________________________________
Breadth First Search (BFS) ________________________________________
A* Search _____________________________________________________
3.1 A* Search using the Manhattan Distance Heuristic__________________
3.2 A* Search using the Tiles Out of Place Heuristic___________________
3.3 A* Search using Greedy Search_________________________________
Language of Choice for Project_____________________________________
How is the Eight Puzzle represented in the program?_____________________
How was the BFS was implemented?_________________________________
How was the A* Search implemented?________________________________
7.1 How was the Manhattan Distance Heuristic implemented?____________
7.2 How was the Tiles Out of Place Heuristic implemented?_____________
7.3 How was the A* Search using Greedy Search implemented?___________
How Random is Randomize Tiles?___________________________________
Results from Searches_____________________________________________
Known Bugs____________________________________________________
10.1 Display of Breadth First Search (BFS)____________________________
10.2 Depth Problem With Respect To Breath First Search (BFS)___________
10.3 Depth Problem With Respect To A* Searches______________________
10.4 Applet Usage Problem With Respect To Microsoft Internet Explorer__
10.5 Applet Usage Problem With Respect To Netscape Navigator________
Page 2 of 14
3
3
4
5
5
6
6
6
7
7
8
11
12
12
12
13
13
13
13
13
14
14
0. Test System
I used my home PC in order to do the testing for the project. The specifications of interest for it
are:
Pentium 150 MHz
64 Megabytes Ram
10.4 Gig HDD
4 Megabytes VRAM Video card
1. Introduction
The Eight puzzle is the largest puzzle of its type that can be completely solved. It is simple, and
yet obeys a combinatorially large problem space of 9!/2 states. The N*N extension of the 8puzzle is NP-hard.
It is a game in which there are eight 1 x 1 tiles arranged on a 3 x 3 square so that there is one 1 x
1 uncovered area on the square. The tiles are labeled 1 through 8, and initially they are arranged
in some random order. A tile with a face adjacent to the uncovered area can be transferred to the
uncovered area in a single move. The goal of the puzzle is to place them in order, as in
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 4 | 5 | 6 |
+---+---+---+
| 7 | 8 |
|
+---+---+---+
Figure 1. Goal State of Eight Puzzle
Therefore, the following formulation makes up the Eight-Puzzle problem:
 States: a state description specifies the location of each of the eight tiles in one of the
nine squares. For efficiency, it is useful to include the location of the blank.
 Operators: blank moves left, right, up, or down.
 Goal test: state matches the goal configuration (as seen above in Figure 1).
 Path cost: each step costs 1, so the path cost is just the length of the path.
For this problem, I will demonstration how to solve the eight puzzle using three methods: (1)
Breadth First Search (BFS), (2) A* Search using the Manhattan Distance heuristic, and (3) A*
Search using the number of tiles out of place heuristic.
Page 3 of 14
2. Breadth First Search (BFS)
Breadth-first search (BFS) is one of the simpler search algorithms. In method, the root node of
the search tree is expanded first, then all the nodes generated by the root node are expanded next,
and then their successors until it reaches a terminating/goal state of the search. In most cases, all
the nodes at depth d in the search tree are expanded before the nodes at depth d+1. This method
is very systematic because it considers all paths at one level before moving onto future levels of
the search tree (looks at all nodes at level 1 before going onto level 2). BFS is a complete
algorithm because if there is a solution, it will find it. It is also generates an optimal solution
provided the path cost is a non-decreasing function of the depth of the node (not using a path cost
function determine where to expand next).
This method has some drawbacks to it. This is because a result of the time and memory factor.
As the search algorithm navigates down the search tree the amount of nodes it needs to evaluate
increments by a factor of bd, where b is the branching factor and d is the depth the search is
currently at. Now suppose that the solution for the problem has a path length of d. The maximum
number of node which need to be expanded before finding the solution would be equivalent to:
# Nodes Expanded  1  b  b 2  b 3  ...  b d
Figure 2. BFS Node Expansion example from d = 0 to d = 2
This is the maximum number, but the solution could be found at any point on level d, therefore
in the best case, this number would be smaller. As a result, the time and memory complexity are
both a ratio of O(bd).
Page 4 of 14
Figure 3. BFS depth requirements on time and memory
3. A* Search
The A* Search is a part of a class of algorithms called Best-First Search. This class of searching
uses an evaluation function in order to determine the desirability (or lack thereof) of expanding a
node. The name of this class of search algorithms is sort of misleading because if the search was
able to directly pick the best node first, it would be a straight marsh to the Goal State instead of a
search. However, what actually happens is that it chooses the node that appears to be the best
node according to the evaluation function.
The A* search makes its determination via the summation of two sub-functions in order to
produce the evaluation function. There sub-functions provide the total path cost so far, g(n), and
an admissible heuristic1, h(n), which is used to minimize the estimated path cost to the goal state.
Therefore, this search method is optimal and complete. This means that it will in the end, always
find a solution and it will be the best one.
3.1 A* Search using the Manhattan Distance Heuristic
Using the Manhattan distance heuristic with the A* search is good algorithm use if you would
like to keep the keep the search from retreating in depth too much. This algorithm uses the sum
of the distances of the tiles from their goal positions. Because tile cannot move along diagonals,
the distance counted will be the sum of the horizontal and vertical distances. This heuristic is
admissible, because any move can only move one tile one step closer to the goal. Below is the
result of this heuristic when tiles 1 to 8 are in the following Start State:
1
An admissible heuristic never overestimates the cost to reach the Goal State. This optimism of this transfers
through to the f function as well. If h is admissible, f(n) never overestimates the actual cost of the best solution
through n.
Page 5 of 14
+---+---+---+
| 5 | 4 |
|
+---+---+---+
| 6 | 1 | 8 |
+---+---+---+
| 7 | 3 | 2 |
+---+---+---+
Manhattan Distance = 2 + 3 + 3 + 2 + 4 + 2 + 0 + 2 = 18
Figure 4. Manhattan Distance Heuristic
3.2 A* Search using the Tiles Out of Place Heuristic
The Tiles Out of Place heuristic is a fine algorithm to use with A* search. The heuristic involves
summing the number of tiles that are not in their correct location for the Goal State. This
heuristic is admissible, because it is clear that any tile that is out of place must be moved at least
once. Below is the result of this heuristic when tiles 1 to 8 are in the following Start State:
+---+---+---+
| 5 | 4 |
|
+---+---+---+
| 6 | 1 | 8 |
+---+---+---+
| 7 | 3 | 2 |
+---+---+---+
Tiles Out of Place = 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 = 7
Figure 5. Tiles Out of Place Heuristic
3.3 A* Search using Greedy Search
The Greedy Search is one of the simplest algorithms to use. This is because there is no additional
heuristic to aid you besides the total path cost so far, g(n). As a result, many nodes that should
not be expanded are and additional time is needed in order to find the correct solution.
4. Language of Choice for Project
The language that I picked for this project was Java. This is because this project is a
demonstration of how to solve the Eight Puzzle with different algorithms. JAVA is a very good
language for this purpose, especially with its ability to quickly create graphics and its delightful
similarity to the common Object Oriented Language (OOP), C++. Consequently, this project will
displayable from a Web page or via Java’s Appletviewer, i.e. it is platform-independent.
Page 6 of 14
Figure 6. Main Screen of Project as seen through Java’s Appletviewer
5. How is the Eight Puzzle represented in the program?
The Eight Puzzle is represented inside of the program as a one-dimensional array of integers,
starting from 0 to the size of the dimensions of the board –1. The dimensions are specified within
the HTML file EightPuzzle.html via the parameters x and y, whereby the dimensions of the
board are equal to x*y. The blank location is specified by another parameter in the previously
mentioned HTML file and is labeled BLANK. It has a number from 0 to the size of the
dimensions of the board – 1.
Each value inside of the array initially corresponds to the array index, i.e. puzzle[0] = 0. The
initial representation is Goal State. Each initial value of the array 0, 1, 2… also corresponds to a
piece of an image specified in the previously mentioned HTML file as parameter IMAGE.
6. How was the BFS was implemented?
Breadth First Search (BFS) was implemented using a queue. The queue stores its values in a
linked list, therefore the size is able to increase or decrease with copying all currently stored data
into a larger array. A queue is a simple way to accomplish BFS because it needs to go down and
across the search tree in order to find a solution. By using a queue, the program appends all valid
child nodes onto the queue for later checking. The program is going through every combination
and therefore it does not know the order of how it reached the goal, i.e. order of moves made.
Below are the procedures used to accomplish BFS.
Page 7 of 14
Let cCount = the number of nodes that possibly
at current depth
Let fCount = the number of nodes that possibly
at current depth + 1, i.e. future
Let nodes = the number of nodes evaluated
Let depth = the expected depth for finding the
current depth looking at
need to be checked
need to be checked
depth
solution, i.e. the
1. Remove a node state from queue.
2. If cCount = 0, then Increment depth by 1. Set cCount = fCount
and fCount = 0.
3. If all tiles are in correct location, add 1 to nodes and Done!
Otherwise continue to step 3.
4. Create all valid future nodes for that state and append to
queue. Increment fCount by 1 for valid future nodes.
5. Reduce cCount by 1.
6. Increment nodes by 1.
7. Go to step 1.
Figure 7. Procedures for Implemented BFS
7. How was the A* Search implemented?
The A* Search algorithm, described generally in section 3, uses two heuristics, g(n) and h(n), to
determine which path to continue reviewing of the open leaves (nodes) on the Search Tree. For
the Eight Puzzle problem, the total path cost so far, g(n), is an increment of 1 tile per move.
Each of admissible heuristics will be described in the following subsections.
From reading section 3, it can be seen that the A* Search is a bit complex as compared to the
BFS implementation described in section 6. This is because you need to keep track of all of the
open nodes on the Search Tree while keeping track of the total cost from the heuristics for each
open node. For the purposes of this project, hash-tables and vectors were used. The vectors and
hash-tables were used to keep track of the different nodes on the search tree that need to be
examined throughout the search to see if they are better than the current best path so far. Below
are the procedures used to accomplish the A* Search.
Page 8 of 14
Let nodes = A vector that contains all open children nodes from
the best node sorted by least total cost
Let best = The first node in nodes vector. The node under
consideration for future expansion.
Let bestTotal = the best total of all nodes evaluated.
Let open = A hash-table that contains all open nodes on the
Search Tree. It is used to make sure that there is no
duplicates saved and only keeping the best around.
Let closed = A hash-table that contains the nodes that have
already been expanded on the Search Tree. It is used
insuring that the correct path is not over looked.
Let theNode = A temporary variable that holds the node under
examination.
Let children = A vector that contains children of best,
temporarily, until added to the nodes vector.
1. Set best = the first node in nodes vector.
2. If best’s heuristic total != bestTotal, then set bestTotal =
best’s heuristic total
3. If best is the Goal State, then Done! Recurse through best back
to the Start State and store all values in Vector (path through
the Search Tree to reach the Goal State), so it can be shown
graphically to user by manipulating the tiles.
4. Clean up past children from last run.
5. Generate best’s children.
6. Produce best’s children’s g(n), 1 + best’s cost.
7. Increment expanded depth by 1.
8. Examine of best’s children individually using the following
steps:
a. Obtain next child state, and clear out closedNode (temp var),
openNode (temp var), theNode.
b. If the child state is not in the closed table (store in
closedNode), then try to obtain it from the open table (store
in openNode).
c. If openNode isn’t “null”, then theNode = openNode, otherwise
theNode = closedNode.
d. Determine whether theNode isn’t “null”.
i. If theNode isn’t “null”
1. Check to see if theNode’s costs are > the best’s
children’s costs. If they are:
a. If closedNode isn’t “null”
i.
Put theNode into the open table with the
child state as the key.
ii.
Remove the value in the closed table with the
child state as the key.
iii. Set theNode’s costs = the child’s costs
iv.
Set theNode’s total = the theNode’s new cost
+ theNode’s distance.
v.
Set theNode’s parent to the best node.
vi.
Add theNode to the children vector.
Page 9 of 14
b. If closedNode is “null”
i. Set theNode = a new node for the child state,
with the parent as the best node, costs as the
child’s costs, and the distance as theNode’s
distance.
ii. Put theNode into the open table with the
child state as the key.
iii. Add theNode to the children vector.
ii. If theNode is “null”
1. Get the estimate for the child state.
2. Create a new node for the child state, with the parent
as the best node, costs as the child’s costs, and the
distance as the estimate.
3. Put the new node inter the open table with the child
state as the key.
4. Increment the evaluated nodes
5. Add the new node to the children vector.
e. Loop until all of best’s children have been examined.
9. Remove from the open table the value where the best node’s state
is the key.
10. Add to the closed table the best node’s state using the best
node as a key.
11. Remove the first element in nodes vector.
12. Add children nodes to nodes vector in order of lowest cost
13. Go to step 1, until there are no more nodes in the nodes
vector.
14. Return “null”, signifying a failure, i.e. no solution found.
Figure 8. Procedures for Implemented A* Search
Page 10 of 14
7.1 How was the Manhattan Distance Heuristic implemented?
The Manhattan Distance Heuristic described in section 3.1, has been implemented via a nested
for loop where the inner loop performed the calculations to generated the final result of the
heuristic. The code fragment for this heuristic is:
int “heuristic result” = 0;
int “index” = -1;
for(int sy = 0; sy < “vertical dimension of puzzle”; sy++)
{
for(int sx = 0; sx < “horizontal dimension of puzzle”; sx++)
{
“increment index by 1”;
int “tile value” = “sequence to check”[“index”];
if (“tile value” == “blank location in puzzle”)
{
// don’t include in heuristic result
continue;
}
int “horizontal spaces offby” = “tile value” %
“horizontal dimension of puzzle”;
int “vertical spaces offby” = “tile value” /
“horizontal dimension of puzzle”;
“heuristic result” += Math.abs(“vertical spaces offby” - sy) +
Math.abs(“horizontal spaces offby” - sx);
}
}
return “heuristic result”;
Figure 9. Pseudo code fragment for Manhattan Distance Heuristic
Page 11 of 14
7.2 How was the Tiles Out of Place Heuristic implemented?
The Tiles Out of Place Heuristic, talked about in section 3.2, is implemented via a for loop that
checks each element in the array to determine whether or not the number in each element is in
the correct position. Each time the number is incorrect the heuristic result is incremented by one,
starting at zero. The code fragment for this heuristic is:
for(int offby=0; offby < “dimensions of puzzle”; offby++)
{
if( “sequence to check”[offby] != offby )
{
“increment heuristic result by one”;
}
}
return “heuristic result”;
Figure 10. Pseudo code fragment for Tiles Out of Place Heuristic
7.3 How was the A* Search using Greedy Search implemented?
As state previously in section 3.3, the Greedy Search only uses the total path cost so far, g(n).
Therefore in the Greedy Search implementation, zero is added to g(n) in order to protect the
operational procedures of the A* Search algorithm stated above, in section 7.
8. How Random is Randomize Tiles?
Randomize Tiles is very random. While testing it out, there were times using the A* searches to
solve the Eight Puzzle that the depth reached and was in excess of 23 and on average the solution
depth was about 27. Therefore, it is strongly urged until a less random tile option is added to the
program, please manually move the tiles around via mouse clicks in the interface to achieve a
less random board to solve.
Page 12 of 14
9. Results from Searches
The following table was produced after running tests on the program using the following eleven
moves on the tiles from the Goal State: Right, Up, Right, Up, Right, Down, Left, Up, Right,
Right, Up.
Moves from Breadth First Search Manhattan Distance Tiles Out of Place
Greedy Search
Goal State
Depth
Nodes
Depth
Nodes
Depth
Nodes
Depth
Nodes
1
1
3
1
4
1
4
1
7
3
3
20
3
9
3
9
3
23
5
5
132
5
12
5
12
5
71
7
7
1412
7
17
7
21
7
256
9
9
8580
9
21
9
40
9
763
11
11
10278
11
23
11
76
11
2013
Figure 11. Results from Eight Puzzle Program Search Algorithms
10. Known Bugs
10.1 Display of Breadth First Search (BFS)
The problem with the BFS display is that the search doesn’t graphically display each movement
of the tiles from the Start State to the Goal State after completing the search, but rather redisplays
the Goal State to the user. This is a result of not attaching the parent states to each child state
throughout the search before putting the nodes on the queue to be later examined, something I
did not forget to do in the A* searches. This bug will be corrected in the next version of the
program.
10.2 Depth Problem With Respect To Breath First Search (BFS)
While doing experimentation on the BFS algorithm in the program, I noticed that a depth greater
13 was beyond a reasonable amount of time to wait for an answer2. This is because the Eight
Puzzle has on average a branching factor of around 2.7 3. Therefore at depth 14, the number of
nodes that needs to be evaluated is approximately 1,094,190 compared to depth 13 which is
approximately 405,256 nodes. This means that it would need significantly more time to complete
the evaluation of these depths up to the point of never.
10.3 Depth Problem With Respect To A* Searches
2
A reasonable amount of time is approximately ¾ of a hour. This was sufficient time for me to get bored playing
other games or watching television, waiting for an answer. However, according to the ACM Regional Coding
Contest, I recently attended, the reasonable amount of time was significantly lower. It actually was two minutes.
3
1 location with all four valid moves, 4 with three valid moves, and 4 with two valid moves = ((1*4)+(4*3)+(4*2))/
9 spots = 2.6666 ~ 2.7
Page 13 of 14
The A* searches also have problems with large depths. However, when using the Randomize
Tiles function, the main problem that was truly noticed was between depth 30 to depth 50. This
problem was the ability to display the moved taken to trace back the path to reach the Goal State.
The number that continued to pop up as 18,144 nodes. A conclusion drawn from this is that there
is a limitation to amount to information that was able to be stored in the solution vector, which
resulted in this problem. Further research into the matter is underway.
10.4 Applet Usage Problem With Respect To Microsoft Internet Explorer
The Microsoft Internet Explorer problem is most likely the result of the browser’s hatred for
working with non-Microsoft products. The applet opens in IE, however totally functionality does
not work. This includes movement of tiles, running Randomize Tiles, and submitting a request to
solve the puzzle. Further research into the matter is underway.
10.5 Applet Usage Problem With Respect To Netscape Navigator
The problem with Netscape Navigator is the inability to use the Randomize Tiles function.
Further research into the matter is underway and therefore suggested that Java’s Appletviewer be
used to test and play with the program at the present time to have all functionality working.
Page 14 of 14
Download