Thuật toán của Dijkstra trên đồ thị khổng lồ


15

Tôi rất quen thuộc với Dijkstra và tôi có một câu hỏi cụ thể về thuật toán. Nếu tôi có một biểu đồ khổng lồ, ví dụ 3,5 tỷ nút (tất cả dữ liệu OpenStreetMap) thì rõ ràng tôi sẽ không thể có biểu đồ trong bộ nhớ, vì vậy biểu đồ được lưu trữ trên đĩa trong cơ sở dữ liệu.

Có các thư viện có sẵn để tính toán các đường dẫn ngắn nhất trên các biểu đồ như vậy. Làm thế nào để họ làm điều này? Cụ thể hơn, làm thế nào để họ tải phần cần thiết của biểu đồ để chạy thuật toán của Dijkstra?

Tìm nạp danh sách kề của mỗi đỉnh được truy cập sẽ cần khoảng 1.500 truy vấn cơ sở dữ liệu trên 10.000 nút theo dữ liệu thống kê của tôi, vì vậy rõ ràng đó không phải là cách họ thực hiện. Đó sẽ là cách quá chậm.

Họ làm nó như thế nào? Tôi đang cố gắng tự thực hiện nó.


2
Bạn có chắc chắn họ sử dụng Dijkstra? Có rất nhiều thuật toán đường dẫn ngắn nhất khác có thể phù hợp hơn với tình huống bạn mô tả.
David Richerby

1
Bạn đã nhìn vào mã? Làm sao chúng ta biết? "truy vấn cơ sở dữ liệu" - Tôi hy vọng bạn không sử dụng DBMS để lưu trữ biểu đồ?
Raphael

@DavidR Richby vâng tôi chắc chắn, hãy nhìn vào liên kết này
dimitris93

2
"[Tôi] sẽ là một quá trình cực kỳ tẻ nhạt để xem xét mã C thuần túy." Nhưng đó là cách duy nhất để biết mã làm gì. Vì vậy, bạn chỉ cần yêu cầu chúng tôi phải làm nhiệm vụ của bạn tẻ nhạt cho bạn, đó không phải là quảng cáo lớn nhất cho câu hỏi của bạn ...
David Richerby

1
@Shiro Bạn hỏi rõ ràng, "Làm thế nào để họ làm điều này?" Nếu đó không thực sự là câu hỏi bạn muốn hỏi, bạn cần phải viết lại.
Raphael

Câu trả lời:


6

Có các thư viện có sẵn để tính toán các đường dẫn ngắn nhất trên các biểu đồ như vậy. Làm thế nào để họ làm điều này? Cụ thể hơn, làm thế nào để họ tải phần cần thiết của biểu đồ để chạy thuật toán của Dijkstra?

Bạn có thể sử dụng DB, định dạng tệp tùy chỉnh để đọc từ đĩa và cài đặt trong bộ nhớ.

Nhưng từ kinh nghiệm của tôi khi sử dụng DB thì chậm hơn khoảng 5 đến 10 lần và cường độ bộ nhớ cao hơn nhiều so với việc viết định dạng tệp của riêng bạn dựa trên định dạng danh sách được liên kết 'đơn giản'.

Điều tốt là có một số khung phần mềm sử dụng OSM là nguồn mở để bạn có thể xem ngay mã, ví dụ xem tại đây . Trong công cụ định tuyến nguồn mở GraphHopper, rất dễ dàng chuyển từ cài đặt ánh xạ bộ nhớ (dựa trên đĩa) sang cài đặt trong bộ nhớ - cả hai đều sử dụng cùng một định dạng. Cài đặt "mmap" thậm chí cho phép sử dụng trên các thiết bị di động bị hạn chế bộ nhớ và thiết bị sau hoạt động nhanh hơn rất nhiều nếu bạn có RAM cần thiết, ví dụ như trên máy chủ. Ví dụ, đối với đồ thị trên toàn thế giới (> 100 triệu nút), sau đó bạn cần khoảng 8-10gb RAM, cộng thêm nhiều RAM nếu bạn muốn tăng tốc mọi thứ hơn nữa, ví dụ như với Contraction HVELies - khoảng 5-8gb cho mỗi chiếc xe bạn muốn.

Định dạng rất đơn giản và về cơ bản chỉ lưu trữ dữ liệu bạn cần với một vài thủ thuật để làm cho nó nhỏ gọn. Đọc thêm về nó ở đây . Tuyên bố miễn trừ trách nhiệm: Tôi là tác giả của GraphHopper.

Về các câu trả lời khác:

Thuật toán Dijkstras trong khi áp dụng được coi là không tối ưu cho vấn đề này

Dijkstra 'bình thường' có thể thực hiện rất hợp lý (<1 giây đối với các truy vấn trên toàn quốc như ví dụ về các nút 3 triệu của bạn) và tối ưu theo 'lý thuyết lý thuyết' nhưng cần điều chỉnh một chút để nhanh chóng trong các kịch bản sản xuất. Và các kỹ thuật như Contraction Hierachies sử dụng một sửa đổi hai chiều của nó và thực hiện rất tốt.

mạng lưới đường được phân cấp và phẳng.

mạng lưới đường được phân cấp chỉ dành cho xe hơi và không phải mặt phẳng (cầu, đường hầm, ...)


Tôi có một câu hỏi nữa. Làm thế nào để bạn tìm thấy NodeIDnút gần nhất từ latitude/longitude? Đó là yêu cầu để tính đường đi ngắn nhất A-> B. Và chúng ta cũng cần lưu ý rằng A và B có thể không tồn tại dưới dạng các nút, bởi vì không phải mỗi mét vuông đều chứa một nút. Vì vậy, chúng ta cần tìm 2 NodeID gần nhất của A và B.
dimitris93

Điều đó được thực hiện trong LocationIndexTree, đây là loại hình tứ giác lưu trữ hiệu quả các NodeID trong một ô, ví dụ như đối với GraphHopper có bán kính ~ 500m. Nếu không tìm thấy gì, nó sẽ mở rộng bán kính lên đến một mức độ nhất định. Điều này nghe có vẻ đơn giản trên lý thuyết nhưng rất phức tạp vì bạn có thể có các cạnh đi qua khu vực, bạn cần phải hiệu quả khi tạo và truy vấn nó và nhiều hơn nữa.
Karussell

Không phải KD-Cây hiệu quả hơn khi tìm kiếm người hàng xóm gần nhất? Tại sao bạn chọn QuadTrees trên KD-Plants? Tôi đang triển khai KD-Plants cho công cụ định tuyến của mình ngay bây giờ. Tôi bắt đầu triển khai QuadTrees nhưng tôi đã dừng lại vì tôi nghĩ rằng KD-Plants là điều tương tự, nhưng dễ viết mã hơn và nhanh hơn để truy vấn người hàng xóm gần nhất. Tôi có lầm không ?
dimitris93

Khi sử dụng quadtrees, không cần phải lưu trữ rõ ràng hộp giới hạn mang lại lợi thế lưu trữ, điều này quan trọng hơn đối với usecase của tôi (tôi cũng thấy dễ dàng hơn quadtrees;)). Tốc độ truy vấn không phải là một vấn đề. Trong thực tế, ai đó đã nghiên cứu những cố gắng như vậy và nó vượt trội hơn bất kỳ triển khai nào khác. Cây KD, nhưng tôi cho rằng tất cả phụ thuộc vào việc triển khai cụ thể ...
Karussell

Nếu bạn xem trang 9 của pdf này từ stanford, việc tìm kiếm người hàng xóm gần nhất trong KD-Plants không yêu cầu bạn phải biết các hộp giới hạn. Và một điều nữa là vì chúng ta biết tất cả các điểm trước đó, chúng ta có thể tạo ra một cây cân bằng về chiều cao logn. Bạn vẫn tích cực rằng tứ giác có bất kỳ lợi thế nào so với cây kd không?
dimitris93

2

Bạn không cần đặt tất cả các cạnh liền kề trong hàng ưu tiên. "Nói dối" với thuật toán của Dijkstra và chỉ cung cấp cho nó đỉnh ngắn nhất, v, sự cố cho đỉnh, giả sử w, kéo ra khỏi ngăn xếp. Sau đó, khi v được kéo ra khỏi hàng đợi, bạn nói "rất tiếc" Tôi đã mắc lỗi và cũng nên đưa cho bạn đỉnh này, đây là đỉnh gần nhất với đỉnh w. Dễ dàng thấy rằng bằng cách này, bạn sẽ có một giải pháp chính xác và kích thước hàng đợi được giảm đáng kể xuống chỉ còn một đỉnh thay vì nhiều đỉnh. Mặc dù vậy, bạn cần theo dõi các sự cố để luôn đưa ra đỉnh gần nhất tiếp theo - khi được yêu cầu. Một trong những ý kiến ​​cho rằng mạng lưới đường là không chính xác. Trên thực tế, một nghiên cứu đã chỉ ra rằng chúng rất phi phẳng. Hãy nghĩ về tất cả các đường cao tốc băng qua các cây cầu thông qua một thành phố tạo ra nhiều phi hành tinh.


0

Thuật toán Dijkstras trong khi áp dụng được coi là không tối ưu cho vấn đề này mặc dù các biến thể hiệu quả hơn có thể được coi là "tương tự". có nhiều đơn giản hóa. mạng lưới đường được phân cấpphẳng . đây là những cách tiếp cận cơ bản khu vực này thường được gọi là "quy hoạch tuyến đường trong mạng lưới đường bộ".

  • một cấu trúc biểu đồ có thể được "biên dịch" từ dữ liệu danh sách kề. đây là cách tiếp cận trong thư viện mà bạn trích dẫn , SpatiaLite. các cấu trúc biểu đồ này được lưu trữ ở định dạng nhị phân nén trong đó các vị trí biểu đồ được biểu thị bằng các số nguyên được mã hóa nhị phân, v.v., vì vậy việc biểu diễn và thao tác biểu đồ chiếm ít không gian hơn so với lưu trữ tất cả các tên đường, v.v .; có vẻ như thuật toán SpatiaLite không "trực tuyến" và chạy hoàn toàn trong bộ nhớ.

  • có các thuật toán song song / phân tán. xem ví dụ: Đồ thị GPU có thể mở rộng / Merrill, Vòng hoa, Grimshaw.

  • câu hỏi sử dụng thuật ngữ máy khách-máy chủ tức là "truy vấn". các thuật toán không chạy bằng cách "truy vấn" cơ sở dữ liệu theo nghĩa máy khách-máy chủ. Các ngôn ngữ truy vấn cấp cao hơn như SQL là một giao diện cho cơ sở dữ liệu và có thể được sử dụng để truyền yêu cầu để tính toán các tuyến tối thiểu nhưng không được thuật toán sử dụng trong nội bộ. nói chung thuật toán chạy "bên trong cơ sở dữ liệu" tức là hoàn toàn "phía máy chủ". do đó, việc viết một thuật toán đường dẫn ngắn nhất trong các truy vấn cơ sở dữ liệu là khả thi đối với các mạng nhỏ nhưng không phải là các mạng có quy mô trung bình / lớn.

  • có một cách tiếp cận khác trong đó ước tính trong tỷ lệ phần trăm nhỏ có thể được chấp nhận. ý tưởng cơ bản là giữ một chỉ số khoảng cách giữa các nút. xem ví dụ: Ước tính nhanh và chính xác các đường đi ngắn nhất trong đồ thị lớn / Gubichev, Bedathur, Seufert, Weikum

  • Luận án này (235p!) Phd đặc biệt được áp dụng. Quy hoạch tuyến đường trong Mạng lưới đường / Schultes

  • một số thuật toán sử dụng nhiều trong số những ý tưởng này và những ý tưởng khác, được điều chỉnh cao và độc quyền và tràn ngập các bí mật thương mại cạnh tranh. ví dụ: Google. có thể có một số phương tiện truyền thông sai lệch về chủ đề này. ví dụ: Thuật toán đơn giản, thanh lịch giúp Google Maps có thể tuyên bố / ngụ ý Google sử dụng thuật toán Dijkstras mà không cần trích dẫn.


1
Google Maps chắc chắn đã nâng cấp lên thứ gì đó tốt hơn Dijskstra. Mỗi nhà phát triển có thẩm quyền nửa chừng sẽ sử dụng A * cho bản đồ đường bộ, nhưng tại công việc trước đây của tôi, chúng tôi đã phát hiện ra rằng động cơ của Google có thể thay thế 2500 km tuyến đường thông qua một điểm dừng trong <100 ms. Điều đó quá nhanh đối với A *, vì vậy có thể họ sử dụng thứ gì đó như ArcFlags.
MSalters

Câu trả lời của Karussell thách thức câu mở đầu này "thuật toán Dijkstras trong khi áp dụng được coi là không tối ưu cho vấn đề này" mà không mong đợi sẽ gây tranh cãi. có sự hỗ trợ rất mạnh mẽ cho sự khẳng định trong luận án Schultes (từ rất sớm), đây cũng là một khảo sát rất toàn diện / gần đây về khu vực, và cũng giải thích "các xấp xỉ" phân cấp và phẳng ". Thật không may, dường như không có dấu hiệu nào cho thấy các thuật toán google thực tế trong tài liệu mở về tìm kiếm chữ thảo.
vzn

-2

Trên các tập dữ liệu cực lớn như vậy, để có được kết quả nhanh như vậy, tôi thấy tốt nhất là sử dụng cấu trúc dữ liệu tìm kết hợp với nén đường dẫn. Tuy nhiên, nếu bạn đang tìm cách chỉ sử dụng thuật toán của Djikstra và tối ưu hóa điều đó, thì đó là thông tin mà mỗi nút trong biểu đồ có. Bạn rất có thể không cần thực hiện tất cả 1.500 truy vấn.

Ví dụ, hãy xem xét ví dụ sau. Hãy nói rằng tôi đang cố gắng tìm mức độ phân tách giữa bất kỳ 2 diễn viên nào (số Bacon) và tôi muốn tìm đường dẫn có trọng số thấp nhất (đường dẫn sử dụng các bộ phim mới nhất có thể). Bây giờ, hãy nói rằng tôi có một chức năng được gọi là shortestPath(actor A, actor B);. Hãy xem xét các kịch bản sau đây.

Nếu Diễn viên A đã diễn xuất từ ​​năm 1970 và Diễn viên B đã diễn xuất từ ​​năm 2000, sau đó được cung cấp thông tin đó, sẽ hợp lý hơn nhiều khi tìm thấy một con đường bắt đầu từ bộ phim đầu tiên của Diễn viên B và sau đó đi qua Diễn viên A. Như trái ngược với việc lặp đi lặp lại qua mỗi bộ phim Diễn viên A đã đóng.

Do đó, điểm chính là việc tối ưu hóa thuật toán của Djikstra thực sự phụ thuộc vào tập dữ liệu của bạn là gì. Bạn sẽ cần cung cấp thêm thông tin về những gì bộ dữ liệu của bạn đòi hỏi cho chúng tôi để giúp bạn tối ưu hóa thuật toán của mình.

EDIT: Giả sử bạn đang cố gắng tìm con đường ngắn nhất giữa 2 thành phố trong cùng một quốc gia và nếu quốc gia này dài hơn rộng hơn, chẳng hạn như Argentina, thì bạn có thể thực hiện các truy vấn của mình dựa trên kinh độ và vĩ độ của các quốc gia ranh giới. Sau đó, bạn có thể bắt đầu di chuyển ngang (sử dụng kinh độ) trái ngược với chiều ngang. Tất nhiên, cần phải có xử lý ngoại lệ, nhưng bạn có được ý tưởng chung.


1
Làm thế nào để bạn sử dụng Union-Find trong Dijkstra?
Raphael

Dữ liệu là dữ liệu không gian, vĩ độ và kinh độ. Tôi nghĩ rằng đó là rõ ràng.
dimitris93
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.