NetworkX Graph 对象的"同构"比较,而不是默认的"地址"比较



我想使用NetworkX Graph对象作为Python dict中的键。但是,我不希望使用默认行为进行比较(即通过对象的地址)。相反,我希望同构图是dict中相同元素的键。

这种行为已经在某个地方实施了吗?我找不到这方面的任何信息。

如果我必须自己实施,以下评估是否现实?

  • 在类中包装networkx.Graph
  • 定义__eq__,使其调用is_isomorphic
  • 以某种方式定义__hash__(欢迎提出建议)

我认为我必须使这个包装的Graph不可变,因为:

如果一个类定义了可变对象并实现了__eq__()方法,那么它就不应该实现__hash__(),因为可散列集合的实现要求键的散列值是不可变的(如果对象的散列值发生变化,那么它将位于错误的散列桶中)。

下面是一个将networkx Graph子类化并添加eqhash函数的示例。我不确定它是否能解决你的问题,但应该是一个开始。

import networkx as nx
class myGraph(nx.Graph):
    def __eq__(self, other):
        return nx.is_isomorphic(self, other)
    def __hash__(self):
        return hash(tuple(sorted(self.degree().values())))

if __name__ == '__main__':
    G1 = myGraph([(1,2)])
    G2 = myGraph([(2,3)])
    G3 = myGraph([(1,2),(2,3)])
    print G1.__hash__(), G1.edges()
    print G2.__hash__(), G2.edges()
    print G3.__hash__(), G3.edges()
    print G1 == G2
    print G1 == G3
    graphs = {}
    graphs[G1] = 'G1'
    graphs[G2] = 'G2'
    graphs[G3] = 'G3'
    print graphs.items()

输出类似于:

3713081631935493181 [(1, 2)]
3713081631935493181 [(2, 3)]
2528504235175490287 [(1, 2), (2, 3)]
True
False
[(<__main__.myGraph object at 0xe47a90>, 'G2'), (<__main__.myGraph object at 0x1643250>, 'G3')]
[aric@hamerkop tmp]$ python gc.py 
3713081631935493181 [(1, 2)]
3713081631935493181 [(2, 3)]
2528504235175490287 [(1, 2), (2, 3)]
True
False
[(<__main__.myGraph object at 0x1fefad0>, 'G2'), (<__main__.myGraph object at 0x27ea290>, 'G3')]

最新更新