Dijkstra'nın devasa grafiklerde algoritması


15

Dijkstra'ya çok aşinayım ve algoritma hakkında özel bir sorum var. Eğer büyük bir grafik, örneğin 3,5 milyar düğüm (tüm OpenStreetMap verileri) varsa, o zaman açıkça grafik bellekte olamazdı, bu yüzden grafik bir veritabanındaki diskte depolanır.

Bu tür grafiklerde en kısa yolları hesaplamak için kullanılabilir kütüphaneler vardır. Bunu nasıl yapıyorlar? Daha spesifik olarak, Dijkstra'nın algoritmasını çalıştırmak için grafiğin gerekli kısmını nasıl yüklerler?

Ziyaret edilen her bir tepe noktasının bitişiklik listesini almak, istatistiksel verilerime göre 10.000 düğüm başına yaklaşık 1.500 veritabanı sorgusu gerektiriyordu, bu yüzden açıkça yaptıkları gibi değil. Bu çok yavaş olurdu.

Nasıl yapıyorlar? Kendim uygulamaya çalışıyorum.


2
Dijkstra kullandıklarından emin misiniz? Açıkladığınız duruma daha uygun olabilecek en kısa yol algoritmaları vardır.
David Richerby

1
Kodu incelediniz mi? Nasıl bilebiliriz? "veritabanı sorguları" - Umarım grafik depolamak için DBMS kullanmazsınız?
Raphael

@DavidRicherby evet Eminim, bu bağlantıya bakın
dimitris93

2
"[C] saf C koduna bakmak son derece sıkıcı bir süreç olurdu." Ancak kodun ne yaptığını bilmenin tek yolu budur. Yani sizden sadece sizin için sıkıcı görevinizi yapmamızı istiyorsunuz, bu da sorunuzun en büyük reklamı değil ...
David Richerby

1
@Shiro Açıkça "Bunu nasıl yapıyorlar?" Bu gerçekten sormak istediğiniz soru değilse, yeniden ifade etmeniz gerekir.
Raphael

Yanıtlar:


6

Bu tür grafiklerde en kısa yolları hesaplamak için kullanılabilir kütüphaneler vardır. Bunu nasıl yapıyorlar? Daha spesifik olarak, Dijkstra'nın algoritmasını çalıştırmak için grafiğin gerekli kısmını nasıl yüklerler?

Bir DB, diskten okunacak özel bir dosya biçimi ve bir bellek içi ayarı kullanabilirsiniz.

Ancak bir DB kullanma deneyimim, 'basit' bağlantılı liste biçimine dayalı olarak kendi dosya biçiminizi yazmaktan kabaca 5 ila 10 kat daha yavaş ve çok daha fazla bellek yoğun.

İyi bir şey, açık kaynak kodlu OSM kullanan çeşitli yazılım çerçeveleri vardır, böylece koda doğrudan bakabilirsiniz, örneğin buraya bakın . In GraphHopper açık kaynak yönlendirme motoru bir bellekten anahtara çok kolaydır bellek ayarına ayarı (tabanlı disk) eşlenen - her ikisi de aynı biçimi kullanarak. "Mmap" ayarı, bellek kısıtlamalı mobil cihazlarda kullanıma bile izin verir ve ikincisi, örneğin sunucuda gerekli RAM'e sahipseniz çok daha hızlı performans gösterir. Örneğin, dünya çapında bir grafik (> 100mio düğüm) için, 8-10gb RAM'e ve ayrıca her şeyi daha da hızlandırmak istiyorsanız, örneğin Kasılma Hiyerarşileri ile - istediğiniz her araç için yaklaşık 5-8gb daha fazla RAM'e ihtiyacınız var.

Biçim çok basittir ve temelde yalnızca ihtiyacınız olan verileri kompakt hale getirmek için birkaç püf noktası ile saklar. Bununla ilgili daha fazla bilgiyi buradan edinebilirsiniz . Feragatname: GraphHopper'in yazarıyım.

Diğer cevaplarla ilgili olarak:

Dijkstras algoritması uygulanabilir durumdayken bu sorun için uygun değildir.

'Normal' Dijkstra çok makul performans gösterebilir (3mio düğüm örneğiniz gibi ülke çapındaki sorgular için <1'ler) ve 'teori anlamında' optimaldir ancak üretim senaryolarında hızlı olmak için biraz ayarlamaya ihtiyaç duyar. Kasılma Hiyerarşileri gibi teknikler, bunun çift yönlü bir modifikasyonunu kullanır ve çok iyi performans gösterir.

yol ağları hiyerarşik ve düzlemseldir.

yol ağları sadece araba için hiyerarşiktir ve düzlemsel değildir (köprüler, tüneller, ...)


Bir sorum daha var. 'Den NodeIDen yakın düğümü nasıl buluyorsunuz latitude/longitude? En kısa A-> B yolunu hesaplamak için gereklidir. Ayrıca, A ve B'nin düğüm olarak bulunmayabileceğini de aklımızda tutmalıyız, çünkü her metrekarede bir düğüm yoktur. Bu yüzden A ve B'nin en yakın 2 Düğüm Kimliğini bulmamız gerekiyor
dimitris93

Bu, örneğin GraphHopper için ~ 500m yarıçapa sahip bir hücrede NodeID'leri etkili bir şekilde saklayan bir tür dörtlü olan LocationIndexTree'de yapılır. Hiçbir şey bulunmazsa yarıçapı belirli bir dereceye kadar genişletir. Bu teoride basit gibi görünse de, alanı geçen kenarlara sahip olabileceğiniz için çok karmaşıktır, oluştururken ve sorgularken verimli olmanız ve çok daha fazlası gerekir.
Karussell

KD-Trees en yakın komşuyu ararken daha verimli değil mi? KD Ağaçları yerine neden QuadTrees seçtiniz? Yönlendirme motorum için şu anda KD-Ağaçları uyguluyorum. QuadTrees uygulamaya başladım, ancak durdum çünkü KD-Trees'ın aynı şey olduğunu, ancak kodlaması daha kolay ve en yakın komşuyu sorgulamak için daha hızlı olduğunu düşündüm. Yanlış mıyım ?
dimitris93

Quadtrees kullanırken, sınırlayıcı kutuyu usecase için daha kritik olan bir depolama avantajı vererek açık bir şekilde depolamaya gerek yoktur (ayrıca quadtrees'i daha kolay buluyorum;)). Sorgu hızı bir sorun değildir. Aslında birisi bu denemeleri inceledi ve diğer uygulamalardan daha iyi performans gösterdi. KD ağaçları, ama her şeyin belirli bir uygulamaya bağlı olduğunu varsayıyorum ...
Karussell

Bu pdf'nin 9. sayfasından stanford'dan bakarsanız, KD-Trees'da en yakın komşuyu aramak sınırlayıcı kutuları bilmenizi gerektirmez. Ve başka bir şey, önceden tüm noktaları bildiğimiz için dengeli bir logn yüksekliği ağacı oluşturabiliriz. Dörtlü ağaçların kd ağaçlarına göre herhangi bir avantajı olduğunu düşünüyor musunuz?
dimitris93

2

Öncelik kuyruğuna bitişik olan tüm kenarları koymanıza gerek yoktur. Dijkstra'nın algoritmasına "Yalan" ve ona en kısa tepe noktasını verin, v, tepe noktasına gelen, diyelim ki, y yığını çıkardı. Daha sonra, v kuyruktan çekildiğinde "ayy" diyorsunuz. Bir hata yaptım ve bu köşe noktasını da vermelisiniz, ki bu da w köşesine en yakın olanıdır. Bu şekilde doğru bir çözüme sahip olacağınız ve kuyruk büyüklüğünün sadece bir olay yerine bir olay tepe noktasına önemli ölçüde azaltıldığı kolayca görülebilir. Gereksinim duyulduğunda, her zaman en yakın tepe noktasını vermek için olayları takip etmeniz gerekir. Yol ağlarının yanlış olduğu iddia edilen yorumlardan biri. Aslında, bir çalışma onların oldukça düzlemsel olmadıklarını göstermiştir. Birçok düzlemsizliğe neden olan bir şehir üzerinden köprülerden geçen tüm otoyolları düşünün.


0

Daha etkin varyantlar "benzer" olarak değerlendirilebilse de, uygulanabilir durumdayken Dijkstras algoritması bu sorun için uygun değildir. çeşitli basitleştirmeler var. yol ağları hiyerarşik ve düzlemseldir . İşte temel yaklaşımlar. bölge genellikle "karayolu ağlarında rota planlama" olarak bilinir.

  • bir grafik yapısı bitişiklik listesi verilerinden "derlenebilir". alıntı yaptığınız kütüphanede bu yaklaşım SpatiaLite. bu grafik yapıları, grafik konumlarının ikili kodlanmış tamsayılar vb. ile temsil edildiği sıkıştırılmış bir ikili biçimde saklanır, böylece grafik gösterimi ve manipülasyonu, tüm yol adlarını depolamaktan çok daha az yer kaplar; SpatiaLite algoritması "çevrimiçi" değil ve tamamen bellekte çalışıyor gibi görünüyor.

  • paralel / dağıtılmış algoritmalar vardır. bkz. örneğin Ölçeklenebilir GPU Grafiği Gezinme / Merrill, Garland, Grimshaw.

  • soru istemci-sunucu terminolojisini kullanmaktadır, yani "sorgular". algoritmalar istemci-sunucu anlamında veritabanını "sorgulayarak" çalışmaz. SQL gibi daha üst düzey sorgu dilleri veritabanına bir arabirimdir ve minimum yolları hesaplamak için istek iletmek için kullanılabilir, ancak algoritma tarafından dahili olarak kullanılmaz. algoritma genellikle "veritabanı içinde" yani tamamen "sunucu tarafında" çalışır. bu nedenle veritabanı sorgularına en kısa yol algoritması yazmak küçük ağlar için mümkündür ancak orta / büyük ölçekli ağlar için uygun değildir.

  • küçük yüzdelerdeki tahminlerin kabul edilebileceği başka bir yaklaşım daha vardır. temel fikir düğümler arasındaki mesafelerin bir dizinini tutmaktır. bakınız örn . Büyük Grafiklerde En Kısa Yolların Hızlı ve Doğru Tahmini / Gubichev, Bedathur, Seufert, Weikum

  • bu (235p!) Doktora tezi özellikle geçerlidir. Yol Ağlarında / Schultes'te Rota Planlama

  • bazı algoritmalar bu fikirlerin birçoğunu kullanır ve diğerleri, yüksek derecede ayarlanmış ve tescilli ve rekabetçi ticari sırlar üzerinde sınırlıdır. örneğin, Google'ın. bu konuda bazı yanıltıcı medya olabilir. örneğin Google Maps Olası yapar Basit, Zarif Algoritma hangi iddialar / Google'ın herhangi kaynak gösterilmeden Dijkstras algoritma kullanır ima eder.


1
Google Haritalar kesinlikle Dijskstra'dan daha iyi bir şeye geçmiştir. Her yarım yetkin geliştirici yol haritaları için A * kullanırdı, ancak önceki işimde Google'ın motorunun <100 ms'de bir yol noktası aracılığıyla 2500 km'lik yolları yeniden planlayabildiğini öğrendik. Bu A * için çok hızlı, bu yüzden ArcFlags gibi bir şey kullanmaları muhtemel.
MSalters

Karussell'in cevabı, "Dijkstras algoritması, uygulanabilir durumdayken bu sorun için en uygun değil olarak kabul edilir" diye tartışılan bu açılış cümlesini tartışır. Schultes tezinde (erken), aynı zamanda bölgenin çok kapsamlı / güncel bir araştırması olan ve "hiyerarşik ve düzlemsel" "yaklaşımları" açıklayan çok güçlü bir destek var. ne yazık ki, cursory arama üzerine açık literatürde gerçek google algoritmalarının bir göstergesi yok gibi görünüyor.
Mart'ta vzn

-2

Böyle son derece büyük veri setlerinde, bu kadar hızlı sonuçlar elde etmek için, en iyi yolu birleşik bul veri yapısını yol sıkıştırması ile kullanıyorum. Ancak, sadece Djikstra algoritmasını kullanmak ve optimize etmek istiyorsanız, grafikteki her düğümün hangi bilgilere sahip olduğu ortaya çıkar. Büyük olasılıkla 1.500 sorgunun tümünü yapmanız gerekmez.

Örneğin, aşağıdaki örneği ele alalım. Diyelim ki, 2 aktör arasındaki (Bacon numarası) ayrılma derecelerini bulmaya çalışıyorum ve en az ağırlıklı yolu (mümkün olan en yeni filmleri kullanan yol) bulmak istiyorum. Şimdi diyelim ki adlı bir fonksiyonum var shortestPath(actor A, actor B);. Aşağıdaki senaryoyu düşünün.

Aktör A 1970'den beri oynuyorsa ve Aktör B 2000'den beri hareket ediyorsa, o bilgi verildiğinde, Aktör B'nin ilk filminden başlayıp Aktör A'ya giden yolu bulmak çok daha mantıklı olacaktır. Aktör A'nın oynadığı her filmde yinelemeye karşıydı.

Bu nedenle, ana nokta, Djikstra algoritmasının optimizasyonunun gerçekten veri kümenizin ne olduğuna bağlı olmasıdır. Algoritmanızı optimize etmenize yardımcı olması için veri kümenizin bizim için neleri içerdiği hakkında daha fazla bilgi sağlamanız gerekir.

DÜZENLEME: Diyelim ki aynı ülkede 2 şehir arasındaki en kısa yolu bulmaya çalışıyorsunuz ve bu ülke daha genişse (örneğin, Arjantin), o zaman sorgularınızı ülkelerin boylam ve enlemine göre yapabilirsiniz sınırları. Ardından, yatay olarak değil, dikey olarak (boylam kullanarak) hareket etmeye başlayabilirsiniz. Ofc, istisna işleme gerekir, ama genel fikir olsun.


1
Union-Find'u Dijkstra'da nasıl kullanıyorsunuz?
Raphael

Veriler uzamsal veriler, enlem ve boylamdır. Bunun açık olduğunu düşündüm.
dimitris93
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.