【问题标题】:Python Search Algorithm from Implied Graphs隐含图的 Python 搜索算法
【发布时间】:2015-10-15 19:24:06
【问题描述】:

不久前,我问了一个问题 (depth first search algorithm in python),@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 函数传递给 search 函数(转载如下):

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

关于上述欢迎的效率/效果的想法或cmets。

但是,问题的关键在于,如果您有一个由邻居函数隐含的通用图(如下所示),该怎么办:

是否有类似的搜索功能可以让您探索通过它的最短路径(再次仅使用邻居功能,而不是整个图的先验知识)。一种选择是实现 dijkstra 的算法,但我认为(尽管有利于找到最佳解决方案),这对于为非常大的图找到好的解决方案可能效率低下。有没有像这样的图的深度优先搜索?或者dijkstra可以以类似的方式实现吗?或者你会考虑什么方法?

我希望这个问题有意义,并且对更多人有用,而不仅仅是我!

【问题讨论】:

  • 您已经发现了基本深度优先搜索算法的一个缺点——它会陷入循环。避免这种情况的一种方法是维护您已经访问过的节点列表,并将它们排除在任何进一步的探索之外。如果你不喜欢这个想法,你可以尝试广度优先搜索,或者不同的图遍历算法

标签: python algorithm dijkstra depth-first-search


【解决方案1】:

有一个相当有效的 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()

您还可以通过向节点对象添加一个布尔值来处理“找到”列表记帐,在您触摸它时标记每个节点。

这对您有何帮助?当你接近到一个目标节点时,你有什么方法可以直觉吗?如果是这样,可能会有一些启发式方法来缩短搜索。

【讨论】:

  • 这是一个好主意,如果你知道你要去的节点是什么。有时有多个节点满足要求。然而,问题也是关于在给定邻居函数的情况下实现算法的pythonic方法。
  • 使用标准更改:添加一个新的起始节点,其邻居恰好是 true 起始节点的集合。对完成节点也这样做。从开始到结束绘制一条路径。当我有一点时间时,我会回到 Pythonic 部分。
  • ... 或者您是想说在检查之前无法识别终端节点?这确实会改变问题。
  • 我正在尝试解决一般问题,但我正在处理的特定实例具有可能存在许多最终节点的属性,并且不清楚我是否可以轻松列出它们。通过检查更容易确定。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-10
  • 2021-07-07
  • 2012-03-19
  • 2016-10-03
相关资源
最近更新 更多