最短路徑
「從 A 到 B 怎麼走最近」是圖上最常被問的問題。NetworkX 依有沒有權重、權重可否為負,自動或手動選擇演算法。
兩點之間
import networkx as nx
G = nx.Graph()
G.add_weighted_edges_from([(1, 2, 1), (2, 3, 2), (1, 3, 10), (3, 4, 1)])
nx.has_path(G, 1, 4)
nx.shortest_path(G, 1, 4) # 邊數最少:[1, 3, 4]
nx.shortest_path(G, 1, 4, weight="weight") # 權重最小:[1, 2, 3, 4]
nx.shortest_path_length(G, 1, 4, weight="weight")
沒指定 weight 時,每條邊長度視為 1。指定之後,走的是加總最小的那條路。
單源、所有配對
nx.single_source_shortest_path(G, 1) # 從 1 到其他點(無權重)
nx.single_source_dijkstra_path(G, 1, weight="weight")
nx.shortest_path(G, weight="weight") # 所有配對,回傳巢狀 dict
圖很大時不要輕易算 all-pairs,記憶體與時間都會爆。
平均路徑與直徑
這兩個函式要求圖是連通的(有向圖則要強連通)。不連通時先取最大元件,或改用只在連通對上平均的寫法。
演算法怎麼選
| 情況 | 常用函式 |
|---|---|
| 無權重 | 廣度優先,shortest_path |
| 非負權重 | Dijkstra,dijkstra_path |
| 可能有負權重(無負環) | Bellman–Ford,bellman_ford_path |
一般呼叫 shortest_path(..., weight="weight") 即可;它會依圖的狀況選擇合適實作。
權重語意
Dijkstra 把權重當距離:數字越大越遠。若邊權重代表「互動次數」,必須先轉換,否則結果會跟直覺相反。