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

Python 从NetworkX MultiDiGraph中删除自循环会导致运行时错误,python,networkx,Python,Networkx,我有一个NetworkX有向图,它包含自循环。根据,这是多有向图的一个有效性质 多有向图包含有向边。允许自循环 但是,当我尝试使用MG.remove_edges\u from(MG.selfloop_edges())从多向图中删除自循环时,会生成以下警告: --------------------------------------------------------------------------- RuntimeError Tra

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

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

但是,当我尝试使用
MG.remove_edges\u 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
此方法与有向图的预期效果一样,如下所示:

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

问题在于,
MG.selfloop_edges()
是图中selfloop边上的迭代器(更精确地说是生成器),通过删除边,您在迭代过程中更改了迭代器的边

根据报告:

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

这意味着
ebunch
参数应该是一个容器,而
MG.selfloop\u edges()
返回一个生成器。你可以阅读更多关于两者区别的内容


通过将
列表(MG.selfloop\u edges())
传递给
MG.remove\u from
(而不是直接传递
MG.selfloop\u edges()
)可以解决这个问题。

我在这里的另一个答案中解决了这个问题:


现在您可以执行
MG.从(列表(MG.selfloops\u edges())
中删除边。但是,这实际上是一个bug,将在即将发布的版本中修复:。然后你想写的代码就可以工作了。

因为你总是在里面放一个图,我怀疑有bug,除非OP误用了库。它必须在Python2中工作,因此可能在3的端口上没有捕获到它。文档说明
ebunch
应该是一个列表或容器,这里传递了一个生成器。因此,至少根据文档,它失败是可以的。然而,与直觉相反的是,原来的代码不起作用,可以很容易地在内部修复。谢谢。我会在你的答案中加上这个(最好是doclink),因为这会把意思从“这里有一个解决方法:…”改为“你用错了”;)谢谢@AndrasDeak,我在下面添加了一个答案,解释了这一点。但基本上,这是一个bug,一旦您更新networkx,它就会消失。
# 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)])