2013-12-11 10 views
5

Chciałbym użyć obiektów NetworkX Graph jako kluczy w Pythonie dict. Jednak nie chcę domyślnego zachowania dla porównania (tj. Przez adres obiektu). Zamiast tego chciałbym, aby wykresy izomorficzne były kluczami do tych samych elementów w dict.Porównanie "izomorficzne" obiektów NetworkX Graph zamiast domyślnego porównania "adresu"

Czy to zachowanie zostało już gdzieś zaimplementowane? Nie mogłem znaleźć żadnych informacji w tym kierunku.

Jeśli muszę sam je wdrożyć, czy następująca ocena jest realistyczna?

  • Zawiń networkx.Graph w klasie.
  • Zdefiniuj __eq__ w taki sposób, że wywołuje is_isomorphic.
  • W jakiś sposób zdefiniuj __hash__ (sugestie przyjęte).

Myślę, że będę musiał zrobić to owinięty Graph niezmienne, because:

Jeśli klasa definiuje zmienne obiektów i wdraża metodę __eq__(), nie powinien wdrożyć __hash__(), od momentu wdrożenia hashable kolekcje wymagają, aby wartość skrótu klucza była niezmienna (jeśli wartość mieszania obiektu ulegnie zmianie, będzie ona w niewłaściwym buforze mieszającym).

+1

Czy dobrze rozumiem, że chcesz isophorphic wykresy mieć taki sam hash value()? Jeśli tak, to pomoże ci to pytanie? - http://en.wikipedia.org/wiki/Graph_canonization – Aric

+0

@Aric Jeśli muszę to zaimplementować, to tak, chcę, aby wykres izomorficzny miał tę samą wartość '__hash __()'. Jednak kanonizacja grafów może być przesadna. Miałem na myśli, aby uzyskać [uporządkowaną sekwencję stopni] (http://en.wikipedia.org/wiki/Degree_sequence#Degree_sequence), a następnie ją zahaczyć. W ten sposób nieizomorficzne wykresy mogą mieć ten sam skrót, ale wykresy izomorficzne nie mogą mieć różnej wartości mieszania. Ale zanim zacznę to robić, mam nadzieję, że ktoś już gdzieś to zrobił :) – user1661473

+0

Jeśli możesz znaleźć sposób na unikatową liczbę całkowitą z sekwencji stopni, możesz użyć jej jako funkcji hash(). – Aric

Odpowiedz

3

Oto przykład z instacji do NetworkX Graph i dodanie eq i hash funkcję jak opisujesz. Nie jestem pewien, czy to rozwiązuje twój problem, ale powinien być początkiem.

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

wyjść coś takiego:

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')] 
[[email protected] 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')] 
+1

Dzięki. Prawdopodobnie skończę robić coś takiego. Jeśli ktoś ma podobny problem, polecam wywołanie 'freeze' na twoich obiektach' myGraph' (co czyni je niezmiennymi) przed użyciem ich jako kluczy. – user1661473

Powiązane problemy