代码之家  ›  专栏  ›  技术社区  ›  CurtLH

从NetworkX多向图中删除selfloops会导致运行时错误

  •  3
  • CurtLH  · 技术社区  · 7 年前

    我有一个包含自循环的NetworkX多重有向图。根据 documentation ,这是多向图的有效属性。

    多向图包含有向边。允许自循环。

    但是当我试图用 MG.remove_edges_from(MG.selfloop_edges()) ,中生成以下警告:

    ---------------------------------------------------------------------------
    RuntimeError                              Traceback (most recent call last)
    <ipython-input-13-ff3391f2296f> in <module>()
          1 # remove selfloop edges from the graph
    ----> 2 MG.remove_edges_from(MG.selfloop_edges())
    
    ~/Program_Files/miniconda3/envs/py36/lib/python3.6/site-packages/networkx/classes/multigraph.py in remove_edges_from(self, ebunch)
        603         []
        604         """
    --> 605         for e in ebunch:
        606             try:
        607                 self.remove_edge(*e[:3])
    
    ~/Program_Files/miniconda3/envs/py36/lib/python3.6/site-packages/networkx/classes/function.py in <genexpr>(.0)
       1154                 return ((n, n)
       1155                         for n, nbrs in G.adj.items()
    -> 1156                         if n in nbrs for d in nbrs[n].values())
       1157         else:
       1158             return ((n, n) for n, nbrs in G.adj.items() if n in nbrs)
    
    ~/Program_Files/miniconda3/envs/py36/lib/python3.6/_collections_abc.py in __iter__(self)
        759 
        760     def __iter__(self):
    --> 761         for key in self._mapping:
        762             yield self._mapping[key]
        763 
    
    RuntimeError: dictionary changed size during iteration
    

    在你从MultliDiGraph中删除selfloop的过程中,我是否遗漏了什么,或者这是NetworkX的一个bug?

    演示意外错误的可复制示例:

    import networkx as nx
    
    # create an empty MultiDiGraph
    MG = nx.MultiDiGraph()
    
    # add some edges to the graph
    MG.add_edges_from([(1, 2), (2, 3), (3, 1), (1, 2), (2, 1), (2, 2)])
    
    # check the edges in the graph
    MG.edges()
    
    # remove selfloop edges from the graph
    MG.remove_edges_from(MG.selfloop_edges())
    

    此方法在有向图中的工作方式与预期一致,如下所示:

    # create an empty MultiDiGraph
    G = nx.DiGraph()
    
    # add some edges to the graph
    G.add_edges_from([(1, 2), (2, 3), (3, 1), (1, 2), (2, 1), (2, 2)])
    
    # check the edges in the graph
    G.edges
    OutEdgeView([(1, 2), (2, 3), (2, 1), (2, 2), (3, 1)])
    
    # remove selfloop edges from the graph
    G.remove_edges_from(G.selfloop_edges())
    
    # check the edges in the graph
    G.edges()
    OutEdgeView([(1, 2), (2, 3), (2, 1), (3, 1)])
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   zohar.kom    7 年前

    问题是 MG.selfloop_edges() 是图中自循环边上的迭代器(更精确地说是生成器),通过移除边,可以在迭代过程中更改迭代器的边。

    根据 documentation :

    参数:ebunch(边元组的列表或容器)-。。。

    也就是说 ebunch 参数应为容器,而 MG.selfloop_edges() 返回生成器。你可以读到更多关于两者的区别 here .

    这个问题可以通过 list(MG.selfloop_edges()) MG.remove_edges_from (而不是通过 MG.selfloop_edges() 直接)。