Python 从隐含图搜索算法
Python Search Algorithm from Implied Graphs
不久前我问了一个问题(),@6502 回答得很好。它让我可以更准确地思考这个问题并引出这个后续问题。
在上一个问题中,您从这样的函数中得到了一个隐含的有向树:
def neighbors1(node):
"Returns neighboring nodes in directed tree"
#some code
yield node_1
#some more code
yield node_2
#...
yield node_n
成功标准函数如下:
def goal(node):
"Returns true if node is the end goal and false otherwise"
if node #meets some goal#:
return True
else:
return False
第一个函数暗示了某种图形,根据细节,它可能是树或循环图,可能是有向的也可能是无向的。但是假设上面暗示了一个有向树(如图)。
这意味着对于任何节点,您都可以找到子节点,并递归地继续搜索这棵树。现在如果你想从节点 A 到节点 H(比如说),你可以使用上一个问题的代码,将 neighbors1 函数传递给搜索函数(在下面重现):
def search(start_state, neighbors, goal):
path = [start_state]
class PathFound(RuntimeError):
pass
def rsearch(x):
if goal(x):
raise PathFound
for y in neighbors(x):
path.append(y)
rsearch(y)
path.pop()
try:
rsearch(start_state)
except PathFound:
return path
return None # No path exists
所以你只需调用
search(A,neighbors1,goal)
现在(经过那么长的介绍),问题是,如果邻居函数隐含了不同的图怎么办?
我认为如果邻居函数意味着像这样的无向树:
那么上面的方法可能行不通,因为你最终可能会陷入无限循环,你可以在其中来回跳转,例如B 和 F。但是,我认为这可以通过添加一个简单的检查来解决,看看你是否在加倍返回:
def search(start_state, neighbors, goal):
path = [start_state]
class PathFound(RuntimeError):
pass
def rsearch(x):
if goal(x):
raise PathFound
for y in neighbors(x):
if y in path: continue #New line for undirected graphs
path.append(y)
rsearch(y)
path.pop()
try:
rsearch(start_state)
except PathFound:
return path
return None # No path exists
对以上efficiency/effectiveness的想法或意见欢迎。
但是,问题的症结在于,如果您有一个由 neighbors 函数(如下所示)隐含的一般图怎么办:
是否有类似的搜索功能可以让您探索通过它的最短路径(再次仅使用邻居功能,而不是 a priori 整个图的知识)。一种选择是实施 dijkstra 算法,但我认为(虽然这有助于找到最佳解决方案),但对于为非常大的图找到好的解决方案而言,这可能效率低下。是否存在像这样的图的深度优先搜索之类的东西?或者 dijkstra 可以用类似的方式实现吗?或者您会考虑什么方法?
我希望这个问题有道理并且对更多人有用,而不仅仅是我!
有一个相当有效的 Dijkstra 算法版本用于查找路径。将搜索分成两个叶,从每个终端节点开始一个。在两者之间交替,每次迭代扩展一个深度级别。
成功是当您将一个节点添加到一个列表中,而另一个列表中已经存在:两个搜索在中间相遇。
理解:深度优先搜索,通过检查找到终端节点。在这种情况下,我们需要做一些简单的改动:
def rsearch(x, found=[]):
if goal(x):
raise PathFound
for y in neighbors(x) and y not in found:
found.append(y)
path.insert(0, y) # switch to depth-first search
rsearch(y, found)
path.pop()
您还可以通过向节点对象添加一个布尔值来处理 "found" 列表记帐,在您触摸它时标记每个节点。
这对你有用吗?当您 接近 到目标节点时,您有什么直觉的方法吗?如果是这样,可能会有一些启发式方法来缩短搜索。
不久前我问了一个问题(
在上一个问题中,您从这样的函数中得到了一个隐含的有向树:
def neighbors1(node):
"Returns neighboring nodes in directed tree"
#some code
yield node_1
#some more code
yield node_2
#...
yield node_n
成功标准函数如下:
def goal(node):
"Returns true if node is the end goal and false otherwise"
if node #meets some goal#:
return True
else:
return False
第一个函数暗示了某种图形,根据细节,它可能是树或循环图,可能是有向的也可能是无向的。但是假设上面暗示了一个有向树(如图)。
这意味着对于任何节点,您都可以找到子节点,并递归地继续搜索这棵树。现在如果你想从节点 A 到节点 H(比如说),你可以使用上一个问题的代码,将 neighbors1 函数传递给搜索函数(在下面重现):
def search(start_state, neighbors, goal):
path = [start_state]
class PathFound(RuntimeError):
pass
def rsearch(x):
if goal(x):
raise PathFound
for y in neighbors(x):
path.append(y)
rsearch(y)
path.pop()
try:
rsearch(start_state)
except PathFound:
return path
return None # No path exists
所以你只需调用
search(A,neighbors1,goal)
现在(经过那么长的介绍),问题是,如果邻居函数隐含了不同的图怎么办?
我认为如果邻居函数意味着像这样的无向树:
那么上面的方法可能行不通,因为你最终可能会陷入无限循环,你可以在其中来回跳转,例如B 和 F。但是,我认为这可以通过添加一个简单的检查来解决,看看你是否在加倍返回:
def search(start_state, neighbors, goal):
path = [start_state]
class PathFound(RuntimeError):
pass
def rsearch(x):
if goal(x):
raise PathFound
for y in neighbors(x):
if y in path: continue #New line for undirected graphs
path.append(y)
rsearch(y)
path.pop()
try:
rsearch(start_state)
except PathFound:
return path
return None # No path exists
对以上efficiency/effectiveness的想法或意见欢迎。
但是,问题的症结在于,如果您有一个由 neighbors 函数(如下所示)隐含的一般图怎么办:
是否有类似的搜索功能可以让您探索通过它的最短路径(再次仅使用邻居功能,而不是 a priori 整个图的知识)。一种选择是实施 dijkstra 算法,但我认为(虽然这有助于找到最佳解决方案),但对于为非常大的图找到好的解决方案而言,这可能效率低下。是否存在像这样的图的深度优先搜索之类的东西?或者 dijkstra 可以用类似的方式实现吗?或者您会考虑什么方法?
我希望这个问题有道理并且对更多人有用,而不仅仅是我!
有一个相当有效的 Dijkstra 算法版本用于查找路径。将搜索分成两个叶,从每个终端节点开始一个。在两者之间交替,每次迭代扩展一个深度级别。
成功是当您将一个节点添加到一个列表中,而另一个列表中已经存在:两个搜索在中间相遇。
理解:深度优先搜索,通过检查找到终端节点。在这种情况下,我们需要做一些简单的改动:
def rsearch(x, found=[]):
if goal(x):
raise PathFound
for y in neighbors(x) and y not in found:
found.append(y)
path.insert(0, y) # switch to depth-first search
rsearch(y, found)
path.pop()
您还可以通过向节点对象添加一个布尔值来处理 "found" 列表记帐,在您触摸它时标记每个节点。
这对你有用吗?当您 接近 到目标节点时,您有什么直觉的方法吗?如果是这样,可能会有一些启发式方法来缩短搜索。