Python 优化将(定向)边列表转换为邻接列表的函数

Python 优化将(定向)边列表转换为邻接列表的函数,python,numpy,graph-theory,Python,Numpy,Graph Theory,我编写了一个函数,它将2元组列表(表示有向图的边)转换为列表数组(表示从数组索引给定的顶点开始可以到达的顶点) 到目前为止,我所拥有的: def make_图(边、顶点数量): 图=[]表示范围内的u(顶点数量)] 对于边中的边: 图形[边[0]]。追加(边[1]) 返回图 因此,对于这个图: 它将这样做: >>> make_graph([(0, 1), (2, 0), (1, 2), (0, 2)], 3) [[1, 2], [2], [0]] 从顶点0可以到达顶点1和

我编写了一个函数,它将2元组列表(表示有向图的边)转换为列表数组(表示从数组索引给定的顶点开始可以到达的顶点)

到目前为止,我所拥有的:

def make_图(边、顶点数量):
图=[]表示范围内的u(顶点数量)]
对于边中的边:
图形[边[0]]。追加(边[1])
返回图
因此,对于这个图:

它将这样做:

>>> make_graph([(0, 1), (2, 0), (1, 2), (0, 2)], 3)
[[1, 2], [2], [0]]
从顶点0可以到达顶点1和2等

它可以很好地工作并提供我想要的输出,但对于我的应用程序来说,这还不够快——我的真实图形将有大约10万到10万个顶点和1-4百万条边。有没有办法提高性能?也许是另一个列表理解,或者
numpy


如果Python不能更快地完成这项工作,我愿意用其他语言解决这个问题。

您可以从使用defaultdict删除与dict相关的开销开始

from collections import defaultdict

connenctions = defaultdict(list)
connection_input = [(0, 1), (2, 0), (1, 2), (0, 2)]

for x, y in connection_input:
    connenctions[x].append(y)


>>> connenctions.values()

dict_values([[1, 2], [0], [2]])

您可以从使用defaultdict删除与dict相关的开销开始

from collections import defaultdict

connenctions = defaultdict(list)
connection_input = [(0, 1), (2, 0), (1, 2), (0, 2)]

for x, y in connection_input:
    connenctions[x].append(y)


>>> connenctions.values()

dict_values([[1, 2], [0], [2]])


最流行的方法是使用
networkx
package。事实上,尽管它的设计很友好,但速度还是很慢。幸运的是,它有一些Python的替代方案。这是。我已经测试了一些替代方案,如
igraph
graph工具
。然而,graph tools有一个非常好的文档,但是它是基于Linux的,因为我是Windows用户,所以我无法访问它。最后,
igraph
在从安装后对我起了作用,我对性能非常满意。Hovewer,
igraph
接受标记为从0开始的整数的节点,因此如果需要,您需要创建节点的重新映射。

最常用的方法是使用
networkx
包。事实上,尽管它的设计很友好,但速度还是很慢。幸运的是,它有一些Python的替代方案。这是。我已经测试了一些替代方案,如
igraph
graph工具
。然而,graph tools有一个非常好的文档,但是它是基于Linux的,因为我是Windows用户,所以我无法访问它。最后,
igraph
在从安装后对我起了作用,我对性能非常满意。Hovewer,
igraph
接受标记为从0开始的整数的节点,因此如果需要,您需要创建节点的重新映射。

不要问我们:问Python。当您编写每个建议时发生了什么?我的意思是它工作正常,Python不会抛出异常,这也不是我的问题。我想问的是,如何在创建图表的时间方面提高其效率。我可以问Python如何让它更快,还是我遗漏了什么?你的图形有多少个顶点,你能在你的内存中保存一个nxn numpy数组吗?它大约在10万到10万个节点之间,有100万到400万个连接。我知道你发布的代码工作得很好;你的理解代码和NumPy代码怎么样?不要问我们:问Python。当您编写每个建议时发生了什么?我的意思是它工作正常,Python不会抛出异常,这也不是我的问题。我想问的是,如何在创建图表的时间方面提高其效率。我可以问Python如何让它更快,还是我遗漏了什么?你的图形有多少个顶点,你能在你的内存中保存一个nxn numpy数组吗?它大约在10万到10万个节点之间,有100万到400万个连接。我知道你发布的代码工作得很好;你的理解码和NumPy码怎么样?谢谢,我会查出来的!另外,请记住networkx的文档记录非常好,而igraph的文档记录非常差。谢谢,我会查看它的!另外,请记住networkx的文档记录非常好,而igraph的文档记录非常差。我已经将您建议的解决方案作为一个函数实现了,但实际上它似乎比我原来的函数慢了大约1/5。使用
defaultdicts
应该只是稍微加快了一点速度。尽管如此,这里还是无法避免循环。与C语言相比,Python循环仍然是一个巨大的性能消耗者。但是,与在图形库上执行的图形操作相比,浪费相对较小。@LuM,您确定正在对正确的部分计时吗?这里的要点是删除部分代码:
graph=[[]用于范围内(顶点数量)]
。在对相关部分计时时,我得到的反馈是,我的脚本需要512 ns,而你的脚本需要1.26µs。“我几乎可以肯定它不会慢下来。”mathfux同意。我本来打算发布一些类似于networkx的东西,但我不确定这是否会给OP带来太多的开销。是的,在这种情况下,像列表comp这样更快的东西不是一个选项,因为我们正在做特定于案例的列表追加,而在列表comp中追加是一个不存在的问题。我已经将您提出的解决方案作为一个函数实现了,但它实际上似乎比我原来的函数慢了大约1/5。使用
defaultdicts
应该只是稍微快一点。尽管如此,这里还是无法避免循环。与C语言相比,Python循环仍然是一个巨大的性能消耗者。但是,与在图形库上执行的图形操作相比,浪费相对较小。@LuM,您确定正在对正确的部分计时吗?这里的要点是删除部分代码:
graph=[[]用于范围内(顶点数量)]
。在对相关部分计时时,我得到的反馈是,我的脚本需要512 ns,而你的脚本需要1.26µs。“我几乎可以肯定它不会慢下来。”mathfux同意。实际上,我打算发布一些类似于networkx的东西,但不确定它是否会对OP造成太大的开销。是的,在这种情况下,像列表comp这样更快的东西是不可取的,因为我们正在进行特定于案例的列表追加,而在列表comp中追加是不可取的