Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 这种广度优先的搜索能更快吗?_Python_Algorithm_Computer Science_Breadth First Search - Fatal编程技术网

Python 这种广度优先的搜索能更快吗?

Python 这种广度优先的搜索能更快吗?,python,algorithm,computer-science,breadth-first-search,Python,Algorithm,Computer Science,Breadth First Search,我有一个数据集,它是一个大的未加权循环图,循环发生在大约5-6条路径的循环中。它由大约8000个节点组成,每个节点有1-6个连接,通常约4-5个连接。我正在进行单对最短路径计算,并实现了以下代码来进行广度优先搜索 from Queue import Queue q = Queue() parent = {} fromNode = 'E1123' toNode = 'A3455' # path finding q.put(fromNode) parent[fromNode] = 'Root'

我有一个数据集,它是一个大的未加权循环图,循环发生在大约5-6条路径的循环中。它由大约8000个节点组成,每个节点有1-6个连接,通常约4-5个连接。我正在进行单对最短路径计算,并实现了以下代码来进行广度优先搜索

from Queue import Queue

q = Queue()
parent = {}
fromNode = 'E1123'
toNode = 'A3455'

# path finding
q.put(fromNode)
parent[fromNode] = 'Root'

while not q.empty():
  # get the next node and add its neighbours to queue
  current = q.get()
  for i in getNeighbours(current):
    # note parent and only continue if not already visited
    if i[0] not in parent:
      parent[i[0]] = current
      q.put(i[0])

  # check if destination
  if current == toNode:
    print 'arrived at', toNode
    break
上面的代码使用Python2.6队列模块,GetNeights只是一个子例程,它进行一个MySQL调用,并以元组列表的形式返回邻居,例如“foo”、“bar”,。SQL调用很快

代码运行正常,但是测试到大约7层的深度大约需要20秒才能运行2.5GHz Intel 4GB RAM OS X 10.6


我欢迎大家对如何改进这段代码的运行时间提出意见。

我敢打赌这台机器有多个内核,不是吗?并行运行


嗯,BFS不包括标记你已经看到的节点,这样你就不会再访问它们了吗?

好吧,考虑到评论的投票结果,我现在就回答这个问题

紧循环中的SQL肯定会减慢您的速度。我不管电话有多快。想想看——你要求解析一个查询,运行一个查找——尽管如此,它仍然处于一个紧密的循环中。您的数据集看起来像什么?您可以将整个数据集选择到内存中,或者至少在MySQL之外使用它吗

如果您在内存中处理这些数据,您将看到显著的性能提升。

类似这样的内容:

#!/usr/bin/env python

from Queue import Queue

def traverse_path(fromNode, toNode, nodes):
    def getNeighbours(current, nodes):
        return nodes[current] if current in nodes else []

    def make_path(toNode, graph):
        result = []
        while 'Root' != toNode:
            result.append(toNode)
            toNode = graph[toNode]
        result.reverse()
        return result

    q = Queue()
    q.put(fromNode)
    graph = {fromNode: 'Root'}

    while not q.empty():
        # get the next node and add its neighbours to queue
        current = q.get()
        for neighbor in getNeighbours(current, nodes):
            # use neighbor only continue if not already visited
            if neighbor not in graph:
                graph[neighbor] = current
                q.put(neighbor)

        # check if destination
        if current == toNode:
            return make_path(toNode, graph)
    return []

if __name__ == '__main__':
    nodes = {
        'E1123': ['D111', 'D222', 'D333', 'D444'],
        'D111': ['C01', 'C02', 'C04'],
        'D222': ['C11', 'C03', 'C05'],
        'D333': ['C01'],
        'C02': ['B1'],
        'B1': ['A3455']
    }
    result = traverse_path('E1123', 'A3455', nodes)
    print result

['E1123', 'D111', 'C02', 'B1', 'A3455']

如果将SQL查询替换为列表字典,这将是一个棘手的部分,您将获得此性能。

我认为您的意思是Python多处理。第二,8000个节点将很容易放入内存中。很好的调用!包含节点信息的表只是fromNode、toNode的行。我将研究如何简单地将其加载到内存中。可能只是一个大的字典结构。作为一个简单的测试,我在CREATE表定义中使用ENGINE=memory将MySQL加载到内存中。同样的代码现在大约在2.5秒内完成!派对有点晚了,但你是在用事先准备好的陈述来提问吗?应该能够节省一些SQL处理时间,特别是在内存中的变体中。确实如此。如果节点已经被放置在父节点[]中,那么它以前已经被看到过,因此它不会被放入队列中再次执行操作。哦,我明白了。对不起,我错过了。不过,将该标志放入每个节点比操纵不断增长的集合要便宜。太棒了,休。我在内存表中的性能一直很好。我将尝试下一步。有大约14K的连接,这将最终成为一个web应用程序,因此我需要仔细考虑加载到内存中的工作方式。我发现我的代码与你的相似,休,但是你的肯定更优雅。除了“neighbor/neighbor”的区域设置相关拼写外,我对上述内容的唯一额外建议是在make_path中调用result.reverse,因为它按从node->toNode的顺序返回列表