Reputation: 25
I am getting the following error:
Traceback (most recent call last):
File "dijkastras.py", line 146, in <module>
g.add_edge(vertices[i], k[0], int(k[1]))
File "dijkastras.py", line 82, in add_edge
self.vertices[frm].add_neighbour(self.vertices[to], weight)
File "dijkastras.py", line 16, in add_neighbour
self.adjacent[neighbour] = weight
TypeError: unhashable type: 'Vertex'
I know that defining an __eq__
means the default hash function goes away function and that I have to redefine the __hash__
method but I have no idea how to do that. Could someone suggest an implementation for the hash function?
Thanks in advance.
Here is my code.
import sys
import heapq
from functools import total_ordering
@total_ordering
class Vertex:
def __init__(self, node):
self.id = node
self.adjacent = {}
# Set the distances to infinity for all nodes
self.distance = sys.maxsize
self.visited = False
self.previous = None
def add_neighbour(self, neighbour, weight=0):
self.adjacent[neighbour] = weight
def get_connections(self):
return self.adjacent.keys()
def get_id(self):
return self.id
def get_weight(self, neighbour):
return self.adjacent[neighbour]
def set_distance(self, dist):
self.distance = dist
def get_distance(self):
return self.distance
def set_previous(self, prev):
self.previous = prev
def set_visited(self):
self.visited = True
def __str__(self):
return str(self.id) + ' adjacent: '
+ str([x.id for x in self.adjacent])
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.distance == other.distance
return NotImplemented
def __lt__(self, other):
if isinstance(other, self.__class__):
return self.distance < other.distance
return NotImplemented
class Graph:
def __init__(self):
self.vertices = {}
self.num_vertices = 0
def __iter__(self):
return iter(self.vertices.values())
def add_vertex(self, node):
self.num_vertices += 1
new_vertex = Vertex(node)
self.vertices[node] = new_vertex
return new_vertex
def get_vertex(self, n):
if n in self.vertices:
return self.vertices[n]
return None
def get_vertices(self):
return self.vertices.keys()
def add_edge(self, frm, to, weight=0):
if frm not in self.vertices:
self.add_vertex(frm)
if to not in self.vertices:
self.add_vertex(to)
self.vertices[frm].add_neighbour(self.vertices[to], weight)
self.vertices[to].add_neighbour(self.vertices[frm], weight)
def set_previous(self, current):
self.previous = current
def get_previous(self, current):
return self.previous
def shortest(vertex, path):
''' Find the shortest path from vertex.previous'''
if vertex.previous:
path.append(vertex.previous.get_id())
shortest(vertex.previous, path)
return
def dijkstra(aGraph, start, target):
start.set_distance(0)
univisted = [(v.get_distance(), v) for v in aGraph]
print(univisted)
heapq.heapify(univisted)
while len(univisted):
uv = heapq.heappop(univisted)
current = uv[1]
current.set_visited()
for next in current.adjacent:
if next.visited:
continue
new_dist = current.get_distance() + current.get_weight(next)
if new_dist < next.get_distance():
next.set_distance(new_dist)
next.set_previous(current)
print('updated : current = %s next = %s new_dist = %s'
% (current.get_id(), next.get_id(), next.get_distance()))
else:
print('not updated : current = %s next = %s new_dist = %s'
% (current.get_id(), next.get_id(), next.get_distance()))
while len(univisted):
heapq.heappop(univisted)
univisted = [(v.get_distance(), v) for v in aGraph if not v.visited]
heapq.heapify(univisted)
if __name__ == '__main__':
g = Graph()
text = open('Graph.txt').read().split('\n')
vertices = text[0].split()
for i in vertices:
g.add_vertex(i)
vert_all = []
for i in range(1, 11):
vert_all.append(list(zip(vertices, text[i].split()[1:])))
filtered_vert_all = []
for i in vert_all:
filtered = [x for x in i if x[1] is not '0']
filtered_vert_all.append(filtered)
# print(filtered_vert_all)
for i, j in enumerate(filtered_vert_all):
for k in j:
print(vertices[i], k[0], int(k[1]))
g.add_edge(vertices[i], k[0], int(k[1]))
for v in g:
for w in v.get_connections():
vid = v.get_id()
wid = w.get_id()
print('( {} , {}, {:d})'.format(vid, wid, v.get_weight(w)))
dijkstra(g, g.get_vertex('E'), g.get_vertex('J'))
target = g.get_vertex('E')
path = [target.get_id()]
shortest(target, path)
print('The shortest path is: {}'.format(path[::-1]))
Upvotes: 0
Views: 628
Reputation: 4900
Based on this part of Python documentation:
It is advised to mix together the hash values of the components of the object that also play a part in comparison of objects by packing them into a tuple and hashing the tuple.
Here's an example:
class Vertex:
def __init__(self, prop1, prop2):
self.prop1 = prop1
self.prop2 = prop2
def __hash__(self):
return hash((self.prop1, self.prop2))
Upvotes: 0
Reputation: 5017
Maybe try something like adding to Vertex class:
def __hash__(self):
return hash(str(self.id))
(You can also choose a mix of different attributes, not only id; the ones you choose should be hashable themselves).
Upvotes: 2