为什么计算优先附件是昂贵的?

时间:2014-03-21 08:27:01

标签: python performance algorithm numpy graph

我有一个带有1034个顶点和53498个边的无向图。我计算顶点的优先附着索引。两个顶点之间的优先附着相似度被定义为第一顶点的度数乘以第二顶点的度数的乘积。我注意到我的计算速度非常慢。计算所需的图表需要2.7分钟。我不确定我的算法是慢还是其他错误。如果有人能够对我的代码进行一些调查,我将非常感激。

编辑:我刚刚意识到S是1034_by_1034矩阵。看看嵌套的for循环,它似乎是一个O(n ^ 2)算法!我猜这就是它变慢的原因。你不同意吗?

def pa(graph):
    """
        Calculates Preferential Attachment index.

        Returns S the similarity matrix.
    """
    A = gts.adjacency(graph)
    S = np.zeros(A.shape)
    for i in xrange(S.shape[0]):
        for j in xrange(S.shape[0]):
            i_degree = graph.vertex(i).out_degree()
            j_degree = graph.vertex(j).out_degree()
            factor = i_degree * j_degree
            S[i,j] = factor
    return S

1 个答案:

答案 0 :(得分:2)

据我所知,这些是我建议的加速:

第0次加速:i_degree不依赖于j,所以将它向上移动一级

def pa(graph):
    A = gts.adjacency(graph)
    S = np.zeros(A.shape)
    for i in xrange(S.shape[0]):
        i_degree = graph.vertex(i).out_degree() # easy to see that this can be put here instead, since it does not depend on j 
        for j in xrange(S.shape[0]):
            j_degree = graph.vertex(j).out_degree()
            factor = i_degree * j_degree
            S[i,j] = factor
    return S

第一次加速:只调用out_degree()N次,而不是2N ^ 2。

def pa2(graph):
    A = gts.adjacency(graph)
    i_degree = numpy.zeros(A.shape[0])
    for i in xrange(A.shape[0]):
        i_degree[i] = graph.vertex(i).out_degree()
    S = np.zeros(A.shape)
    for i in xrange(S.shape[0]):
        for j in xrange(S.shape[0]):
            S[i,j] = i_degree[i]*i_degree[j]
    return S

第二次加速:numpy而不是python for-loop

def pa3(graph):
    A = gts.adjacency(graph)
    i_degree = numpy.zeros(A.shape[0])
    for i in xrange(A.shape[0]):
        i_degree[i] = graph.vertex(i).out_degree()
    S = i_degree[:,None]*i_degree[None,:]
    return S

这会滥用问题的对称性。

注意:[None,:]与使用[numpy.newaxis,:]的效果相同。如果你想保留你的代码,你也可以在@memoize方法上使用out_degree()装饰器,但最好只在递归的东西上使用它,这不是那些情况之一。