diff --git a/README.md b/README.md index e3aa1f9e4..3ad8e340b 100644 --- a/README.md +++ b/README.md @@ -74,8 +74,8 @@ Here is a table of algorithms, the figure, name of the algorithm in the book and | 3.7 | Graph-Search | `graph_search` | [`search.py`][search] | Done | | | 3.11 | Breadth-First-Search | `breadth_first_graph_search` | [`search.py`][search] | Done | Included | | 3.14 | Uniform-Cost-Search | `uniform_cost_search` | [`search.py`][search] | Done | Included | -| 3.17 | Depth-Limited-Search | `depth_limited_search` | [`search.py`][search] | Done | | -| 3.18 | Iterative-Deepening-Search | `iterative_deepening_search` | [`search.py`][search] | Done | | +| 3.17 | Depth-Limited-Search | `depth_limited_search` | [`search.py`][search] | Done | Included | +| 3.18 | Iterative-Deepening-Search | `iterative_deepening_search` | [`search.py`][search] | Done | Included | | 3.22 | Best-First-Search | `best_first_graph_search` | [`search.py`][search] | Done | Included | | 3.24 | A\*-Search | `astar_search` | [`search.py`][search] | Done | Included | | 3.26 | Recursive-Best-First-Search | `recursive_best_first_search` | [`search.py`][search] | Done | | @@ -186,4 +186,4 @@ Many thanks for contributions over the years. I got bug reports, corrected code, [rl]:../master/rl.py [search]:../master/search.py [utils]:../master/utils.py -[text]:../master/text.py \ No newline at end of file +[text]:../master/text.py diff --git a/search.ipynb b/search.ipynb index 8effcd7f2..8edbe675d 100644 --- a/search.ipynb +++ b/search.ipynb @@ -1132,7 +1132,7 @@ }, "outputs": [], "source": [ - "def tree_search_for_vis(problem, frontier):\n", + "def tree_breadth_search_for_vis(problem):\n", " \"\"\"Search through the successors of a problem to find a goal.\n", " The argument frontier should be an empty queue.\n", " Don't worry about repeated paths to a state. [Figure 3.7]\"\"\"\n", @@ -1143,7 +1143,7 @@ " node_colors = {k : 'white' for k in problem.graph.nodes()}\n", " \n", " #Adding first node to the queue\n", - " frontier.append(Node(problem.initial))\n", + " frontier = deque([Node(problem.initial)])\n", " \n", " node_colors[Node(problem.initial).state] = \"orange\"\n", " iterations += 1\n", @@ -1151,7 +1151,7 @@ " \n", " while frontier:\n", " #Popping first node of queue\n", - " node = frontier.pop()\n", + " node = frontier.popleft()\n", " \n", " # modify the currently searching node to red\n", " node_colors[node.state] = \"red\"\n", @@ -1179,9 +1179,9 @@ " \n", " return None\n", "\n", - "def breadth_first_tree_search_(problem):\n", + "def breadth_first_tree_search(problem):\n", " \"Search the shallowest nodes in the search tree first.\"\n", - " iterations, all_node_colors, node = tree_search_for_vis(problem, FIFOQueue())\n", + " iterations, all_node_colors, node = tree_breadth_search_for_vis(problem)\n", " return(iterations, all_node_colors, node)" ] }, @@ -1199,10 +1199,10 @@ "outputs": [], "source": [ "all_node_colors = []\n", - "romania_problem = GraphProblem('Arad', 'Fagaras', romania_map)\n", - "a, b, c = breadth_first_tree_search_(romania_problem)\n", + "romania_problem = GraphProblem('Arad', 'Bucharest', romania_map)\n", + "a, b, c = breadth_first_tree_search(romania_problem)\n", "display_visual(romania_graph_data, user_input=False, \n", - " algorithm=breadth_first_tree_search_, \n", + " algorithm=breadth_first_tree_search, \n", " problem=romania_problem)" ] }, @@ -1222,11 +1222,56 @@ }, "outputs": [], "source": [ - "def depth_first_tree_search_graph(problem):\n", + "def tree_depth_search_for_vis(problem):\n", + " \"\"\"Search through the successors of a problem to find a goal.\n", + " The argument frontier should be an empty queue.\n", + " Don't worry about repeated paths to a state. [Figure 3.7]\"\"\"\n", + " \n", + " # we use these two variables at the time of visualisations\n", + " iterations = 0\n", + " all_node_colors = []\n", + " node_colors = {k : 'white' for k in problem.graph.nodes()}\n", + " \n", + " #Adding first node to the stack\n", + " frontier = [Node(problem.initial)]\n", + " \n", + " node_colors[Node(problem.initial).state] = \"orange\"\n", + " iterations += 1\n", + " all_node_colors.append(dict(node_colors))\n", + " \n", + " while frontier:\n", + " #Popping first node of stack\n", + " node = frontier.pop()\n", + " \n", + " # modify the currently searching node to red\n", + " node_colors[node.state] = \"red\"\n", + " iterations += 1\n", + " all_node_colors.append(dict(node_colors))\n", + " \n", + " if problem.goal_test(node.state):\n", + " # modify goal node to green after reaching the goal\n", + " node_colors[node.state] = \"green\"\n", + " iterations += 1\n", + " all_node_colors.append(dict(node_colors))\n", + " return(iterations, all_node_colors, node)\n", + " \n", + " frontier.extend(node.expand(problem))\n", + " \n", + " for n in node.expand(problem):\n", + " node_colors[n.state] = \"orange\"\n", + " iterations += 1\n", + " all_node_colors.append(dict(node_colors))\n", + "\n", + " # modify the color of explored nodes to gray\n", + " node_colors[node.state] = \"gray\"\n", + " iterations += 1\n", + " all_node_colors.append(dict(node_colors))\n", + " \n", + " return None\n", + "\n", + "def depth_first_tree_search(problem):\n", " \"Search the deepest nodes in the search tree first.\"\n", - " # This algorithm might not work in case of repeated paths\n", - " # and may run into an infinite while loop.\n", - " iterations, all_node_colors, node = tree_search_for_vis(problem, Stack())\n", + " iterations, all_node_colors, node = tree_depth_search_for_vis(problem)\n", " return(iterations, all_node_colors, node)" ] }, @@ -1237,9 +1282,9 @@ "outputs": [], "source": [ "all_node_colors = []\n", - "romania_problem = GraphProblem('Arad', 'Oradea', romania_map)\n", + "romania_problem = GraphProblem('Arad', 'Bucharest', romania_map)\n", "display_visual(romania_graph_data, user_input=False, \n", - " algorithm=depth_first_tree_search_graph, \n", + " algorithm=depth_first_tree_search, \n", " problem=romania_problem)" ] }, @@ -1262,7 +1307,7 @@ }, "outputs": [], "source": [ - "def breadth_first_search_graph(problem):\n", +"def breadth_first_search_graph(problem):\n", " \"[Figure 3.11]\"\n", " \n", " # we use these two variables at the time of visualisations\n", @@ -1282,8 +1327,7 @@ " all_node_colors.append(dict(node_colors))\n", " return(iterations, all_node_colors, node)\n", " \n", - " frontier = FIFOQueue()\n", - " frontier.append(node)\n", + " frontier = deque([node])\n", " \n", " # modify the color of frontier nodes to blue\n", " node_colors[node.state] = \"orange\"\n", @@ -1292,7 +1336,7 @@ " \n", " explored = set()\n", " while frontier:\n", - " node = frontier.pop()\n", + " node = frontier.popleft()\n", " node_colors[node.state] = \"red\"\n", " iterations += 1\n", " all_node_colors.append(dict(node_colors))\n", @@ -1315,8 +1359,7 @@ " node_colors[node.state] = \"gray\"\n", " iterations += 1\n", " all_node_colors.append(dict(node_colors))\n", - " return None" - ] + " return None" ] }, { "cell_type": "code", @@ -1346,8 +1389,7 @@ "collapsed": true }, "outputs": [], - "source": [ - "def graph_search_for_vis(problem, frontier):\n", + "source": [ "def graph_search_for_vis(problem):\n", " \"\"\"Search through the successors of a problem to find a goal.\n", " The argument frontier should be an empty queue.\n", " If two paths reach a state, only use the first one. [Figure 3.7]\"\"\"\n", @@ -1356,7 +1398,7 @@ " all_node_colors = []\n", " node_colors = {k : 'white' for k in problem.graph.nodes()}\n", " \n", - " frontier.append(Node(problem.initial))\n", + " frontier = [(Node(problem.initial))]\n", " explored = set()\n", " \n", " # modify the color of frontier nodes to orange\n", @@ -1365,7 +1407,7 @@ " all_node_colors.append(dict(node_colors))\n", " \n", " while frontier:\n", - " # Popping first node of queue\n", + " # Popping first node of stack\n", " node = frontier.pop()\n", " \n", " # modify the currently searching node to red\n", @@ -1401,7 +1443,7 @@ "\n", "def depth_first_graph_search(problem):\n", " \"\"\"Search the deepest nodes in the search tree first.\"\"\"\n", - " iterations, all_node_colors, node = graph_search_for_vis(problem, Stack())\n", + " iterations, all_node_colors, node = graph_search_for_vis(problem)\n", " return(iterations, all_node_colors, node)" ] }, @@ -1462,7 +1504,7 @@ " all_node_colors.append(dict(node_colors))\n", " return(iterations, all_node_colors, node)\n", " \n", - " frontier = PriorityQueue(min, f)\n", + " frontier = PriorityQueue('min', f)\n", " frontier.append(node)\n", " \n", " node_colors[node.state] = \"orange\"\n", @@ -1558,7 +1600,7 @@ "metadata": {}, "outputs": [], "source": [ - "def depth_limited_search(problem, frontier, limit = -1):\n", + "def depth_limited_search(problem, limit = -1):\n", " '''\n", " Perform depth first search of graph g.\n", " if limit >= 0, that is the maximum depth of the search.\n", @@ -1568,7 +1610,7 @@ " all_node_colors = []\n", " node_colors = {k : 'white' for k in problem.graph.nodes()}\n", " \n", - " frontier.append(Node(problem.initial))\n", + " frontier = [Node(problem.initial)]\n", " explored = set()\n", " \n", " cutoff_occurred = False\n", @@ -1622,7 +1664,7 @@ "\n", "def depth_limited_search_for_vis(problem):\n", " \"\"\"Search the deepest nodes in the search tree first.\"\"\"\n", - " iterations, all_node_colors, node = depth_limited_search(problem, Stack())\n", + " iterations, all_node_colors, node = depth_limited_search(problem)\n", " return(iterations, all_node_colors, node) " ] },