从NetworkX MultiDiGraph删除自环会导致运行时错误

时间:2018-09-27 02:10:29

标签: python networkx

我有一个包含自环的NetworkX MultiDiGraph。根据{{​​3}},这是MultiDiGraph的有效属性。

  

MultiDiGraph保存有向边。允许自循环。

但是当我尝试使用MG.remove_edges_from(MG.selfloop_edges())从MultiDiGraph中删除自环时,会生成以下警告:

---------------------------------------------------------------------------
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中删除自环的方式,或者这是NetworkX的错误?

可再现的示例,显示了意外错误:

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())

此方法可与DiGraph一起使用,如下所示:

# 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)])

2 个答案:

答案 0 :(得分:2)

问题在于MG.selfloop_edges()是图形中自环边上的迭代器(更确切地说是生成器),并且通过删除边来在迭代过程中更改迭代器的边。

根据documentation

  

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

这意味着ebunch参数应该是一个容器,而MG.selfloop_edges()返回一个生成器。您可以详细了解两个here之间的区别。

可以通过将 list(MG.selfloop_edges()) 传递给MG.remove_edges_from(而不是直接传递MG.selfloop_edges())来解决此问题。

答案 1 :(得分:1)

我在这里的另一个答案中解决了这个问题:https://stackoverflow.com/a/49428652/2966723

现在您可以执行MG.remove_edges_from(list(MG.selfloops_edges()))。但是,这实际上是一个错误,将在即将发布的版本https://github.com/networkx/networkx/pull/4080中修复。这样,您要编写的代码就可以使用。