如何在Python中累积有向图中的计数

时间:2014-01-27 02:53:52

标签: python algorithm data-structures graph directed-acyclic-graphs

我在字典中保留有向非循环图结构,其中每个键都是父键,每个值都是另一个字典,它将父元素的子元素映射到相应的边缘权重。例如,在下图中,父1有2个孩子; 2和3的边缘权重对应于2:

g = {
    0: Counter({1: 1}),
    1: Counter({2: 2, 3: 6}), 
    2: Counter({4: 3, 5: 2, 6: 1}),
    3: Counter({6: 2, 5: 7}),
    4: Counter({}),
    5: Counter({}),
    6: Counter({})
}

我还有每个节点的频率图,每个节点都有0个计数(子节点除外,它们的计数为1),这样:

count_map = {i: 0 for i in range(7)}

我想通过以下方案增加每个节点的值:每个叶子(在这种情况下为4,5和6)向上部节点发送1的计数。每个父节点获取计数并将其与相应的边相乘(例如,如果5将计数1发送到上一级,则其父2将获得1x2的计数,而其另一父3将获得1x7的计数)。那些父母也将这个信息传递给他们的父母,例如3将计数7传递给节点1,节点1将用7x6替换计数。每个父级都会将累积的计数传递给上级,直到它们到达根节点。

当然,如果节点从多个父节点获取消息,则需要将计数加起来并将其传递给其父节点。

如何计算此count_map?任何帮助,指针或伪代码表示赞赏。

2 个答案:

答案 0 :(得分:2)

也许是这样的:

# x = root node
def acyc(graph,x=0):
    node = graph[x]

    if len(node) == 0:
        return {x:1}

    # call self on children
    count_map = {}
    for i in node:
        count_map.update(acyc(graph,i))
    count_map[x] = sum([node[i]*count_map[i] for i in node])

    return count_map

答案 1 :(得分:1)

我们的算法将自下而上计算每个节点的值,并将值传播到父级。

首先,我们需要确定一个迭代图形的顺序,这样我们就不会在处理完子节点之前处理它。这个问题被称为topological sorting;有几种标准算法。请注意,我们需要迭代的顺序与标准拓扑排序顺序相反。

其次,我们需要图形的反转版本,因此我们可以轻松确定节点的父节点和通向父节点的边的权重。这很简单。

现在,我们将叶子的值初始化为1,将所有其他值初始化为0.然后,我们按照第一步中确定的顺序迭代图形的节点。对于节点的每个父节点,我们将父节点的值乘以子节点的值与链接两个节点的边的权重。