【问题标题】:Error in the algorithm of ordering nodes in the undirected graph无向图中的节点排序算法错误
【发布时间】:2018-01-02 08:20:57
【问题描述】:

这个想法是在无向图中构造一个按度数排序的节点列表。 图表以 {node: (set of its neighbours) for node in the graph}

的形式给出

代码在“graph[neighbor].remove(node)”行引发 KeyError 异常。该节点似乎已从集合中删除,但我看不到在哪里。

谁能指出错误?

编辑:此节点列表用于按图中节点值的顺序模拟目标攻击。因此,在对度数最大的节点进行攻击后,将其从该节点中移除,并据此重新计算剩余节点的度数。

def fast_targeted_order(graph):
    """returns an orderedv list of the nodes in the graph in decreasing 
    order of their degrees"""

    number_of_nodes = len(graph)  
    # initialise a list of sets of every possible degree
    degree_sets = [set() for dummy_ind in range(number_of_nodes)]

    #group nodes in sets according to their degrees
    for node in graph:
        degree = len(graph[node])
        degree_sets[degree] |= {node}

    ordered_nodes = []
    #starting from the set of nodes with the maximal degree
    for degree in range(number_of_nodes - 1, -1, -1):

        #copy the set to avoid raising the exception "set size changed 
        during the execution
        copied_degree_set = degree_sets[degree].copy()
        while degree_sets[degree]:

            for node in copied_degree_set:
                degree_sets[degree] -= {node}
                for neighbor in graph[node]:
                    neighbor_degree = len(graph[neighbor])
                    degree_sets[neighbor_degree] -= {neighbor}
                    degree_sets[neighbor_degree - 1] |= {neighbor}
                    graph[neighbor].remove(node)

            ordered_nodes.append(node)
            graph.pop(node)

    return ordered_nodes

【问题讨论】:

  • 如果只想按度数对节点进行排序,为什么要在找到节点度数后修改图形?
  • 因为我想在目标攻击的模拟中按照节点值的顺序使用这个节点列表。因此,在对度数最大的节点进行攻击后,将其从该节点中移除,并据此重新计算剩余节点的度数。感谢您的评论,我会修改问题。
  • 使用 |=-= 添加或删除集合中的一个元素比使用 addremove/discard 的可读性更低且速度更慢。
  • 另外我猜ordered_nodes.append(node)graph.pop(node) 应该缩进到for node in copied_degree_set: 循环内?
  • 度数为零时可以再次访问访问过的节点。我建议你对这个图 {1: {2}, 2: {1}} 进行一步一步的跟踪,这是一个有两个节点的图,有一条边连接它们。

标签: algorithm python-2.7


【解决方案1】:

我之前的答案(现已删除)不正确,问题不在于使用集合,而是在通过相同序列迭代期间删除任何序列中的项目。

Python 3.1 版教程明确警告:

在循环中修改被迭代的序列是不安全的 (这只会发生在可变序列类型上,例如列表)。如果 您需要修改您正在迭代的列表(例如, 复制所选项目)您必须迭代副本。

但是,Python 3.5 教程。 (我使用)仅建议:

如果您需要在内部修改您正在迭代的序列 循环(例如复制所选项目),它是 建议您先制作一份副本。

看起来这个操作在 Python 3.5 中仍然非常不可预测,使用相同的输入会产生不同的结果。

在我看来,上一版的教程比当前版更受欢迎。

@PetarPetrovic 和 @jdehesa,感谢您的宝贵建议。

工作解决方案:

def fast_targeted_order(ugraph):
    """
    input: undirected graph in the form {node: set of node's neighbors)
    returns an ordered list of the nodes in V in decresing order of their degrees
    """

    graph = copy_graph(ugraph)
    number_of_nodes = len(graph)

    degrees_dict = {degree: list() for degree in range(number_of_nodes)}

    for node in graph:
        degree = len(graph[node])
        degrees_dict[degree].append(node)

    ordered_degrees = OrderedDict(sorted(degrees_dict.items(), 
                                  key = lambda key_value: key_value[0],
                                  reverse = True))
    ordered_nodes = []

    for degree, nodes in ordered_degrees.items():
        nodes_copy = nodes[:]
        for node in nodes_copy:
            if node in nodes:

                for neighbor in graph[node]:
                    neighbor_degree = len(graph[neighbor])
                    ordered_degrees[neighbor_degree].remove(neighbor)
                    if neighbor_degree:
                        ordered_degrees[neighbor_degree - 1].append(neighbor)
                    graph[neighbor].remove(node)

                graph.pop(node)
                ordered_degrees[degree].remove(node)
                ordered_nodes.append(node)

    return ordered_nodes

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-18
    • 1970-01-01
    • 1970-01-01
    • 2019-04-24
    • 2016-03-31
    • 1970-01-01
    • 2017-07-25
    • 2018-07-17
    相关资源
    最近更新 更多