我正在尝试识别有向图中的气泡结构(方向从左到右)。我从可能的起始节点开始走图,例如绿色节点。然后我向所有路径添加一个节点,在路径再次发散时添加路径副本,如下所示:
第一次迭代: [[3],[7]]
第二次迭代:[[3,4],[3,5],[7,8],[7,9]]
每次迭代后,我想检查是否有任何路径相交并将它们保存为已确认的气泡。目前我正在使用嵌套的for循环来比较每个路径,但路径的数量会变得非常大,因此脚本可能变得非常慢。路径的顺序很重要。
有关如何提高路径列表中路径与另一路径的比较速度的建议吗?
if
其中GetNextSegment只返回连接到给定函数的节点的节点列表(在这种情况下,是路径的最后一个节点)。 outEdges是一个字典:node:[out,going,edges]。在ComparePaths()中,当2个路径的.intersection()长度大于0时,确认气泡。
气泡是一种图形结构,其中2条路径发散(例如,从绿色节点)并最终再次聚集在一起。在这个例子中,气泡将从2变为11,它们之间有所有节点。
我不是要求一个完整的冒泡算法,只是为了快速比较所有其他路径的所有路径的想法。
答案 0 :(得分:1)
不要使用列表列表,而应考虑使用一组元组(如果订单很重要)或一组frozensets(如果顺序无关紧要)。使用newPaths
初始化newPaths = set()
,然后将每个路径添加为元组或冻结集(可以清除)而不是列表:
for node in nextNodes:
newPath = tuple(path) + (node,)
# or: newPath = frozenset(path).union({node})
newPaths.add(newPath)
这可以使检查成员资格和交叉点更快一些。
通过两次循环paths
,您似乎多次检查相同的路径。例如,如果path1
等于(3, 4)
且path2
等于(3, 5)
,则无需检查(3, 4)
与(3, 5)
还有(3, 5)
与(3, 4)
,因为您的支票看似对称。您可以使用ComparePaths
帮助程序简化itertools
:
from itertools import combinations
def ComparePaths(paths, putativeBubbleStartSegment):
# This gets all combinations of paths without repeating any pairing.
for path1, path2 in combinations(paths, 2)
# Don't need to check the length of the intersection because an
# empty set is always equivalent to "False" in an if statement.
if set(path1).intersection(path2):
# Bubble confirmed
看起来您的示例代码遗漏了一些细节(因为有未使用的函数参数和变量),但我在这里看到的并不是似乎它应该适用于您的工作试图做。因此,即使可能有其他方法可以改进您的算法,也很难建议任何其他加速。