Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Isomorphic' comparison of NetworkX Graph objects instead of the default 'address' comparison

I would like to use NetworkX Graph objects as keys in a Python dict. However, I do not want the default behavior for comparison (i.e., by the address of the object). Instead, I would like isomorphic graphs to refer to be keys to the same elements in the dict.

Is this behavior already implemented somewhere? I could not find any information in this direction.

If I have to implement it myself, is the following assessment realistic?

  • Wrap networkx.Graph in a class.
  • Define __eq__ such that it calls is_isomorphic.
  • Define __hash__ somehow (suggestions welcomed).

I think that I would have to make this wrapped Graph immutable, because:

If a class defines mutable objects and implements an __eq__() method, it should not implement __hash__(), since the implementation of hashable collections requires that a key’s hash value is immutable (if the object’s hash value changes, it will be in the wrong hash bucket).

like image 370
user1661473 Avatar asked Dec 11 '13 21:12

user1661473


People also ask

Which is better Igraph or NetworkX?

The igraph library requires less resources for compilation, and comes with additional bindings for the R and C languages which the other two lack. NetworkX is comparatively very inefficient, but it is trivial to install --- requiring no compilation at all, since it is pure python.

Can NetworkX handle large graphs?

For NetworkX, a graph with more than 100K nodes may be too large. I'll demonstrate that it can handle a network with 187K nodes in this post, but the centrality calculations were prolonged. Luckily, there are some other packages available to help us with even larger graphs.

Does NetworkX use GPU?

RAPIDS's graph algorithms like PageRank and functions like NetworkX make efficient use of the massive parallelism of GPUs to accelerate analysis of large graphs by over 1000X.


1 Answers

Here is an example of subclassing a networkx Graph and adding a eq and hash function as you describe. I'm not sure if it solves your problem but should be a start.

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

Outputs something like:

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')]
like image 193
Aric Avatar answered Sep 30 '22 16:09

Aric