1Search Policy
The search policy refers to how to select the order of extended nodes during the search process. Generally, search strategies adopt testing methods. There are two types: backtracking and graphic search.
2Blind Image Search Policy
Graph Search policies can be classified into two types: one is called a blind Graph Search policy or an information-Free Graph Search policy, and the other is called a heuristic search policy or an information-based graph search policy. The two most common information-free graph search strategies are width-first search and depth-first search.
2.1Width-first search
It starts from the root node (Start Node) and searches by layer, that is, expands nodes by layer. Layer-by-layer scaling refers to the extension of the next layer of nodes until the target node is obtained.
The advantage of this search method is that, as long as there are any answers, it can ensure that the shortest path from the Start Node to the target node is finally found, however, it often has a long search process.
2.2Deep Priority Search
It starts from the root node. First, it expands the newly generated node, that is, it develops along the depth of the search tree until there is no successor node. Then it returns the result and goes through another path. That is, when each layer of the Search Tree always extends only one subnode and keeps advancing in depth until it can no longer advance (reaching the leaf node or being subject to depth restrictions, from the current node back to the upper-level node, continue along the other direction. The search tree of this method is gradually formed from the root of the tree.
Because a problematic tree may contain infinite branches, it is impossible to find the target node if an infinite Branch (that is, an infinite depth) is entered in the depth-first search. In order to avoid this situation, a deep boundary is defined when this method is implemented. When the search reaches this deep boundary and the target is not found, a re-searching is returned, deep Priority Search policies are incomplete. In addition, the solution obtained by applying this policy is not necessarily the optimal solution (Shortest Path ).
3 "Eight" Digital puzzle width-first search and depth-first search
3.1 "Eight" Digital puzzle width-first search
The procedure is as follows:
1. Determine whether the initial node is the target node. If the initial node is the target node, the search process ends. If not, go to step 1;
2. expand from the initial node to the 1st layer and get three nodes: 2, 3, and 4. If a node is obtained, the search process ends; if neither Node 2, 3, or 4 is the target node, go to step 2;
3. Expand from 1st nodes at Layer 1st to 2nd, and get node 5. Expand from 1st nodes at Layer 2nd to 2nd, and get 3 nodes: 6. 7 and 8. expand from the 1st nodes in the 3rd layer to the 2nd layer to get node 9. If a node is obtained, the search process ends; if nodes 6, 7, 8, and 9 are not the target node, go to step 1;
4. Expand the nodes in the next layer according to the above method to search for the target node until the target node is searched.
5. The search process is shown in Figure 1.
3.2In-depth priority search for "Eight" Digital difficulties
The procedure is as follows:
1. Set the depth limit, for example, 5;
2. Determine whether the initial node is the target node. If the initial node is the target node, the search process ends. If not, go to step 1;
3. expand from the initial node to Layer 2 to get Node 2 and determine whether Node 2 is the target node. If it is, the search process ends. If not, expand Node 2 to Layer 2, obtain Node 3;
4. Determine whether Node 3 is the target node. If it is not, the search process ends. If not, expand Node 3 to Layer 3 to obtain node 4;
5. Determine whether node 4 is the target node. If it is not, the search process ends. If not, expand node 4 to Layer 4 to obtain node 5;
6. Check whether node 5 is the target node. If it is not, the search process ends. If not, end this round of search and return to layer 2nd. Expand Node 3 to layer 3rd to get node 6;
7. Check whether node 6 is the target node. If it is not, the search process ends. If not, expand node 6 to Layer 7 to obtain node 7;
8. Determine whether node 7 is the target node. If it is not, end the search process. If not, expand node 6 to Layer 4 to get node 8;
9. Wait until the target node is obtained.
10. The search process is shown in figure 2.
3.3Search Efficiency Comparison
Measure the search efficiency of different search policies:
1. Odds (P): indicates the width of the area to be searched from the initial node to the target node in the search project.
P = L/T; P ε (0, 1]
L: the path length from the initial node to the target;
T: Total number of nodes generated throughout the process (excluding the initial nodes );
2. valid branch score (B): indicates the average number of subnodes generated by each valid node.
T = B + B2 +... + BL, B ≥ 1
When B = 1 and T = 1, the search efficiency is the highest.
When B> 1 ,,
3.3.1Search efficiency when width is used for Priority Search
L = 5, t = 26, P = L/T = 5/26 = 0.192, B = 1.613;
3.3.1Search efficiency when width is used for Priority Search
L = 5, t = 18, P = L/T = 5/18 = 0.278, B = 1.464;
From the calculation above, we can see that the efficiency of deep priority search is significantly higher than that of width priority search.
3.4Comparison of the above two search policies
In the width-first search process, the target node is found when the number of nodes is expanded to 26th. In the depth-first search process, the target node is obtained when the number of nodes is expanded to 18th.
In the width-first search process, you need to traverse all the nodes in each layer before the layer where the target node is located, that is, you need to traverse all the branches. In the deep priority search process, you do not need to traverse so many nodes. Therefore, in solving the "Eight" digital problem, the efficiency of deep priority search is significantly higher than that of width-based priority search.
Generally, depth is preferred for trees with a large depth, but not for trees with a large breadth. breadth precedence is the opposite. A tree with a large depth refers to a tree with multiple intermediate nodes from the Start Node to the target node (it can be understood that there are many intermediate solutions to the problem, and these solutions can be considered partially correct, however, to get a completely correct result-the target node, you must first find these intermediate solutions in sequence ). The wide tree refers to the tree with many possible nodes from the Start Node to the target node (it can be understood that there are many possible solutions to the problem. These solutions are either correct or wrong. To get a completely correct result-the target node, You must judge in sequence whether these possible solutions are correct ).
In most cases, the efficiency of deep priority search is higher than that of width priority search. However, in some cases, the advantages and disadvantages (or efficiency) of the two search strategies need to be analyzed and compared based on different problems.
Depth-first C # code:
public class DFS { static public bool DFSOn = false; //initial flag. if set initializes the array variables. static public bool solving = false; //solving flag set whilst the algorithm is running. static private bool trackBack = false; //trackBack flag set if the puzzle get stuck to track back moves private static Stack stackDFS = new Stack(); //FIFO structure required for DFS private static Stack stackMoves = new Stack(); //Stack stores everymove made. used for tracking back private static ArrayList xVisitedList = new ArrayList(); //list to store all the states that have been expanded private static ArrayList yVisitedList = new ArrayList(); public static Double[][] xTempPuzzle = new Double[3][]; //actual x & y 2-d arrays strore the pos of squares public static Double[][] yTempPuzzle = new Double[3][]; //gets the number of moves made towards the goal state. static public int getNumberOfMovesMade() { return stackMoves.Count; } //initialzes the 2-d arrays xTempPuzzle and yTempPuzzle and sets them to the current value of the //Puzzle displayed on the screen. static public void initializeArray() { for (int i = 0; i < 3; i++) { xTempPuzzle[i] = new Double[3]; yTempPuzzle[i] = new Double[3]; } xTempPuzzle[0][0] = PuzzleData.xPuzzle[0][0]; xTempPuzzle[0][1] = PuzzleData.xPuzzle[0][1]; xTempPuzzle[0][2] = PuzzleData.xPuzzle[0][2]; xTempPuzzle[1][0] = PuzzleData.xPuzzle[1][0]; xTempPuzzle[1][1] = PuzzleData.xPuzzle[1][1]; xTempPuzzle[1][2] = PuzzleData.xPuzzle[1][2]; xTempPuzzle[2][0] = PuzzleData.xPuzzle[2][0]; xTempPuzzle[2][1] = PuzzleData.xPuzzle[2][1]; xTempPuzzle[2][2] = PuzzleData.xPuzzle[2][2]; yTempPuzzle[0][0] = PuzzleData.yPuzzle[0][0]; yTempPuzzle[0][1] = PuzzleData.yPuzzle[0][1]; yTempPuzzle[0][2] = PuzzleData.yPuzzle[0][2]; yTempPuzzle[1][0] = PuzzleData.yPuzzle[1][0]; yTempPuzzle[1][1] = PuzzleData.yPuzzle[1][1]; yTempPuzzle[1][2] = PuzzleData.yPuzzle[1][2]; yTempPuzzle[2][0] = PuzzleData.yPuzzle[2][0]; yTempPuzzle[2][1] = PuzzleData.yPuzzle[2][1]; yTempPuzzle[2][2] = PuzzleData.yPuzzle[2][2]; } //resets all the variables. called when the reset button is clicked or the algorithm has finished static public void resetAll() { xVisitedList.Clear(); yVisitedList.Clear(); stackDFS.Clear(); stackMoves.Clear(); DFSOn = true; solving = false; } //the entry point method of this class. Get's called everytime a next move using DFS is required. static public bool solvePuzzle() { if (DFSOn) { initializeArray(); DFSOn = false; } if (PuzzleData.isFinalState(DFS.xTempPuzzle, DFS.yTempPuzzle)) { return true; } addNextMove(); movePuzzle(); return false; } //Each square of the shuffle can have 3 values each for x and y position. Those values //are 0, 100 & 200. This function checks if a left, up, down or right move is possible. //It does so by looking at the current x and y position of the blank square of the puzzle. static private bool isValidMove(int direction) { if (direction == 0) //check if sliding left is possible { if (DFS.xTempPuzzle[2][2] >= 100) { return true; } } else if (direction == 1) //check if sliding up is possible { if (DFS.yTempPuzzle[2][2] >= 100) { return true; } } else if (direction == 2)//check if sliding right is possible { if (DFS.xTempPuzzle[2][2] < 200) { return true; } } else if (direction == 3) //check if sliding down is possible { if (DFS.yTempPuzzle[2][2] < 200) { return true; } } return false; } //Checks if the current state has been expanded before or not contrary to the name //it doesn't check all the visited states but expanded states. static private bool isVisitedState() { for (int cnt = xVisitedList.Count - 1; cnt > -1; cnt--) { int sameElementCnt = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if ((((Double[][])xVisitedList[cnt])[i][j] == xTempPuzzle[i][j]) && ((Double[][])yVisitedList[cnt])[i][j] == yTempPuzzle[i][j]) { sameElementCnt++; } } } if (sameElementCnt == 9) { return true; } } return false; } //The method below checks for a valid move and then checks if the state has been visited //if not the it adds that direction to the stackDFS variable. static private void addNextMove() { bool moveAdded = false; if (isValidMove(0)) { PuzzleData.moveLeft(xTempPuzzle, yTempPuzzle); if (isVisitedState()) { PuzzleData.moveRight(xTempPuzzle, yTempPuzzle); } else { PuzzleData.moveRight(xTempPuzzle, yTempPuzzle); stackDFS.Push(0); moveAdded = true; } } if (isValidMove(1)) { PuzzleData.moveUp(xTempPuzzle, yTempPuzzle); if (isVisitedState()) { PuzzleData.moveDown(xTempPuzzle, yTempPuzzle); } else { PuzzleData.moveDown(xTempPuzzle, yTempPuzzle); stackDFS.Push(1); moveAdded = true; } } if (isValidMove(2)) { PuzzleData.moveRight(xTempPuzzle, yTempPuzzle); if (isVisitedState()) { PuzzleData.moveLeft(xTempPuzzle, yTempPuzzle); } else { PuzzleData.moveLeft(xTempPuzzle, yTempPuzzle); stackDFS.Push(2); moveAdded = true; } } if (isValidMove(3)) { PuzzleData.moveDown(xTempPuzzle, yTempPuzzle); if (isVisitedState()) { PuzzleData.moveUp(xTempPuzzle, yTempPuzzle); } else { PuzzleData.moveUp(xTempPuzzle, yTempPuzzle); stackDFS.Push(3); moveAdded = true; } } //if no move could be found happens when the current state cannot get out because all the //neighbouring states have already been expanded. It adds the opposite of the last move made //which makes the puzzle go back one step. if (!moveAdded) { int lastMove = (int)stackMoves.Pop(); if (lastMove == 0) { lastMove = 2; } else if (lastMove == 1) { lastMove = 3; } else if (lastMove == 2) { lastMove = 0; } else if (lastMove == 3) { lastMove = 1; } stackDFS.Push(lastMove); trackBack = true; //trackBack flag is set for the movePuzzle method. see there for more explanation. } } //Method that updates the puzzle with the direction popped of the DFS stack. Then adds the new puzzle state //to the visited list. static private void movePuzzle() { int direction = (int)stackDFS.Pop(); if (direction == 0) //Move Left { PuzzleData.moveLeft(xTempPuzzle, yTempPuzzle); } else if (direction == 1) //Move Up { PuzzleData.moveUp(xTempPuzzle, yTempPuzzle); } else if (direction == 2) //Move Right { PuzzleData.moveRight(xTempPuzzle, yTempPuzzle); } else if (direction == 3) //Move Down { PuzzleData.moveDown(xTempPuzzle, yTempPuzzle); } //if the trackBack flag is set as there were no moves, it doesn't add the move to the movesList stack. if (!trackBack) { addMove(direction); } addVisitedList(); trackBack = false; } //adds the cuurent state the puzzle is in to the visitedList. static private void addVisitedList() { Double[][] xTemp = new Double[3][]; xTemp[0] = new Double[3]; xTemp[1] = new Double[3]; xTemp[2] = new Double[3]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { xTemp[i][j] = xTempPuzzle[i][j]; } } xVisitedList.Add(xTemp); Double[][] yTemp = new Double[3][]; yTemp[0] = new Double[3]; yTemp[1] = new Double[3]; yTemp[2] = new Double[3]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { yTemp[i][j] = yTempPuzzle[i][j]; } } yVisitedList.Add(yTemp); } //adds the previous move (while NOT trackingBack) to the visited list. static private void addMove(int direction) { stackMoves.Push(direction); } }
Last run:
Program Executable File Download