从权重导出的ad-hoc边缘属性

时间:2011-05-30 11:32:11

标签: graph igraph edge

我使用igraph(通过python)进行图聚类。

我有一棵树(几何图形的最小生成树),带有加权边,并且想要计算重量时间 如果边是两个组件的顶点数较少 删除:

def sep(graph, e):
    h = copy(graph)
    w = h.es[e]['weight']
    h.delete_edges(e)
    return w * min(h.components().sizes())

# 'graph' is the tree I am dealing with
ss = [sep(graph,x) for x in range(len(graph.es))]

我的问题是:

  1. 这是图论中的已知(和命名)属性吗?如果是这样,那是什么 它

  2. 如果我为所有人计算这段代码,我的代码效率非常低 边缘,如上所示。如果图形变为50000个边和顶点, 内存消耗变得巨大。你有什么建议吗? 优化

2 个答案:

答案 0 :(得分:1)

我不知道你的第一个问题,但我可能对第二个问题有所了解 由于我们正在处理最小的生成树,您可以使用关于一条边获得的信息来计算与其相邻的边的所需属性(从现在开始,我将此属性称为f(e)边缘e)。
让我们看一下边缘(A,B)和(B,C)。在计算f(A,B)时,我们假设在从图表中删除边缘后,您发现较小的组件是A侧的组件,您知道:
f(B,C) = (f(A,B) / weight(A,B) + 1) * weight(B,C)
这是正确的,因为(B,C)与(A,B)相邻,并且在移除它之后,您将得到“几乎”相同的两个分量,唯一的区别是B从较大的分量移动到较小的分量。 这样,您可以对一个边进行完整的计算(包括删除dge和发现组件及其大小),然后只对连接到它的每个其他边进行简短计算。
您将需要特别注意这种情况,即较小的组件(随着我们沿着边缘链生长)会变得更大。

更新:
经过一番思考后,我意识到如果你能在树中找到一个叶子节点,那么你根本不需要搜索组件及其大小。首先计算附加到此节点的边的f(e)。因为它的叶子:
f(e) = weight(e) * 1(1因为它是一个叶子节点,在删除边缘后,你会得到一个只包含叶子的组件和一个组件,它是图表的其余部分。)
从这里继续,如前所述......
排除查找叶节点所需的资源和时间,其余的计算将在O(m)(m是边数)和使用常量内存中完成。

答案 1 :(得分:1)

yurib's answer上详细说明,我会做这样的事情(也发布在igraph邮件列表上):

我将使用两个属性,一个用于顶点,一个用于边缘。 edge属性很简单,它将被称为cut_value,它可以是None或包含您要查找的值。最初,所有这些值都是None s。我们将使用cut_value=None 未处理的和边缘调用边缘,其中``cut_value不是None``` 已处理

顶点属性将被称为cut_size,它仅对存在一个未经处理的事件边缘的顶点有效。由于您有一棵树,除非处理完所有边(您可以终止算法),否则您将始终至少有一个这样的顶点。最初,对于所有顶点,cut_size将为1(但请记住,它们仅对具有一个未处理的事件边缘的顶点有效)。

我们还将有一个列表deg,其中包含在给定节点上发生事件的未处理边数。最初所有边都是未处理的,因此该列表包含顶点的度数。

到目前为止,我们有这个:

n, m = graph.vcount(), graph.ecount()
cut_values = [None] * m
cut_sizes = [1] * n
deg = graph.degree()

我们将始终使用一个事件未处理的边缘处理顶点。最初,我们将这些放入队列中:

from collections import deque
q = deque(v for v, d in enumerate(deg) if d == 1)

然后我们按如下方式逐个处理队列中的顶点,直到队列变空:

  1. 首先,我们从队列中删除顶点 v 并找到其唯一未处理的事件边缘。让这条边用 e

  2. 表示
  3. e cut_value e 的权重乘以min(cut_size[v], n - cut_size[v])

  4. e 的另一个端点用 u 表示。由于 e 现在已经处理,因此 u 上的未处理边数减少了1,因此我们必须将deg[u]减少1.如果{{1} }变为1,我们将 u 放入队列中。我们还将其deg[u]增加一个,因为 v 现在是图表中的一部分,当我们稍后移除 u 上的最后一个边缘事件时,它们将被分开

  5. 在Python中,这应该类似于以下代码(未经测试):

    cut_size