我正在尋找一種方法來實時查找巨大圖中節點之間的最短路徑。它有數十萬個頂點和數百萬條邊。我知道這個問題之前已經被問過了,我想答案是使用廣度優先搜索,但我更感興趣的是知道您可以使用哪些軟件來實現它。例如,如果它已經存在一個用於在無向圖中執行bfs的庫(帶有python綁定!),那將是完全完美的。高效地在大圖中找到最短路徑
回答
補充說:
的評論讓我好奇的是,pygraph的表現是如何的OP的數量級上的問題,所以我做了一個玩具程序找出來。以下是問題的一個稍微小版本的輸出:
$ python2.6 biggraph.py 4 6
biggraph generate 10000 nodes 00:00:00
biggraph generate 1000000 edges 00:00:00
biggraph add edges 00:00:05
biggraph Dijkstra 00:01:32
biggraph shortest_path done 00:04:15
step: 1915 2
step: 0 1
biggraph walk done 00:04:15
path: [9999, 1915, 0]
對於10k節點和1M邊緣也不算太壞。重要的是要注意,Dijkstra的方式是通過pygraph計算的,爲每個節點相對於一個目標生成所有生成樹的字典(該節點是任意節點0,並且在圖中不具有特權位置)。因此,花費3.75分鐘計算的解決方案實際上得出了「從所有節點到目標的最短路徑是多少」的答案。事實上,一旦shortest_path
完成,行走答案僅僅是字典查找,基本上沒有時間。還值得注意的是,在約1.5分鐘處將預先計算的邊緣添加到圖形上是相當昂貴的。這些計時在多次運行中保持一致。
我想說這個過程很好,但我仍然在biggraph 5 6
上等待閒置的計算機(Athlon 64,4800 BogoMIPS每個處理器,全部處於核心),它已經運行了超過四分之一小時。至少內存使用穩定在0.5GB左右。其結果是:
biggraph generate 100000 nodes 00:00:00
biggraph generate 1000000 edges 00:00:00
biggraph add edges 00:00:07
biggraph Dijkstra 00:01:27
biggraph shortest_path done 00:23:44
step: 48437 4
step: 66200 3
step: 83824 2
step: 0 1
biggraph walk done 00:23:44
path: [99999, 48437, 66200, 83824, 0]
這是一個很長一段時間,但它也是一個沉重的計算(和我真的希望我醃的結果)。下面是好奇代碼:
#!/usr/bin/python
import pygraph.classes.graph
import pygraph.algorithms
import pygraph.algorithms.minmax
import time
import random
import sys
if len(sys.argv) != 3:
print ('usage %s: node_exponent edge_exponent' % sys.argv[0])
sys.exit(1)
nnodes = 10**int(sys.argv[1])
nedges = 10**int(sys.argv[2])
start_time = time.clock()
def timestamp(s):
t = time.gmtime(time.clock() - start_time)
print 'biggraph', s.ljust(24), time.strftime('%H:%M:%S', t)
timestamp('generate %d nodes' % nnodes)
bg = pygraph.classes.graph.graph()
bg.add_nodes(xrange(nnodes))
timestamp('generate %d edges' % nedges)
edges = set()
while len(edges) < nedges:
left, right = random.randrange(nnodes), random.randrange(nnodes)
if left == right:
continue
elif left > right:
left, right = right, left
edges.add((left, right))
timestamp('add edges')
for edge in edges:
bg.add_edge(edge)
timestamp("Dijkstra")
target = 0
span, dist = pygraph.algorithms.minmax.shortest_path(bg, target)
timestamp('shortest_path done')
# the paths from any node to target is in dict span, let's
# pick any arbitrary node (the last one) and walk to the
# target from there, the associated distance will decrease
# monotonically
lastnode = nnodes - 1
path = []
while lastnode != target:
nextnode = span[lastnode]
print 'step:', nextnode, dist[lastnode]
assert nextnode in bg.neighbors(lastnode)
path.append(lastnode)
lastnode = nextnode
path.append(target)
timestamp('walk done')
print 'path:', path
+1:OP正在尋找Python代碼,這個答案提供了它。 – 2010-06-14 16:08:26
對於具有巨大圖形的實時解決方案?僅Python的解決方案將不符合性能要求。 – Brandon 2010-06-14 16:38:14
我同意布蘭登。儘管它實際上取決於OP所指的「實時」。 – 2010-06-14 17:15:22
無向圖中的BFS只有大約25行代碼。你不需要一個圖書館。查看Wikipedia article中的示例代碼。
對於一個圖表,大(和你的性能限制),你可能想的Boost Graph Library,因爲它是用C++編寫。它有你正在尋找的Python bindings。
-1以上,則python綁定無法維護。 – fmark 2010-06-15 01:23:04
查看包裝Boost圖的圖工具。 – shongololo 2016-10-13 21:22:49
嗯,這取決於你有多少元數據附加到你的節點和邊緣。如果相對較少,圖形的大小將適合內存,因此我推薦使用純Python的優秀NetworkX軟件包(請參閱http://networkx.lanl.gov/reference/generated/networkx.shortest_path.html)。
對於一個更強大的解決方案,可以處理數百萬個節點,大型元數據,交易,磁盤存儲等,我已經與neo4j(http://www.neo4j.org/)很好運。它是用Java編寫的,但有Python綁定或可以作爲REST服務器運行。遍歷它是一個小竅門,但並不壞。
對於大圖,請嘗試Python接口igraph。它的核心是用C實現的,因此它可以相對容易地處理具有數百萬頂點和邊的圖。它包含BFS實現(以及其他算法),還包括Dijkstra算法和加權圖的Bellman-Ford算法。
至於「實時性」,我做了一些快速測試,以及:
from igraph import *
from random import randint
import time
def test_shortest_path(graph, tries=1000):
t1 = time.time()
for _ in xrange(tries):
v1 = randint(0, graph.vcount()-1)
v2 = randint(0, graph.vcount()-1)
sp = graph.get_shortest_paths(v1, v2)
t2 = time.time()
return (t2-t1)/tries
>>> print test_shortest_path(Graph.Barabasi(100000, 100))
0.010035698396
>>> print test_shortest_path(Graph.GRG(1000000, 0.002))
0.413572219742
根據上面的代碼段,具有100K的頂點發現在一個小世界圖中,兩個給定頂點之間的最短路徑10M邊緣(10M = 100K * 100)平均需要大約0.01003秒(平均1000次)。這是第一個測試案例,如果您正在使用社交網絡數據或其他網絡,而網絡的直徑與網絡的規模相比較小,則這是合理的估計。第二個測試是一個幾何隨機圖,其中一個點在一個二維平面上隨機丟棄,如果它們的距離小於0.002,則連接兩個點,從而產生一個包含大約1M個頂點和6.5M邊的圖。在這種情況下,最短路徑計算需要更長的時間(因爲路徑本身更長),但它仍然非常接近實時:平均爲0.41357秒。
聲明:我是igraph的作者之一。
感謝您的指針。並將它放在Ubuntu/Debian存儲庫和PyPi上是一個優點。你怎麼知道我最近剛剛用Python進行圖形分析? – msw 2010-06-15 14:08:43
嗯,我不知道它...... :) – 2010-06-15 15:22:55
根據您擁有哪種附加信息,A *可能非常有效。特別是,如果給定一個節點,您可以計算從該節點到目標的成本估計值,A *是最優效率的。
它包括Dijkstra算法,A *, 「最短路徑」 算法。
- 1. 谷歌地圖。找到最短路徑
- 2. C# - 最短路徑地圖查找
- 3. 找到有向圖的最短路徑
- 4. 圖最短路徑?
- 5. 找到使用谷歌地圖爲大量節點的最短路徑
- 6. 在直接圖中找到第二條最短路徑
- 7. 在非加權圖中找到最短路徑
- 8. 在圖中找到第二條最短路徑(帶回溯)
- 9. 找到最大增益的最短路徑
- 10. 最短路徑查找器
- 11. 自定義地圖最短路徑
- 12. 找到從頭到尾頂點的圖中的最短路徑
- 13. 找到第k個最短路徑?
- 14. 如何找到最短路徑成本?
- 15. 使用BFS找到最短路徑
- 16. 在Vim中高效地讀取路徑
- 17. JGraphT圖最短路徑
- 18. 谷歌地圖API將目的地劃分爲組並找到最短路徑
- 19. 谷歌地圖API:尋找最短路徑
- 20. 最短路徑
- 21. 查找矩陣中的最短路徑
- 22. 尋找迷宮中的最短路徑
- 23. 查找DLV中的最短路徑
- 24. 在C++中找到最短路徑權重
- 25. 最有效的最短路徑算法非負邊緣圖
- 26. 彩色邊圖中的最短路徑
- 27. 優先圖中的最短路徑
- 28. 圖中最短路徑的數量
- 29. DAG最短路徑
- 30. OrientDB:在最短路徑
只有在圖形中的每個邊具有相同的權重時,BFS才能正常工作。除此之外,無論如何,您可能會比Dijkstra的算法,統一成本搜索或A *獲得更好的性能。 – 2010-06-14 17:13:09
您的圖形是否明確存儲在覈心內存中?或者你是否在對圖表進行歸納描述? – 2010-06-14 17:13:58
我想我應該提到這一點。 :/數據存儲在數據庫中。但是我正在考慮將圖存儲在某種基於磁盤的數據結構中,因爲它很重要,可以完全讀入內存。當然,這意味着需要整個圖形在內存中的軟件無法工作。 – 2010-06-15 16:39:06