อัลกอริทึมของ Dijkstra บนกราฟขนาดใหญ่


15

ฉันคุ้นเคยกับ Dijkstra มากและมีคำถามเฉพาะเกี่ยวกับอัลกอริทึม หากฉันมีกราฟขนาดใหญ่เช่น 3.5 พันโหนด (ข้อมูล OpenStreetMap ทั้งหมด) จากนั้นฉันจะไม่สามารถมีกราฟในหน่วยความจำได้อย่างชัดเจนดังนั้นกราฟจะถูกเก็บไว้ในดิสก์ในฐานข้อมูล

มีห้องสมุดสำหรับคำนวณเส้นทางที่สั้นที่สุดบนกราฟดังกล่าว พวกเขาทำเช่นนี้ได้อย่างไร โดยเฉพาะพวกเขาจะโหลดส่วนที่ต้องการของกราฟเพื่อเรียกใช้อัลกอริทึมของ Dijkstra ได้อย่างไร

การดึงรายการ adjacency ของแต่ละจุดสุดยอดที่เข้าชมจะต้องใช้ฐานข้อมูล 1,500 แบบสอบถามต่อ 10,000 โหนดตามข้อมูลสถิติของฉันดังนั้นจึงไม่ใช่วิธีการที่ชัดเจน นั่นจะช้าเกินไป

พวกเขาทำมันได้อย่างไร? ฉันพยายามที่จะใช้มันด้วยตัวเอง


2
คุณแน่ใจหรือว่าพวกเขาใช้ Dijkstra มีอัลกอริธึมพา ธ สั้นที่สุดอื่น ๆ อีกมากมายที่อาจเหมาะสมกับสถานการณ์ที่คุณอธิบายมากขึ้น
David Richerby

1
คุณเคยดูโค้ดหรือไม่ เราจะรู้ได้อย่างไร? "การสืบค้นฐานข้อมูล" - ฉันหวังว่าคุณจะไม่ใช้ DBMS สำหรับจัดเก็บกราฟ?
Raphael

@DavidRicherby ใช่ฉันแน่ใจว่าดูที่ลิงค์นี้
dimitris93

2
"[I] จะเป็นกระบวนการที่น่าเบื่ออย่างยิ่งที่จะดูรหัส C บริสุทธิ์" แต่นั่นเป็นวิธีเดียวที่จะรู้ว่าโค้ดทำอะไร ดังนั้นคุณเพียงแค่ขอให้เราทำงานที่น่าเบื่อสำหรับคุณซึ่งไม่ใช่โฆษณาที่ยิ่งใหญ่ที่สุดสำหรับคำถามของคุณ ...
David Richerby

1
@Shiro คุณถามอย่างชัดเจนว่า "พวกเขาทำสิ่งนี้ได้อย่างไร" หากนั่นไม่ใช่คำถามที่คุณต้องการถามจริงๆคุณจำเป็นต้องใช้ถ้อยคำใหม่
Raphael

คำตอบ:


6

มีห้องสมุดสำหรับคำนวณเส้นทางที่สั้นที่สุดบนกราฟดังกล่าว พวกเขาทำเช่นนี้ได้อย่างไร โดยเฉพาะพวกเขาจะโหลดส่วนที่ต้องการของกราฟเพื่อเรียกใช้อัลกอริทึมของ Dijkstra ได้อย่างไร

คุณสามารถใช้ DB ซึ่งเป็นรูปแบบไฟล์ที่กำหนดเองเพื่ออ่านจากแผ่นดิสก์และการตั้งค่าในหน่วยความจำ

แต่จากประสบการณ์ของฉันในการใช้ฐานข้อมูลนั้นช้าลงประมาณ 5 ถึง 10 เท่าและหน่วยความจำที่มากขึ้นกว่าการเขียนรูปแบบไฟล์ของคุณเองโดยใช้รูปแบบรายการที่ลิงก์แบบ 'เรียบง่าย'

สิ่งที่ดีคือมีกรอบซอฟต์แวร์หลายใช้ OSM ซึ่งเป็นแหล่งที่มาเปิดเพื่อให้คุณสามารถมองขวาเป็นรหัสเช่นดูที่นี่ ในเครื่องมือกำหนดเส้นทางโอเพนซอร์ส GraphHopperมันง่ายมากที่จะเปลี่ยนจากการตั้งค่าการแมปหน่วยความจำ (ตามดิสก์) เป็นการตั้งค่าในหน่วยความจำ - โดยใช้รูปแบบเดียวกัน การตั้งค่า "mmap" ช่วยให้สามารถใช้งานบนอุปกรณ์พกพาที่ จำกัด หน่วยความจำและอุปกรณ์รุ่นหลังจะทำงานได้เร็วขึ้นมากหากคุณมี RAM ที่จำเป็นเช่นบนเซิร์ฟเวอร์ เช่นสำหรับกราฟทั่วโลก (> โหนด 100mio) จากนั้นคุณต้องมี RAM 8-10gb และเพิ่ม RAM อีกมากถ้าคุณต้องการเร่งความเร็วทุกอย่างเพิ่มเติมเช่นกับ Contraction Hierarchies - ประมาณ 5-8gb สำหรับรถทุกคันที่คุณต้องการ

รูปแบบนั้นง่ายมากและเก็บเฉพาะข้อมูลที่คุณต้องการด้วยเทคนิคเล็กน้อยเพื่อให้กะทัดรัด อ่านข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ที่นี่ ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียน GraphHopper

เกี่ยวกับคำตอบอื่น ๆ :

อัลกอริทึม Dijkstras ในขณะที่ใช้ถือว่าไม่เหมาะสมสำหรับปัญหานี้

'ปกติ' Dijkstra สามารถทำงานได้อย่างสมเหตุสมผล (<1s สำหรับการสืบค้นทั่วประเทศเช่นตัวอย่างโหนด 3 mio ของคุณ) และเหมาะสมที่สุดใน 'การรับรู้ทางทฤษฎี' แต่ต้องการการปรับแต่งเล็กน้อยเพื่อให้รวดเร็วในสถานการณ์การผลิต และเทคนิคเช่น Contraction Hierachies ใช้การปรับเปลี่ยนแบบสองทิศทางและทำงานได้ดีมาก

เครือข่ายถนนเป็นลำดับชั้นและภาพถ่าย

เครือข่ายถนนเป็นลำดับชั้นสำหรับรถยนต์เท่านั้นและไม่ใช่ภาพถ่าย (สะพาน, อุโมงค์, ... )


ฉันมีอีกหนึ่งคำถาม คุณจะค้นหาNodeIDโหนดที่ใกล้ที่สุดจากได้latitude/longitudeอย่างไร ที่จำเป็นในการคำนวณเส้นทางที่สั้นที่สุด A-> B และเราต้องจำไว้ว่า A และ B อาจไม่มีอยู่เป็นโหนดเพราะไม่ใช่ทุกตารางเมตรมีโหนด ดังนั้นเราจำเป็นต้องค้นหา NodeID ที่ใกล้เคียงที่สุดของ A และ B
dimitris93

ที่ทำใน LocationIndexTree ซึ่งเป็นชนิดของควอดทรีที่จัดเก็บ NodeIDs ในเซลล์ได้อย่างมีประสิทธิภาพเช่นสำหรับ GraphHopper รัศมีของ ~ 500m หากไม่พบสิ่งใดเลยมันจะขยายรัศมีออกไปในระดับหนึ่ง สิ่งนี้ฟังดูง่ายในทางทฤษฎี แต่มีความซับซ้อนมากเนื่องจากคุณอาจมีขอบข้ามพื้นที่คุณจำเป็นต้องมีประสิทธิภาพในการสร้างและทำการสืบค้นและอื่น ๆ อีกมากมาย
Karussell

KD-Trees มีประสิทธิภาพมากขึ้นเมื่อค้นหาเพื่อนบ้านที่ใกล้ที่สุดหรือไม่ ทำไมคุณถึงเลือก QuadTrees เหนือ KD-Trees ฉันกำลังใช้ KD-Trees สำหรับเครื่องมือกำหนดเส้นทางของฉันในตอนนี้ ฉันเริ่มใช้ QuadTrees แต่ฉันหยุดเพราะฉันคิดว่า KD-Trees นั้นเป็นสิ่งเดียวกัน แต่ง่ายต่อการเขียนโค้ดและเร็วกว่าในการค้นหาเพื่อนบ้านที่ใกล้ที่สุด ฉันผิดหรือเปล่า?
dimitris93

เมื่อใช้ควอดทรีไม่จำเป็นต้องจัดเก็บกล่องขอบเขตอย่างชัดเจนทำให้ได้เปรียบในการจัดเก็บซึ่งเป็นสิ่งสำคัญยิ่งสำหรับ usecase ของฉัน ความเร็วการค้นหาไม่ใช่ปัญหา ในความเป็นจริงมีคนศึกษาความพยายามดังกล่าวและมีประสิทธิภาพสูงกว่าการใช้งานอื่น ๆ รวมถึง ต้นไม้ KD แต่ผมถือว่าทุกอย่างขึ้นอยู่กับการใช้งานที่เฉพาะเจาะจง ...
Karussell

หากคุณดูหน้า 9 ของไฟล์ PDF นี้จาก stanford การค้นหาเพื่อนบ้านที่ใกล้ที่สุดใน KD-Trees ไม่จำเป็นต้องให้คุณรู้ว่ามีขอบเขตอยู่ที่ใด และอีกสิ่งหนึ่งก็คือเพราะเรารู้จุดทั้งหมดไว้ก่อนเราจึงสามารถสร้างต้นไม้ที่มีความสูงของล็อกได้อย่างสมดุล คุณยังเป็นบวกหรือไม่ที่ควอดทรีมีข้อได้เปรียบเหนือต้นไม้ kd?
dimitris93

2

คุณไม่จำเป็นต้องวางขอบทั้งหมดที่อยู่ติดกันในคิวลำดับความสำคัญ "โกหก" กับอัลกอริธึมของ Dijkstra และให้เฉพาะจุดยอดที่สั้นที่สุด v, เหตุการณ์ที่เกิดขึ้นกับจุดสุดยอดพูดด้วย w แล้วดึงสแต็กออกมา จากนั้นเมื่อวีถูกดึงออกมาจากคิวคุณพูดว่า "อุ๊ปส์" ฉันทำผิดพลาดและควรให้จุดยอดนี้ด้วยเช่นกัน จะเห็นได้ง่ายว่าวิธีนี้คุณจะมีวิธีการแก้ไขที่ถูกต้องและขนาดคิวจะลดลงอย่างมากถึงจุดสุดยอดเหตุการณ์เดียวเท่านั้นแทนที่จะเป็นจำนวนมาก คุณจำเป็นต้องติดตามเหตุการณ์เพื่อให้จุดสุดยอดที่ใกล้เคียงที่สุดถัดไปเสมอเมื่อจำเป็น หนึ่งในความคิดเห็นที่อ้างว่าเครือข่ายถนนเป็นระนาบที่ไม่ถูกต้อง ในความเป็นจริงการศึกษาได้แสดงให้เห็นว่าพวกเขาไม่ใช่ภาพถ่ายสูง คิดถึงมอเตอร์เวย์ทุกแห่งที่ข้ามผ่านสะพานผ่านเมืองที่ก่อให้เกิดความไม่สงบมากมาย


0

อัลกอริทึม Dijkstras ในขณะที่ใช้งานได้ถือว่าไม่เหมาะสมสำหรับปัญหานี้แม้ว่าตัวแปรที่มีประสิทธิภาพมากขึ้นอาจถือได้ว่า "คล้ายกัน" มีการทำให้เข้าใจง่ายต่าง ๆ เครือข่ายถนนที่มีลำดับชั้นและภาพถ่าย นี่คือวิธีการพื้นฐาน พื้นที่นี้เป็นที่รู้จักกันโดยทั่วไปในชื่อ "การวางแผนเส้นทางในเครือข่ายถนน"

  • โครงสร้างกราฟสามารถ "รวบรวม" จากข้อมูลรายการ adjacency นี่เป็นแนวทางในห้องสมุดที่คุณอ้างถึง SpatiaLite โครงสร้างกราฟเหล่านี้จะถูกเก็บไว้ในรูปแบบไบนารีที่ถูกบีบอัดซึ่งตำแหน่งของกราฟจะถูกแสดงด้วยจำนวนเต็มแบบไบนารีที่เข้ารหัสเป็นต้นดังนั้นการแสดงกราฟและการจัดการจะใช้พื้นที่น้อยกว่าการจัดเก็บชื่อถนนทั้งหมด ฯลฯ ; ดูเหมือนว่าอัลกอริทึม SpatiaLite ไม่ใช่ "ออนไลน์" และทำงานในหน่วยความจำทั้งหมด

  • มีอัลกอริธึมแบบขนาน / แบบกระจาย ดูเช่นกราฟกราฟิคกราฟที่ปรับขนาดได้ / Merrill, Garland, Grimshaw

  • คำถามใช้คำศัพท์เซิร์ฟเวอร์ลูกค้าเช่น "แบบสอบถาม" อัลกอริทึมไม่ทำงานโดย "สอบถาม" ฐานข้อมูลในความรู้สึกของไคลเอ็นต์เซิร์ฟเวอร์ ภาษาคิวรีระดับที่สูงกว่าเช่น SQL เป็นอินเตอร์เฟสไปยังฐานข้อมูลและอาจใช้เพื่อส่งคำขอเพื่อคำนวณเส้นทางขั้นต่ำสุด แต่ไม่ได้ใช้โดยอัลกอริทึมภายใน โดยทั่วไปอัลกอริทึมจะทำงาน "ภายในฐานข้อมูล" เช่น "ฝั่งเซิร์ฟเวอร์" ทั้งหมด ดังนั้นการเขียนอัลกอริธึมพา ธ สั้นที่สุดในการสืบค้นฐานข้อมูลจึงเป็นไปได้สำหรับเครือข่ายขนาดเล็ก แต่ไม่ใช่ขนาดกลาง / ใหญ่

  • มีวิธีการอื่นที่การประมาณค่าในเปอร์เซนต์เล็กน้อยอาจยอมรับได้ แนวคิดพื้นฐานคือการรักษาดัชนีระยะทางระหว่างโหนด ดูเช่นการประมาณค่าที่รวดเร็วและแม่นยำของเส้นทางที่สั้นที่สุดในกราฟขนาดใหญ่ / Gubichev, Bedathur, Seufert, Weikum

  • วิทยานิพนธ์ฉบับนี้มีประโยชน์อย่างยิ่ง (235p!) การวางแผนเส้นทางในเครือข่ายถนน / Schultes

  • อัลกอริทึมบางตัวใช้แนวคิดเหล่านี้และอื่น ๆ จำนวนมากซึ่งได้รับการปรับและเป็นกรรมสิทธิ์และยืนยันความลับทางการค้าที่แข่งขันได้ เช่นของ Google อาจมีสื่อที่ทำให้เข้าใจผิดในเรื่องนี้ เช่นอัลกอริธึมที่เรียบง่ายและสง่างามที่ทำให้ Google Maps เป็นไปได้ที่การอ้างสิทธิ์ / นัย ​​Google ใช้อัลกอริทึม Dijkstras โดยไม่มีการอ้างอิงใด ๆ


1
Google Maps ได้อัปเกรดเป็นสิ่งที่ดีกว่า Dijskstra อย่างแน่นอน นักพัฒนาที่มีความสามารถครึ่งหนึ่งทุกคนจะใช้ A * สำหรับแผนที่ถนน แต่ในงานก่อนหน้านี้ของฉันเราพบว่าเครื่องยนต์ของ Google สามารถใช้เส้นทาง 2500 กม. ผ่านจุดบนเส้นทางใน <100 ms เร็วเกินไปสำหรับ A * ดังนั้นจึงเป็นไปได้ว่าพวกเขาใช้บางอย่างเช่น ArcFlags
MSalters

คำตอบของ Karussell ท้าทายประโยคเปิดนี้ "อัลกอริทึม Dijkstras ในขณะที่การใช้งานถือว่าไม่เหมาะสมสำหรับปัญหานี้" ซึ่งไม่ได้คาดหวังว่าจะมีการโต้เถียง มีการสนับสนุนที่แข็งแกร่งมากสำหรับการยืนยันใน Schultes วิทยานิพนธ์ (ต้น) ซึ่งยังครอบคลุมมาก / สำรวจล่าสุดของพื้นที่และยังอธิบายถึง "ลำดับชั้นและภาพถ่าย" ประมาณ " น่าเสียดายที่ดูเหมือนว่าจะไม่มีข้อบ่งชี้ของอัลกอริทึมของ Google จริงในวรรณคดีเปิดในการค้นหาคร่าวๆ
vzn

-2

ในชุดข้อมูลที่มีขนาดใหญ่มากเช่นนั้นเพื่อให้ได้ผลลัพธ์ที่รวดเร็วฉันพบว่ามันเป็นการดีที่สุดที่จะใช้โครงสร้างข้อมูลแบบยูเนียนค้นหาด้วยการบีบอัดพา ธ อย่างไรก็ตามหากคุณต้องการใช้อัลกอริธึมของ Djikstra และปรับให้เหมาะสมเท่านั้นมันจะแสดงข้อมูลที่แต่ละโหนดในกราฟมี คุณมักจะไม่จำเป็นต้องทำแบบสอบถาม 1,500 ทั้งหมด

ตัวอย่างเช่นพิจารณาตัวอย่างต่อไปนี้ ให้บอกว่าฉันพยายามค้นหาองศาของการแยกระหว่างนักแสดง 2 คน (หมายเลขเบคอน) และฉันต้องการค้นหาเส้นทางที่มีน้ำหนักน้อยที่สุด (เส้นทางที่ใช้ภาพยนตร์ใหม่ล่าสุดที่เป็นไปได้) shortestPath(actor A, actor B);ตอนนี้ขอบอกว่าผมมีฟังก์ชั่นที่เรียกว่า พิจารณาสถานการณ์สมมติต่อไปนี้

หากนักแสดง A ได้รับการแสดงตั้งแต่ปี 1970 และนักแสดง B ได้รับการแสดงตั้งแต่ปี 2000 จากนั้นได้รับข้อมูลนั้นมันจะมีเหตุผลมากขึ้นกว่าที่จะหาเส้นทางที่เริ่มต้นจากภาพยนตร์เรื่องแรกของนักแสดง B แล้วผ่านทางของคุณไป ตรงข้ามกับการแสดงซ้ำในภาพยนตร์ทุกเรื่องที่นักแสดง A ได้แสดง

ดังนั้นประเด็นหลักคือการเพิ่มประสิทธิภาพของอัลกอริทึมของ Djikstra ขึ้นอยู่กับว่าชุดข้อมูลของคุณคืออะไร คุณจะต้องให้ข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่ชุดข้อมูลของคุณสร้างไว้ให้เราเพื่อช่วยคุณปรับแต่งอัลกอริทึมของคุณ

แก้ไข:สมมติว่าคุณกำลังพยายามหาเส้นทางที่สั้นที่สุดระหว่าง 2 เมืองในประเทศเดียวกันและหากประเทศนี้มีความยาวมากกว่าที่กว้างกว่าเช่นอาร์เจนตินาคุณสามารถทำการค้นหาตามลองจิจูดและละติจูดของประเทศ ขอบเขต จากนั้นคุณสามารถเริ่มต้นการสำรวจในแนวตั้ง (โดยใช้ลองจิจูด) เมื่อเทียบกับแนวนอน แน่นอน, จะต้องมีการจัดการข้อยกเว้น, แต่คุณได้รับความคิดทั่วไป


1
คุณใช้ Union-Find ใน Dijkstra ได้อย่างไร
Raphael

ข้อมูลเป็นข้อมูลเชิงพื้นที่ละติจูดและลองจิจูด ฉันคิดว่าชัดเจน
dimitris93
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.