我收到以下错误:
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'
我知道定义__eq__
意味着默认哈希函数消失了函数,我必须重新定义__hash__
方法,但我不知道如何做到这一点。有人可以建议哈希函数的实现吗?
提前致谢。
这是我的代码。
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]))
答案 0 :(得分:1)
也许尝试添加到Vertex:
def __hash__():
return hash(str(self.id))
(您也可以选择不同属性的混合,不仅仅是id;您选择的属性应该是可以自己清洗的。)