[英]Possible problem with python dijkstra's algorithm implementation using classes
所以我一直試圖在 python 中創建一個圖形程序,其中包含在其中實現的 dfs、bfs 和 dijkstra 算法的類,到目前為止已經提出:
class Vertex:
def __init__(self, name):
self.name = name
self.connections = {}
def addNeighbour(self, neighbour, cost):
self.connections[neighbour] = cost
class Graph:
def __init__(self):
self.vertexs = {}
def addVertex(self, newVertex):
new = Vertex(newVertex)
self.vertexs[newVertex] = new
def addEdge(self, src, dest, cost):
self.vertexs[src].addNeighbour(self.vertexs[dest], cost)
def dfs(self, start, end, visited):
visited[start] = True
print(start, end=' ')
if start == end:
# End node found
return True
else:
# Use depth first search
for connection in graph.vertexs[start].connections:
if visited[connection.name] == False:
if self.dfs(connection.name, end, visited) == True:
# Return true to stop extra nodes from being searched
return True
def bfs(self, start, end, visited, queue):
if len(queue) == 0:
# Queue is empty
queue.append(start)
visited[start] = True
currentNode = queue.pop(0)
print(currentNode, end=' ')
if start == end:
# End node found
return True
else:
# Do breadth first search
for connection in graph.vertexs[currentNode].connections:
if visited[connection.name] == False:
# Queue all its unvisited neighbours
queue.append(connection.name)
for newNode in queue:
self.bfs(newNode, end, visited, queue)
def dijkstra(self, current, currentDistance, distances, visited, unvisited):
for neighbour, distance in distances.items():
if neighbour.name not in unvisited:
continue
newDistance = currentDistance + distance
if unvisited[neighbour.name] is None or unvisited[neighbour.name] > newDistance:
unvisited[neighbour.name] = newDistance
visited[current] = currentDistance
del unvisited[current]
if not unvisited:
return True
candidates = [node for node in unvisited.items() if node[1]]
current, currentDistance = sorted(candidates)[0]
self.dijkstra(current, currentDistance, graph.vertexs[current].connections, visited, unvisited)
return visited
def setup():
graphList = {
# Node number: [destination number, cost]
0: {4: 6, 6: 1},
1: {6: 2},
2: {0: 9, 1: 4, 3: 3},
3: {4: 7},
4: {1: 3, 5: 5},
5: {0: 2, 1: 6, 4: 3},
6: {2: 4, 3: 6}
}
graph = Graph()
for i in range(len(graphList)):
graph.addVertex(i)
for dictLength in range(len(graphList)):
for key in list(graphList[dictLength].keys()):
graph.addEdge(dictLength, key, graphList[dictLength][key])
return graph, graphList
graph, graphList = setup()
print("DFS travsersal path from node 1 to node 0:")
graph.dfs(1, 0, [False] * len(graphList))
print()
print("BFS traversal path from node 1 to node 0:")
graph.bfs(1, 0, [False] * len(graphList), [])
print()
print("Shortest possible path from node 1 to 0:")
result = graph.dijkstra(1, 0, graph.vertexs[2].connections, {}, {node: None for node in graphList})
cost = result[len(result) - 1]
path = " ".join([str(arrInt) for arrInt in list(result.keys())])
print(path, "costing", cost)
但是我認為輸出似乎有問題。 如果我想從節點 1 到節點 0,當前輸出是:
從節點1到節點0的DFS遍歷路徑:1 6 2 0 從節點1到節點0的BFS遍歷路徑:1 6 2 3 0 3 4 5 從節點1到0的最短路徑: 1 0 3 4 5 6 2 costing 10
但是,我認為輸出應該是:
從節點1到節點0的DFS遍歷路徑:1 6 2 0 4 5 3 從節點1到節點0的BFS遍歷路徑:1 6 2 3 0 4 5 從節點1到0的最短路徑:1 6 2 0 costing 15
任何人都可以看到這有什么問題嗎?
謝謝!
您的代碼中實際上有幾個問題:
您需要向 Djikstra 算法指定停止的位置,在您的代碼中沒有提到什么是結束節點(在您的示例中它應該是 0)
計算成本為cost = result[len(result) - 1]
不會得到字典中的最后一個元素(字典通常沒有排序,所以“最后一個元素”甚至不存在!)。 您應該檢索成本為cost = result[end]
,其中end
是最終節點,在您的示例中為 0 。
您將函數調用為result = graph.dijkstra(1, 0, graph.vertexs[2].connections, {}, {node: None for node in graphList})
,但是,此函數的第三個參數應該是初始節點的一組鄰居,因此在您的情況下應該是graph.vertexs[1].connections
。
綜上所述,為了使代碼按預期工作,您可以對函數進行如下修改:
def dijkstra(self, current, currentDistance, distances, visited, unvisited, end):
for neighbour, distance in distances.items():
if neighbour.name not in unvisited:
continue
newDistance = currentDistance + distance
if unvisited[neighbour.name] is None or unvisited[neighbour.name] > newDistance:
unvisited[neighbour.name] = newDistance
visited[current] = currentDistance
if current == end:
return visited
del unvisited[current]
if not unvisited:
return True
candidates = [node for node in unvisited.items() if node[1]]
current, currentDistance = sorted(candidates)[0]
self.dijkstra(current, currentDistance, graph.vertexs[current].connections, visited, unvisited, end)
return visited
並按如下方式調用它:
print("Shortest possible path from node 1 to 0:")
start = 1
end = 0
result = graph.dijkstra(start, 0, graph.vertexs[start].connections, {}, {node: None for node in graphList}, end)
cost = result[end]
path = " ".join([str(arrInt) for arrInt in list(result.keys())])
print(path, "costing", cost)
通過這樣做,輸出變成
從節點 1 到 0 的最短路徑: 1 6 2 0 costing 15
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.