SciTech-BigDataAIML-Algorithm-Heuristic啟發式- 帶weight(權重)Graph(圖,無向)的最優路線規劃 : Dijkstra迪傑斯特拉演算法"由節點路線無向Graph"得出"Routing Table(路由表)"

abaelhe發表於2024-11-06

Dijkstra迪傑斯特拉演算法

用“Graph”作出簡圖:

圖例:


推導"選定起點"的Routing Table(路由表)

行號 節點 最短距離 前一節點 已訪問完全
1 A 0
2 B 2 A T
3 C 12 F T
4 D 7 B T
5 E 8 B T
6 F 9 D,E T

上表的用法:

  • 表格的"第1行"是"起點"; 圖例:上表是圖上的節點"A"作為起點;
  • 由"終點"起始,用"每一節點"查表得到的"前一節點";
    一步步倒推,可得出 "起點" 到 "終點" 的 "最短完整路線".
    例如:要求解“A點出發,到C點的最短路線”,
    根據上表,可查表得出:
    • 終點"C"節點的資料記錄行的"行號"是 "3"(第3行),
    • "最短路線" 為12(由"起點A"到"終點C"),
    • "最短完整路線"("起點A"到"終點C"):
      由終點C起始, 遞推的用"每一節點"查表得到的"前一節點", 一步步倒推, 可得出:
      $ C \overset{3}{\leftarrow} F \overset{2}{\leftarrow} D \overset{5}{\leftarrow} B \overset{2}{\leftarrow} A $
    • 注意:"最短路徑"可能有不只一條;
      例如: "起點A"到"終點F"的"最短路線"(最短距離都為9)
      • $ F \overset{2}{\leftarrow} D \overset{5}{\leftarrow} B \overset{2}{\leftarrow} A $
      • $ F \overset{1}{\leftarrow} E \overset{6}{\leftarrow} B \overset{2}{\leftarrow} A $

如何根據"節點路線Graph"得出"Routing Table(路由表)"

將 Graph 轉化為 Dictionary 資料結構:
例如圖示的 Graph 可轉化為:

MAX_DIST = 99999999
DIST_INDEX = 0
PREV_INDEX = 1
SOURCE = "A"

graph_dict = { # Graph 轉化為 Dictionary 資料結構
 "A": [0, ["A"], ("B", 2), ("D", 8)],
 "B": [MAX_DIST, [], ("A", 2), ("D", 5), ("E", 6)],
 "C": [MAX_DIST, [], ("E", 9), ("F", 3)],
 "D": [MAX_DIST, [], ("A", 8), ("B", 5), ("E", 3), ("F", 2)],
 "E": [MAX_DIST, [], ("B", 6), ("D", 3), ("F", 1), ("C", 9)],
 "F": [MAX_DIST, [], ("D", 2), ("E", 1), ("C", 3)],
}

queue_dict = {}
queue_dict[SOURCE] = graph_dict[SOURCE] # 開始只需要將初始"起點A"加入"任務佇列"

while len(queue_dict) > 0: # 需要更新計算“後繼”節點的"任務佇列"
    (node, val) = result_dict.popitem() # 取出一個任務"節點"
    (min_dist, prev, *edges) = val # 得到其"當前累加權重","前一個節點" 和 "其edges"
    print("\n Processing : %r: min_dist:%d, prev:%r" % (node, min_dist, prev))

    for next, weight in edges: # 迭代每一條 edge
        next_val = graph_dict[next]
        accu_dist = min_dist + weight # 由"當前節點" 計算 "下一節點" 的"累加權重"
        if accu_dist < next_val[DIST_INDEX]: # 計算得出"更優"的"累加權重":
            next_val[DIST_INDEX] = accu_dist # 將"更優"的"累加權重"更新到"下一節點"
            next_val[PREV_INDEX] = [node] # "更優"選擇的"前一節點", 更新到"下一節點"
            queue_dict[next] = next_val # 有更新的"下一節點"要加入"任務佇列"
            print(
                "  Edge from:%r, to:%r, accu_dist:%d, prev:%r"
                % (node, next, accu_dist, next_val[PREV_INDEX])
            )
        elif accu_dist == next_val[DIST_INDEX]: # 多個"前節點"有"同優"的"累加權重"
            if node not in next_val[PREV_INDEX]:
                next_val[PREV_INDEX].append(node) # 追加到"前節點"列表
            print(
                "  Edge from:%r, to:%r, accu_dist:%d, prev:%r"
                % (node, next, accu_dist, next_val[PREV_INDEX])
            )
        else:
            print("  Edge from:%r, to:%r, accu_dist:%d, " % (node, next, accu_dist))

print("\n" + "#" * 10 + "\nRouting Table:\n") # 列印路由表
items = list(graph_dict.items())
for n, val in sorted(items, key=lambda x: x[0]):
    print(
        "Node:%r, accu_dist:% 2d, prev:%r" % (n, val[DIST_INDEX], val[PREV_INDEX])
    )

執行結果:

root@localhost:~/storage/shared/AAAAA# python dijkstra.py

 Processing : 'A': min_dist:0, prev:['A']
  Edge from:'A', to:'B', accu_dist:2, prev:['A']
  Edge from:'A', to:'D', accu_dist:8, prev:['A']

 Processing : 'D': min_dist:8, prev:['A']
  Edge from:'D', to:'A', accu_dist:16,
  Edge from:'D', to:'B', accu_dist:13,
  Edge from:'D', to:'E', accu_dist:11, prev:['D']
  Edge from:'D', to:'F', accu_dist:10, prev:['D']

 Processing : 'F': min_dist:10, prev:['D']
  Edge from:'F', to:'D', accu_dist:12,
  Edge from:'F', to:'E', accu_dist:11, prev:['D', 'F']
  Edge from:'F', to:'C', accu_dist:13, prev:['F']

 Processing : 'C': min_dist:13, prev:['F']
  Edge from:'C', to:'E', accu_dist:22,
  Edge from:'C', to:'F', accu_dist:16,

 Processing : 'E': min_dist:11, prev:['D', 'F']
  Edge from:'E', to:'B', accu_dist:17,
  Edge from:'E', to:'D', accu_dist:14,
  Edge from:'E', to:'F', accu_dist:12,
  Edge from:'E', to:'C', accu_dist:20,

 Processing : 'B': min_dist:2, prev:['A']
  Edge from:'B', to:'A', accu_dist:4,
  Edge from:'B', to:'D', accu_dist:7, prev:['B']
  Edge from:'B', to:'E', accu_dist:8, prev:['B']

 Processing : 'E': min_dist:8, prev:['B']
  Edge from:'E', to:'B', accu_dist:14,
  Edge from:'E', to:'D', accu_dist:11,
  Edge from:'E', to:'F', accu_dist:9, prev:['E']
  Edge from:'E', to:'C', accu_dist:17,

 Processing : 'F': min_dist:9, prev:['E']
  Edge from:'F', to:'D', accu_dist:11,
  Edge from:'F', to:'E', accu_dist:10,
  Edge from:'F', to:'C', accu_dist:12, prev:['F']

 Processing : 'C': min_dist:12, prev:['F']
  Edge from:'C', to:'E', accu_dist:21,
  Edge from:'C', to:'F', accu_dist:15,

 Processing : 'D': min_dist:7, prev:['B']
  Edge from:'D', to:'A', accu_dist:15,
  Edge from:'D', to:'B', accu_dist:12,
  Edge from:'D', to:'E', accu_dist:10,
  Edge from:'D', to:'F', accu_dist:9, prev:['E', 'D']

##########
Routing Table:
Node:'A', accu_dist: 0, prev:['A']
Node:'B', accu_dist: 2, prev:['A']
Node:'C', accu_dist: 12, prev:['F']
Node:'D', accu_dist: 7, prev:['B']
Node:'E', accu_dist: 8, prev:['B']
Node:'F', accu_dist: 9, prev:['E', 'D']

相關文章