【问题标题】:Computing the Difference between two graphs 'edge wise' in networkx计算networkx中两个“边缘明智”的图之间的差异
【发布时间】:2015-11-02 12:40:09
【问题描述】:

我想使用 networkx 库比较两个图表。 我想尝试包含 3 个节点的硬编码示例。其中一张图被引用,所以我想检查第二张图的边缘是否在同一个地方。我在考虑一个简单的算法,它会从给定的图中减去参考图,如果结果不是空图,那么它返回 false。

我的代码如下,但它不起作用:

import networkx as nx
import matplotlib.pyplot as plt


S=nx.DiGraph()#S-sample graph

S.add_nodes_from([0,1,2])
S.add_edge(0,2)
S.add_edge(1,2)

nx.draw(S)
#plt.savefig("S.png")
#plt.show()

R=nx.DiGraph()#R-reference graph

R.add_nodes_from([0,1,2])
R.add_edge(1,2)

nx.draw(R)
#plt.savefig("R.png")
#plt.show()

def difference(S, R):
  DIF=nx.create_empty_copy(R)
  DIF.name="Difference of (%s and %s)"%(S.name, R.name)
  if set(S)!=set(R):
    raise nx.NetworkXError("Node sets of graphs is not equal")

 # if S.is_multipgraph():
 #   edges=S.edges_iter(keys=True)
 # else:
  edges=S.edges_iter()
  for e in edges:
    if not R.has_edge(*e):
      DIF.add_edge(*e)
  return DIF

D=difference(S, R)
plt.show(D)

【问题讨论】:

  • 如果你想比较边缘,为什么不使用if set(S.edges())!=set(R.edges())
  • 我可以这样做,但我仍然必须指出有什么区别
  • 将差异中的边添加到您的新有向图? for e in set(S.edges()).difference(set(R.edges()): DIF.add_edge(e)
  • 注意 - 如果图表是无向的,请注意 set(S.edges())。我不确定您是否可以 100% 肯定边缘不会在一个图中返回为 1,2 而在另一个图中返回为 2,1。由于您的图表是定向的,因此这里不是问题。
  • @WardC 为什么不回答这个问题? (请添加关于无向图的警告)

标签: python networkx


【解决方案1】:

您想用参考 (R) 图中的边而不是输入图 (S) 中的边来计算图 (DIF)? 或者你想计算一个 R 和 S 之间的边不同的图?我包括了两个选项,一个被注释掉了。

import networkx as nx

S = nx.DiGraph()#S-sample graph
S.add_nodes_from([0, 1, 2])
S.add_edge(0, 2)
S.add_edge(1, 2)

R = nx.DiGraph()#R-reference graph
R.add_nodes_from([0, 1, 2])
R.add_edge(1, 2)


def difference(S, R):
    DIF = nx.create_empty_copy(R)
    DIF.name = "Difference of (%s and %s)" % (S.name, R.name)
    if set(S) != set(R):
        raise nx.NetworkXError("Node sets of graphs is not equal")

    r_edges = set(R.edges_iter())
    s_edges = set(S.edges_iter())

    # I'm not sure what the goal is: the difference, or the edges that are in R but not in S
    # In case it is the difference:
    diff_edges = r_edges.symmetric_difference(s_edges)

    # In case its the edges that are in R but not in S:
    # diff_edges = r_edges - s_edges

    DIF.add_edges_from(diff_edges)

    return DIF

print(difference(S, R).edges())

这个版本打印[(0, 2)]

正如@Joel 所注意到的,在无向图中,没有保证(至少:我在源代码或文档中没有找到)节点的顺序是一致的。如果这是一个问题,您可以先将元组转换为冻结集,因此顺序无关紧要。您需要frozensets,而不是集合或列表,因为它们是可散列的(这是对集合成员的要求)

set([frozenset(x) for x in S.edges()])

【讨论】:

    【解决方案2】:

    一个简单的写法如下(你的区别方法在raise nx.Networkx...行之后的部分

    for edge in S.edges_iter():
            if not R.has_edge(edge[0],edge[1]):
                DIF.add_edge(edge[0],edge[1])
        return DIF;
    

    这是我为您的示例提供的图表:

    正如@joel 所提到的,我通过将 edge[0] 与 edge[1] 交换来测试它的无向图,并且效果很好。

    至于您的代码,我相信您唯一的问题是显示图表。

    首先要在单独的图中显示每个图表,您必须在每次绘制后执行plt.show()

    第二在最后一行你写了plt.show(D)这不是正确的方法,你必须使用draw函数然后调用plt.show()

    最后,看看drawing documentation,你还有其他绘制函数可以自定义绘制的图形,例如nx.draw_networkx_nodes 节点形状、颜色、大小...

    【讨论】:

    • 如何在节点中添加数字?
    • 你的意思是在显示器上?只需使用 with_labels = True 即可绘制函数如下:nx.draw(D, with_labels = True)
    猜你喜欢
    • 1970-01-01
    • 2013-08-20
    • 2020-05-13
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    相关资源
    最近更新 更多