python深度优先、广度优先和A star search

 1 class Node:
 2     """
 3     This class describes a single node contained within a graph.
 4     It has the following instannce level attributes:
 5
 6     ID: An integer id for the node i.e. 1
 7     heuristic_cost: A float value representing the estimated
 8                     cost to the goal node
 9     """
10     def __init__(self, ID, heuristic_cost):
11         self.ID = ID
12         self.connected_nodes = []
13         self.heuristic_cost = heuristic_cost
14
15     def __repr__(self):
16         ID = self.ID
17         hx = self.heuristic_cost
18         if len(self.connected_nodes)==0:
19             nodes = ‘None‘
20         else:
21             nodes = ‘,‘.join(str(cn[1].ID) for cn in self.connected_nodes)
22         return ‘Node:{}\nh(n):{}\nConnected Nodes:{}‘.format(ID, hx, nodes)
23
24     def set_connected_nodes(self,connected_nodes):
25         """
26         Adds edges that lead from this node to other nodes:
27
28         Parameters:
29         - connected_nodes: A list of tuples consisting of (cost, Node),
30                            where ‘cost‘ is a floating point value
31                            indicating the cost to get from this node
32                            to ‘Node‘ and ‘Node‘ is a Node object
33         """
34         self.connected_nodes = connected_nodes
35
36 def build_graph():
37     """
38     Builds the graph to be parsed by the search algorithms.
39     Returns: The starting node, which is the entry point into the graph
40     """
41     ids = range(13)
42     coords = [(0,0), (1,1), (1,0), (1,1), (5,2), (3,1), (3,0),
43               (3,-1), (5,1), (4,1), (4,0), (4,-2), (7,0)]
44
45     #https://en.wikipedia.org/wiki/Euclidean_distance
46     euclidean_distance = lambda x1y1, x2y2: ((x1y1[0]-x2y2[0])**2 +  (x1y1[1]-x2y2[1])**2)**(0.5)
47
48     def build_connected_node_list(from_id, to_ids):
49         starting_coords = coords[from_id]
50
51         connected_nodes = []
52         for to_id in to_ids:
53             connected_nodes.append((euclidean_distance(starting_coords, coords[to_id]), all_nodes[to_id]))
54
55         return connected_nodes
56
57     goal_coords = (7,0)
58     all_nodes = [Node(_id, euclidean_distance(coord, goal_coords)) for _id, coord in zip(ids, coords)]
59
60     all_nodes[8].set_connected_nodes(build_connected_node_list(8, [12]))
61     all_nodes[10].set_connected_nodes(build_connected_node_list(10,[12]))
62     all_nodes[5].set_connected_nodes(build_connected_node_list(5, [8]))
63     all_nodes[6].set_connected_nodes(build_connected_node_list(6, [9, 10]))
64     all_nodes[7].set_connected_nodes(build_connected_node_list(7, [11]))
65     all_nodes[1].set_connected_nodes(build_connected_node_list(1, [4,5]))
66     all_nodes[2].set_connected_nodes(build_connected_node_list(2, [5,6]))
67     all_nodes[3].set_connected_nodes(build_connected_node_list(3, [7]))
68     all_nodes[0].set_connected_nodes(build_connected_node_list(0, [1,2,3]))
69
70     return all_nodes[0]
1 # The starting node. You can use this cell to familiarize
2 # yourself with the node/graph structure
3 build_graph()

代码:

  1 import numpy
  2
  3 def depth_first_search(starting_node, goal_node):
  4     """
  5     This function implements the depth first search algorithm
  6
  7     Parameters:
  8     - starting_node: The entry node into the graph
  9     - goal_node: The integer ID of the goal node.
 10
 11     Returns:
 12     A list containing the visited nodes in order they were visited with starting node
 13     always being the first node and the goal node always being the last
 14     """
 15     visited_nodes_in_order = []
 16
 17     # YOUR CODE HERE
 18     #raise NotImplementedError()
 19     stack = []
 20     visited = set() # initialize explored set to empty
 21     stack.append(starting_node)
 22
 23     while True:
 24         # if the stack is empty, then return failure
 25         if len(stack) == 0:
 26             return ‘failure‘
 27
 28         # choose a leaf node and remove it from the stack
 29         leafnode = stack.pop()
 30
 31         if leafnode not in visited:
 32             visited_nodes_in_order.append(leafnode.ID)
 33
 34         # if leaf node contain a good state, then return visited_nodes_in_order
 35         if leafnode.ID == goal_node:
 36             return visited_nodes_in_order
 37
 38         # add the node to the explored set
 39         for cn in leafnode.connected_nodes:
 40             if cn[1] not in visited:
 41                 stack.append(leafnode)
 42                 stack.append(cn[1])
 43                 if cn[1] not in visited:
 44                     visited_nodes_in_order.append(cn[1].ID)
 45                     visited.add(cn[1])
 46                 break
 47
 48 def iterative_deepening_depth_first_search(starting_node, goal_node):
 49     """
 50     This function implements the iterative deepening depth first search algorithm
 51
 52     Parameters:
 53     - starting_node: The entry node into the graph
 54     - goal_node: The integer ID of the goal node.
 55
 56     Returns:
 57     A list containing the visited node ids in order they were visited with starting node
 58     always being the first node and the goal node always being the last
 59     """
 60     visited_nodes_in_order = []
 61
 62     # YOUR CODE HERE
 63     iterative_deepening_search(starting_node, goal_node, visited_nodes_in_order)
 64
 65     return visited_nodes_in_order
 66
 67 def iterative_deepening_search(starting_node, goal_node, visited_nodes_in_order):
 68
 69     depth = 0
 70     while depth >= 0:
 71         result = depth_limited_search(starting_node, goal_node, depth, visited_nodes_in_order)
 72
 73         if result != ‘cutoff‘ and result != ‘failure‘:
 74             return
 75
 76         depth = depth+1
 77
 78 def depth_limited_search(starting_node, goal_node, limit, visited_nodes_in_order):
 79     return recursive_dls(starting_node, goal_node, limit, visited_nodes_in_order)
 80
 81 def recursive_dls(node, goal_node, limit, visited_nodes_in_order):
 82     """
 83     :param node:
 84     :param goal_node:
 85     :param limit:
 86     :return: "failure":fail,"cutoff":cutoff,True:success
 87     """
 88
 89     visited_nodes_in_order.append(node.ID)
 90
 91     # goal test
 92     if node.ID == goal_node:
 93         return True
 94     elif limit == 0:
 95         return "cutoff"
 96     else:
 97         cutoff_occurred = False
 98
 99         for cn in node.connected_nodes:
100             child = cn[1]
101             result = recursive_dls(child, goal_node, limit-1, visited_nodes_in_order)
102
103             if result == "cutoff":
104                 cutoff_occurred = True
105             elif result != "failure":
106                 return True
107
108         if cutoff_occurred:
109             return "cutoff"
110         else:
111             return "failure"
112
113 def reconstruct_path(came_from, current):
114     path = [current.ID]
115
116     while current in came_from:
117         current = came_from[current]
118         path.append(current.ID)
119
120     return path
121
122
123 def a_star_search(starting_node, goal_node):
124     """
125     This function implements the A* search algorithm
126
127     Parameters:
128     - starting_node: The entry node into the graph
129     - goal_node: The integer ID of the goal node.
130
131     Returns:
132     A list containing the visited node ids in order they were visited with starting node
133     always being the first node and the goal node always being the last
134     """
135
136     visited_nodes_in_order = []
137
138     # YOUR CODE HERE
139
140     # The set of nodes already evaluated
141     close_set = set()
142
143     # The set of currently discovered nodes that are not evaluated yet.
144     # Initially, only the start node is known.
145     open_set = []
146
147     # For each node, which node it can most efficiently be reached from.
148     # If a node can be reached from many nodes, cameFrom will eventually contain the
149     # most efficient previous step.
150     came_from = {}
151
152     # For each node, the cost of getting from the start node to that node
153     gscore = {starting_node:0}
154
155     # for each node, the total cost of getting from the start node to the goal
156     # by passing by that node. That value is partly known, partly heuristic.
157     fscore = {starting_node:starting_node.heuristic_cost}
158
159     open_set.append((fscore[starting_node], starting_node))
160
161     while open_set:
162
163         # find the node in openSet having the lowest fScore[] value
164         lowscore = open_set[-1][0]
165         current = open_set[-1][1]
166         for item in open_set:
167             if item[0] < lowscore:
168                 current = item[1]
169                 lowscore = item[0]
170
171         if current.ID == goal_node:
172             path = reconstruct_path(came_from, current)
173             for item in reversed(path):
174                 visited_nodes_in_order.append(item)
175
176         open_set.remove((lowscore, current))
177
178         close_set.add(current)
179
180         for cn in current.connected_nodes:
181             next = cn[1]
182             cost = cn[0]
183
184             # Ignore the neighbor which is already evaluated
185             if next in close_set:
186                 continue
187
188             # the cost from start to a neighbor via current
189             new_cost = gscore[current] + cost
190
191             # Discover a new node
192             if next not in [i[1] for i in open_set]:
193                 open_set.append((fscore.get(next, numpy.inf), next))
194             elif new_cost >= gscore.get(next, numpy.inf):
195                 continue
196
197             # This path is the best until now. Record it
198             came_from[next] = current
199             gscore[next] = new_cost
200             fscore[next] = gscore[next] + next.heuristic_cost
201
202     return visited_nodes_in_order

测试:

 1 goal_node = 12
 2 depth_first_search_answer = [0, 1, 4, 5, 8, 12]
 3 iterative_deepening_depth_first_search_answer = [0, 0, 1, 2, 3, 0, 1,
 4                                                  4, 5, 2, 5, 6, 3, 7,
 5                                                  0, 1, 4, 5, 8, 2, 5,
 6                                                  8, 6, 9, 10, 3, 7, 11,
 7                                                  0, 1, 4, 5, 8, 12]
 8 a_star_search_answer = [0, 2, 6, 10, 12]
 9
10 assert (depth_first_search(build_graph(), goal_node)==depth_first_search_answer)
11 assert (iterative_deepening_depth_first_search(build_graph(), goal_node)==iterative_deepening_depth_first_search_answer)
12 assert (a_star_search(build_graph(), goal_node)==a_star_search_answer)

原文地址:https://www.cnblogs.com/wylwyl/p/10357501.html

时间: 2024-08-30 14:44:20

python深度优先、广度优先和A star search的相关文章

图的遍历之广度优先搜索(Breadth First Search)

描述 广度优先搜索算法(Breadth First Search)与树的层序遍历(level-order traversal)类似,基本思想是思想是: 从图中某顶点v出发,访问v之后,并将其访问标志置为已被访问,即visited[i]=1: 依次访问v的各个未曾访问过的邻接点: 分别从这些邻接点出发依次访问它们的邻接点,并使得"先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问,直至图中所有已被访问的顶点的邻接点都被访问到: 如果此时图中尚有顶点未被访问,则需要另选一个未曾被访问过的顶点作为

Python中re.match与re.search的使用方法详解

本文和大家分享的主要是python正则表达式中re.match函数与re.search方法的相关用法及异同点,希望通过本文的分享,能对大家有所帮助. re.match函数 re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none. 函数语法: re.match(pattern, string, flags=0) 函数参数说明: 参数描述 pattern匹配的正则表达式 string要匹配的字符串. flags标志位,用于控制正则表达式的匹配

笔试算法题(48):简介 - A*搜索算法(A Star Search Algorithm)

A*搜索算法(A Star Search Algorithm) A*算法主要用于在二维平面上寻找两个点之间的最短路径.在从起始点到目标点的过程中有很多个状态空间,DFS和BFS没有任何启发策略所以穷举所有的状 态空间,不适合仅需对局部进行搜索的应用.启发式搜索的关键在于:当前节点在选择下一步节点的时候,可以通过一个启发函数进行选择,选择到达终点代价最小 的节点作为下一步节点.A*的启发函数构造为: f(n)=g(n)+h(n) f(n)是可选的下一个节点的代 价,g(n)表示从start点到n点

COMP 2019 Assignment 1 – A Star Search

COMP 2019 Assignment 1 – A Star SearchPlease submit your solution via LEARNONLINE. Submission instructions are given at the end of this assignment.This assessment is due on Sunday, 14 April 2019, 11:59 PM.This assessment is worth 20% of the total mar

python实现基础的深度优先搜索(DFS, depth first search)解决数的全排列问题

数的全排列,是一个很简单的问题,平时我们用笔用纸就能列出答案,但是数列位多的时候,排列的结果就有非常多了,例如有1,2,3,4,5,6,7,8,9这一个数列,有9个数字,则有9!(9的阶乘)这么多种结果.那是非常大的.今天我就来介绍用深度优先搜索来解决这个数的全排列的问题. 深度优先搜索 首先简单介绍一下深度优先搜索,深度优先搜索的关键在于当下该如何做,至于下一步如何做,就与当下做的一样.深度优先搜索的基本模型为: dfs(step): 判断边界:执行相关操作,返回 尝试每一种可能 for( i

[LeetCode]题解(python):098 Validate Binary Search Tree

题目来源 https://leetcode.com/problems/validate-binary-search-tree/ Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys less than the node'

深度优先广度优先

深度优先:纵向 广度优先:横向 

深度优先&amp;广度优先(多继承)

Python支持多父类的继承机制,所以需要注意圆括号中基类的顺序,若是基类中有相同的方法名,并且在子类使用时未指定,Python会从左至右搜索基类中是否包含该方法.一旦查找到则直接调用,后面不再继续查找. # 父类定义 class people: def __init__(self, name, age, weight): self.name = name self.age = age self.__weight = weight def speak(self): print("%s 说: 我

【leetcode-200 深度优先+广度优先】 岛屿数量

给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例 1: 输入:11110110101100000000 输出: 1示例 2: 输入:11000110000010000011 输出: 3 来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/number-of-islands 方法一:深度优先搜索 [通过]直觉 将