Algoritma Dijkstra pada grafik besar

15

Saya sangat akrab dengan Dijkstra dan saya memiliki pertanyaan spesifik tentang algoritme. Jika saya memiliki grafik yang sangat besar, misalnya 3,5 miliar node (semua data OpenStreetMap) maka saya jelas tidak akan dapat memiliki grafik dalam memori, sehingga grafik disimpan pada disk di dalam basis data.

Ada perpustakaan yang tersedia untuk menghitung jalur terpendek pada grafik tersebut. bagaimana mereka melakukan ini? Lebih khusus lagi, bagaimana mereka memuat bagian yang diperlukan dari grafik untuk menjalankan algoritma Dijkstra?

Mengambil daftar kedekatan dari setiap titik yang dikunjungi akan membutuhkan sekitar 1.500 permintaan basis data per 10.000 node menurut data statistik saya, sehingga jelas bukan bagaimana mereka melakukannya. Itu akan terlalu lambat.

Bagaimana mereka melakukannya? Saya mencoba menerapkannya sendiri.

dimitris93
sumber
2
Apakah Anda yakin mereka menggunakan Dijkstra? Ada banyak algoritma jalur terpendek lainnya yang mungkin lebih cocok untuk situasi yang Anda gambarkan.
David Richerby
1
Sudahkah Anda melihat kode? Bagaimana kita tahu? "query database" - Saya harap Anda tidak menggunakan DBMS untuk menyimpan grafik?
Raphael
@ DavidRicherby ya saya yakin, lihat tautan ini
dimitris93
2
"[Saya] akan menjadi proses yang sangat membosankan untuk melihat kode C murni." Tapi itu satu-satunya cara mengetahui apa yang dikerjakan kode. Jadi Anda hanya meminta kami untuk melakukan tugas yang membosankan bagi Anda, yang bukan iklan terbaik untuk pertanyaan Anda ...
David Richerby
1
@ Siro Anda secara eksplisit bertanya, "Bagaimana mereka melakukan ini?" Jika itu bukan pertanyaan yang ingin Anda tanyakan, Anda perlu mengulangi.
Raphael

Jawaban:

6

Ada perpustakaan yang tersedia untuk menghitung jalur terpendek pada grafik tersebut. bagaimana mereka melakukan ini? Lebih khusus lagi, bagaimana mereka memuat bagian yang diperlukan dari grafik untuk menjalankan algoritma Dijkstra?

Anda dapat menggunakan DB, format file khusus untuk dibaca dari disk dan pengaturan di dalam memori.

Tetapi dari pengalaman saya menggunakan DB kira-kira 5 sampai 10 kali lebih lambat dan lebih banyak kehabisan memori daripada menulis format file Anda sendiri berdasarkan format daftar tertaut 'sederhana'.

Yang menyenangkan adalah ada beberapa kerangka kerja perangkat lunak menggunakan OSM yang bersifat open source sehingga Anda dapat melihat langsung ke dalam kode misalnya lihat di sini . Dalam mesin perutean open source GraphHopper , sangat mudah untuk beralih dari pengaturan yang dipetakan memori (berbasis disk) ke pengaturan di dalam memori - keduanya menggunakan format yang sama. Pengaturan "mmap" bahkan memungkinkan penggunaan pada perangkat seluler yang dibatasi memori dan yang terakhir kinerjanya jauh lebih cepat jika Anda memiliki RAM yang diperlukan misalnya pada server. Misalnya untuk grafik di seluruh dunia (> 100 juta node) Anda kemudian membutuhkan sekitar 8-10gb RAM, ditambah banyak lebih banyak RAM jika Anda ingin mempercepat semuanya lebih lanjut misalnya dengan Hirarki Kontraksi - kira-kira 5-8gb lebih untuk setiap kendaraan yang Anda inginkan.

Formatnya sangat sederhana dan pada dasarnya hanya menyimpan data yang Anda butuhkan dengan beberapa trik untuk membuatnya kompak. Baca lebih lanjut di sini . Penafian: Saya penulis GraphHopper.

Mengenai jawaban lain:

Algoritma Dijkstras sementara berlaku dianggap tidak optimal untuk masalah ini

Dijkstra 'normal' dapat berkinerja sangat masuk akal (<1 untuk kueri di seluruh negara seperti contoh 3mio Anda) dan optimal dalam 'pengertian teori' tetapi perlu sedikit penyesuaian untuk mendapatkan skenario skenario produksi yang cepat. Dan teknik seperti Hierachies Kontraksi menggunakan modifikasi dua arah dan berkinerja sangat baik.

jaringan jalan bersifat hierarkis dan planar.

jaringan jalan bersifat hierarkis untuk mobil saja dan tidak planar (jembatan, terowongan, ...)

Karussell
sumber
Saya punya satu pertanyaan lagi. Bagaimana Anda menemukan NodeIDsimpul terdekat dari latitude/longitude? Itu diperlukan untuk menghitung jalur terpendek A-> B. Dan kita juga perlu mengingat bahwa A dan B mungkin tidak ada sebagai simpul, karena tidak setiap meter persegi berisi sebuah simpul. Jadi kita perlu menemukan 2 NodeID terdekat dari A dan B.
dimitris93
Itu dilakukan di LocationIndexTree yang merupakan jenis quadtree yang menyimpan secara efisien NodeIDs dalam sel yang memiliki misalnya untuk GraphHopper radius ~ 500m. Jika tidak ada yang ditemukan itu memperluas jari-jari ke tingkat tertentu. Ini kedengarannya sederhana secara teori tetapi sangat kompleks karena Anda mungkin memiliki tepi melintasi area, Anda harus efisien ketika membuat dan menanyakannya dan banyak lagi.
Karussell
Bukankah KD-Trees lebih efisien saat mencari tetangga terdekat? Mengapa Anda memilih QuadTrees daripada KD-Trees? Saya menerapkan KD-Trees untuk mesin perutean saya sekarang. Saya mulai mengimplementasikan QuadTrees tetapi saya berhenti karena saya pikir bahwa KD-Trees adalah hal yang sama, tetapi lebih mudah untuk kode, dan lebih cepat untuk menanyakan tetangga terdekat. Apakah aku salah ?
dimitris93
Saat menggunakan quadtrees, tidak perlu menyimpan kotak pembatas secara eksplisit sehingga memberikan keuntungan penyimpanan, yang lebih penting untuk penggunaan saya (juga saya temukan quadtrees lebih mudah;)). Kecepatan permintaan tidak menjadi masalah. Bahkan seseorang mempelajari percobaan tersebut dan mengungguli implementasi lainnya termasuk. Pohon KD, tapi saya anggap semua tergantung pada implementasi spesifik ...
Karussell
Jika Anda melihat halaman 9 pdf ini dari stanford, mencari tetangga terdekat di KD-Trees tidak mengharuskan Anda untuk mengetahui kotak terikat sama sekali. Dan satu hal lagi adalah karena kita tahu semua poin sebelumnya, kita dapat membuat pohon tinggi seimbang yang seimbang. Apakah Anda masih yakin bahwa quadtrees memiliki keunggulan dibandingkan kd-tree?
dimitris93
2

Anda tidak perlu meletakkan semua tepi yang berdekatan dalam antrian prioritas. "Berbohong" pada algoritme Dijkstra dan berikan hanya simpul terpendek, v, insiden pada simpul itu, katakanlah w, ditarik dari tumpukan. Kemudian, ketika v ditarik dari antrian Anda mengatakan "oops" Saya membuat kesalahan dan seharusnya memberi Anda simpul ini juga, yang merupakan terdekat terdekat dengan simpul w. Sangat mudah terlihat bahwa dengan cara ini Anda akan memiliki solusi yang benar dan ukuran antrian secara dramatis dikurangi menjadi satu titik kejadian saja, bukan banyak. Anda perlu melacak insiden untuk selalu memberikan titik terdekat berikutnya - bila diperlukan. Salah satu komentar mengklaim jaringan jalan adalah planar yang tidak benar. Faktanya, sebuah penelitian menunjukkan bahwa mereka sangat non-planar. Pikirkan semua jalan raya yang menyeberang melalui jembatan melalui kota yang memicu banyak ketidaklancaran.

pengguna49040
sumber
0

Algoritma Dijkstras sementara berlaku dianggap tidak optimal untuk masalah ini meskipun varian yang lebih efisien dapat dianggap sebagai "serupa". ada berbagai penyederhanaan. jaringan jalan bersifat hierarkis dan planar . di sini adalah pendekatan dasar. daerah ini umumnya dikenal sebagai "perencanaan rute dalam jaringan jalan".

  • struktur grafik dapat "dikompilasi" dari data daftar adjacency. ini adalah pendekatan di perpustakaan yang Anda kutip , SpatiaLite. struktur grafik ini disimpan dalam format biner terkompresi di mana lokasi grafik diwakili oleh bilangan bulat yang disandikan biner, dll., sehingga representasi grafik dan manipulasi membutuhkan ruang yang jauh lebih sedikit daripada menyimpan semua nama jalan dll .; tampaknya algoritma SpatiaLite tidak "online" dan berjalan sepenuhnya dalam memori.

  • ada algoritma paralel / terdistribusi. lihat misalnya Traversal Grafik Grafik Scalable / Merrill, Garland, Grimshaw.

  • pertanyaannya menggunakan terminologi client-server yaitu "query". algoritma tidak berjalan dengan "meminta" database dalam arti client-server. bahasa permintaan tingkat yang lebih tinggi seperti SQL adalah antarmuka ke database dan dapat digunakan untuk mengirimkan permintaan untuk menghitung rute minimal tetapi tidak digunakan oleh algoritma secara internal. umumnya algoritma berjalan "di dalam database" yaitu seluruhnya "sisi server". jadi karenanya menulis algoritma jalur terpendek dalam permintaan basis data layak untuk jaringan kecil tetapi tidak untuk skala menengah / besar.

  • ada pendekatan lain di mana estimasi dalam persentase kecil dapat diterima. ide dasarnya adalah untuk menjaga indeks jarak antar node. lihat mis. Estimasi Cepat dan Akurat dari Jalur Terpendek dalam Grafik Besar / Gubichev, Bedathur, Seufert, Weikum

  • tesis Phd (235p!) ini sangat berlaku. Perencanaan Rute di Jaringan Jalan / Schultes

  • beberapa algoritma menggunakan banyak dari ide-ide ini dan yang lainnya, sangat disesuaikan dan berpemilik dan mendekati rahasia perdagangan yang kompetitif. misalnya Google. mungkin ada beberapa media yang menyesatkan tentang hal ini. eg Algoritma Sederhana, Elegan yang Membuat Google Maps Kemungkinan yang mengklaim / menyiratkan Google menggunakan algoritma Dijkstras tanpa kutipan.

vzn
sumber
1
Google Maps tentu saja telah ditingkatkan ke sesuatu yang lebih baik daripada Dijskstra. Setiap pengembang kompeten setengah jalan akan menggunakan A * untuk peta jalan, tetapi pada pekerjaan saya sebelumnya, kami menemukan bahwa mesin Google dapat merencanakan ulang 2500 km rute melalui titik jalan dalam <100 ms. Itu terlalu cepat untuk A *, jadi mungkin mereka menggunakan sesuatu seperti ArcFlags.
MSalters
Jawaban Karussell menantang kalimat pembuka ini "Algoritma Dijkstras sementara berlaku dianggap tidak optimal untuk masalah ini" yang tidak diharapkan akan kontroversial. ada dukungan yang sangat kuat untuk pernyataan dalam tesis Schultes (awal) yang juga merupakan survei yang sangat komprehensif / baru-baru ini di daerah tersebut, dan juga menjelaskan "hierarki dan planar" "perkiraan". Sayangnya sepertinya tidak ada indikasi algoritma google yang sebenarnya dalam literatur terbuka tentang pencarian sepintas.
vzn
-2

Pada set data yang sangat besar seperti itu, untuk mendapatkan hasil yang begitu cepat, saya merasa lebih baik menggunakan struktur data union-find dengan kompresi jalur. Namun, jika Anda mencari untuk hanya menggunakan algoritma Djikstra dan mengoptimalkannya, itu tergantung pada informasi apa yang dimiliki masing-masing simpul dalam grafik. Kemungkinan besar Anda tidak perlu melakukan semua 1.500 kueri.

Sebagai contoh, perhatikan contoh berikut. Katakanlah saya mencoba untuk menemukan derajat pemisahan antara 2 aktor (nomor Bacon) dan saya ingin menemukan jalur yang paling tidak berbobot (jalur menggunakan film terbaru mungkin). Sekarang, katakanlah saya memiliki fungsi yang dipanggil shortestPath(actor A, actor B);. Pertimbangkan skenario berikut.

Jika Aktor A telah berakting sejak tahun 1970 dan Aktor B telah berakting sejak tahun 2000, maka mengingat info itu, akan jauh lebih logis untuk menemukan jalur mulai dari film pertama dari Aktor B dan kemudian melintasi jalan Anda ke Aktor A. Sebagai menentang iterasi melalui setiap film yang diperankan oleh Aktor A.

Jadi, intinya adalah bahwa optimalisasi algoritma Djikstra benar-benar tergantung pada apa set data Anda. Anda perlu memberikan lebih banyak informasi tentang apa yang dibutuhkan set data Anda agar kami dapat membantu Anda mengoptimalkan algoritma Anda.

EDIT: Katakanlah Anda mencoba menemukan jalur terpendek antara 2 kota di negara yang sama dan jika negara ini lebih panjang daripada yang lebih luas, misalnya Argentina, maka Anda dapat melakukan kueri berdasarkan garis bujur dan garis lintang negara batas-batas. Kemudian Anda dapat mulai melintasi secara vertikal (menggunakan bujur) sebagai kebalikan dari horizontal. Ofc, perlu ada penanganan pengecualian, tetapi Anda mendapatkan ide umum.

Jonathan
sumber
1
Bagaimana Anda menggunakan Union-Find di Dijkstra?
Raphael
Data tersebut adalah data spasial, lintang dan bujur. Saya pikir itu sudah jelas.
dimitris93