Chapter 2 Depth-first search and breadth-first search As the basic search methods for puzzles and games, we formalize depth-firt search and breadth-first search. Both traverse tangible graphs or hypothetical graphs. In many cases those graphs are trees. Each node of the graph (tree) corresponds to a particular configuration of puzzle or game. Example. 8 – game. There are 8 tiles placed on a 3 by 3 grid. Initial configuration goal configuration |--------------------| |--------------------| | 2 8 3 | | 1 | 1 6 4 | | 8 5 | | 7 | 7 |-------------------| 2 3 | 4 | 6 5 | |-------------------| We define a move by the movement of the vacant position. In the initial configuration, the movement of tile 7 to the right is equivalent to move space to the left. So there are three moves in this configuration. After several moves, we have the target as follows: 2 8 3 2 1 6 4 1 5 7 7 8 6 3 2 3 4 1 8 4 5 7 6 5 2 3 1 8 4 7 6 5 1 7 2 3 1 8 4 8 6 5 7 2 3 4 6 5 Set up the initial configuration called “node”. We maintain the closed sets of nodes, CLOSED, which is the set of nodes that are already finished, so to speak procedure dfs(node, depth) begin if d <= depth then begin ### depth is a pre-defined depth push node to stack; Put node into CLOSED for all move on node do begin if ok_dfs(move) then begin node1=apply(move, node) dfs(node1) end pop up stack to node end main initialize node and goal, then call dfs(node, 1) 6 5 4 3 2 83 264 175 283 64 175 7 10 9 8 283 6 4 175 283 164 75 8 3 2 6 4 175 2 3 6 8 4 175 12 283 6 4 175 1 283 164 7 5 18 2 8 3 1 4 765 19 2 8 3 14 765 20 83 214 765 13 2 8 643 175 283 645 14 1 7 283 674 1 5 21 8 3 214 765 863 2 4 175 3 4 25 36 67 88 49 175 2 3 11 6 8 4 175 16 15 83 264 175 283 674 15 2 8 3 6 7 4 17 1 5 22 83 214 765 813 23 2 4 615 26 283 164 75 28 2 3 184 765 24 2 8 3 714 65 25 27 23 29 1 8 4 765 283 14 765 31 30 23 184 765 283 714 6 5 123 8 4 765 283 7 4 615 283 714 65 1 2 3 8 4 765 123 784 65 ok is defined as follows: function ok_dfs( move, node) begin if move is legitimate then begin node1=apply(move, node) if node1 is not in stack and not in CLOSED then return true end end Breadth-first search is described next. procedure bfs(node) begin while queue is not empty do begin take a node from queue Put node into CLOSED for all move on node do begin node1=apply(move, node) if ok_bfs(move) then add node1 to queue end end end main initialize node and goal; add node to queue; call bfs(node) function ok_dfs( move, node) begin if move is legitimate then begin node1=apply(move, node) if node1 is not in queue and not in CLOSED then return true end The breadth-first search above guarantees the shortest path to the target. It stores many nodes in queue, and not space efficient. The depth-first search may end up with the path to the target that is not optimal. Also it may generate many unnecessary nodes. 20 10 5 2 283 64 175 83 264 175 8 3 2 6 4 175 863 2 4 175 3 4 25 36 67 88 49 175 21 2 3 6 8 4 175 11 2 8 3 6 4 175 283 164 75 83 264 175 2 3 684 175 22 2 8 643 175 283 6 4 175 23 283 645 17 283 674 15 283 674 1 5 2 8 3 6 7 4 15 1 283 164 7 5 3 283 2 4 765 283 14 765 6 12 83 214 765 24 83 214 765 8 3 214 765 813 2 4 615 4 283 164 75 2 3 184 765 7 13 283 714 65 25 23 14 1 8 4 765 8 283 14 765 283 714 6 5 283 714 65 45 26 15 23 184 765 283 7 4 615 123 8 4 765 1 2 3 8 4 765 123 784 65