Representation of Search State Space and Search Operators

game of chess we can not possibly enumerate the search tree for all possible games of chess, so we define a successor node search operator that given a board position represented by a node in the search tree calculates all possible moves for either the white or black pieces. The possible chess moves are calculated by a successor node search operator and are represented by newly calculated nodes that are linked to the previous node. Note that even when it is simple to fully enumerate a search tree, as in the game maze example, we still might want to generate the search tree dynamically as we will do in this chapter. For calculating a search tree we use a graph. We will represent graphs as node with links between some of the nodes. For solving puzzles and for game related search, we will represent positions in the search space with Java objects called nodes. Nodes contain arrays of references to both child and parent nodes. A search space using this node representation can be viewed as a directed graph or a tree. The node that has no parent nodes is the root node and all nodes that have no child nodes a called leaf nodes. Search operators are used to move from one point in the search space to another. We deal with quantized search spaces in this chapter, but search spaces can also be continuous in some applications. Often search spaces are either very large or are infinite. In these cases, we implicitly define a search space using some algorithm for extending the space from our reference position in the space. Figure 2.1 shows representations of search space as both connected nodes in a graph and as a two- dimensional grid with arrows indicating possible movement from a reference point denoted by R. When we specify a search space as a two-dimensional array, search operators will move the point of reference in the search space from a specific grid location to an adjoining grid location. For some applications, search operators are limited to moving updownleftright and in other applications operators can additionally move the reference location diagonally. When we specify a search space using node representation, search operators can move the reference point down to any child node or up to the parent node. For search spaces that are represented implicitly, search operators are also responsible for determining legal child nodes, if any, from the reference point. Note that I use different libraries for the maze and graph search examples.

2.2 Finding Paths in Mazes

The example program used in this section is MazeSearch.java in the directory sr- csearchmaze and I assume that the reader has downloaded the entire example ZIP file for this book and placed the source files for the examples in a convenient place. 6 R R Figure 2.1: A directed graph representation is shown on the left and a two- dimensional grid or maze representation is shown on the right. In both representations, the letter R is used to represent the current posi- tion or reference point and the arrowheads indicate legal moves gener- ated by a search operator. In the maze representation, the two grid cells marked with an X indicate that a search operator cannot generate this grid location. Figure 2.2 shows the UML class diagram for the maze search classes: depth first and breadth first search. The abstract base class AbstractSearchEngine contains common code and data that is required by both the classes DepthF irstSearch and BreadthF irstSearch. The class M aze is used to record the data for a two- dimensional maze, including which grid locations contain walls or obstacles. The class M aze defines three static short integer values used to indicate obstacles, the starting location, and the ending location. The Java class M aze defines the search space. This class allocates a two-dimensional array of short integers to represent the state of any grid location in the maze. When- ever we need to store a pair of integers, we will use an instance of the standard Java class java.awt.Dimension, which has two integer data components: width and height. Whenever we need to store an x-y grid location, we create a new Dimension object if required, and store the x coordinate in Dimension.width and the y coor- dinate in Dimension.height. As in the right-hand side of Figure 2.1, the operator for moving through the search space from given x-y coordinates allows a transition to any adjacent grid location that is empty. The Maze class also contains the x-y location for the starting location startLoc and goal location goalLoc. Note that for these examples, the class Maze sets the starting location to grid coordinates 0-0 upper left corner of the maze in the figures to follow and the goal node in width - 1-height - 1 lower right corner in the following figures. 7