高效算法,用于在有向图中找到所有顶点的2步邻域

时间:2017-05-08 19:49:40

标签: algorithm numpy graph-algorithm

我有一个csv格式(~14GB)的大型有向图,边缘用以下格式表示为整数:

node1,node2
3213741,23521361
3213741,6532710
3213741,12340611
3213741,6457392
3213741,9682135
6567133,12956771
6567133,23860123

node1是边缘开始的地方,node2是边缘结束的地方。边缘按node1分组(可以按node2分组)。

我需要为所有节点生成两步邻居。这是以下格式:

node1,node2,node3
3213741,6532710,5347128

我的想法是复制边缘并按node2对它们进行排序,因此有两个表t1.node1,t1.node2t2.node1,t2.node2,然后在t1.node1 == t2.node1和{{}} {{}}时以某种方式连接这两个表{1}}。但这看起来太慢了。是否有更好的算法或任何算法可以利用数据按t1.node1 != t2.node2分组的事实?我更喜欢Numpy。谢谢。

2 个答案:

答案 0 :(得分:2)

根据你的内存有多大,你可以创建一个邻接矩阵作为scipy.sparse.coo_matrix(即每当两个节点连接并且其他地方为零时有一个矩阵),将其转换为另一种类型的稀疏矩阵然后走广场。该矩阵具有准确存在二阶连接的条目。条目的值甚至可以告诉您长度为2的节点之间存在多少条路径。

答案 1 :(得分:2)

我写了一些代码,实现了obachtos提出的稀疏矩阵方法,并使用dask在一个节点上并行运行:

import numpy as np
import pandas as pd
import dask
import time
from scipy.sparse import coo_matrix

np.random.seed(1)

# Fabricate some data
elem = int(1e7)
rng = int(1e5)
gr = np.random.randint(0, rng, elem * 2, np.uint32)
gr = gr.reshape((elem, 2))
gr = gr[np.argwhere(gr[:, 0] != gr[:, 1])]
gr = gr.reshape(-1, 2)
grdf = pd.DataFrame(data=gr)
gr = grdf.drop_duplicates().values

def coord2adjacency(coords, shp, order, chunksize):
    grsp = coo_matrix((np.ones(gr.shape[0]), (gr[:, 0], gr[:, 1])),
                      shape=(shp, shp))
    grcsr = grsp.tocsr()
    adj = grcsr**order
    return adj

adjspdel = dask.delayed(coord2adjacency,
                        pure=True, nout=1, traverse=False)(gr, shp=rng,
                                                           order=2,
                                                           chunksize=5000)
print('Computing an adjacency matrix of order {ordr} from {n} coordinates.'\
      .format(ordr=2, n=gr.shape[0]))
t0 = time.time()
adjsp = adjspdel.compute()
print('Execution time: {tm} minutes.'.format(tm=(time.time() - t0) / 60))

在我的4核/ 8 GB PC上,执行时间为4.1分钟。 OP的问题仍然是几个数量级。 dask distributed包应允许与此类似的代码在足够大的任务集群上运行。