Алгоритм Дейкстри на величезних графіках


15

Я дуже добре знайомий з Дайкстра і у мене є конкретне питання щодо алгоритму. Якщо у мене є величезний графік, наприклад 3,5 млрд. Вузлів (усі дані OpenStreetMap), я, очевидно, не міг би мати графік у пам'яті, тому графік зберігається на диску в базі даних.

Існують бібліотеки для обчислення найкоротших шляхів на таких графіках. Як вони це роблять? Більш конкретно, як вони завантажують необхідну частину графіка для запуску алгоритму Дейкстри?

Для отримання списку суміжності кожної вершини, що відвідується, за моїми статистичними даними потрібно приблизно 1500 запитів до бази даних на 10000 вузлів, так що явно не так, як вони це роблять. Це було б надто повільно.

Як вони це роблять? Я намагаюся реалізувати це самостійно.


2
Ви впевнені, що використовують Dijkstra? Існує безліч інших алгоритмів найкоротшого шляху, які можуть краще відповідати описуваній ситуації.
Девід Річербі

1
Ви заглянули в код? Як ми маємо знати? "запити до бази даних" - сподіваюся, ви не використовуєте СУБД для зберігання графіків?
Рафаель

@DavidRicherby так, я впевнений, дивіться на це посилання
dimitris93

2
"[Я] не був би вкрай стомлюючим процесом вивчити чистий код C." Але це єдиний спосіб дізнатися, що робить код. Отже, ви просто просите нас виконати ваше копітке завдання, яке не є найбільшою рекламою для вашого питання ...
Девід Річербі,

1
@Shiro Ви явно запитуєте: "Як вони це роблять?" Якщо це насправді не питання, яке ви хочете задати, вам потрібно перефразувати.
Рафаель

Відповіді:


6

Існують бібліотеки для обчислення найкоротших шляхів на таких графіках. Як вони це роблять? Більш конкретно, як вони завантажують необхідну частину графіка для запуску алгоритму Дейкстри?

Ви можете використовувати БД, спеціальний формат файлу для читання з диска та налаштування в пам'яті.

Але, з мого досвіду використання БД, це приблизно в 5-10 разів повільніше і набагато більш інтенсивно в пам'яті, ніж написання власного формату файлів на основі "простого" зв'язаного формату списку.

Хороша річ, що є декілька програмних систем, що використовують OSM, які є відкритим кодом, так що ви можете заглянути прямо в код, наприклад, дивіться тут . У двигуні маршрутизації з відкритим кодом GraphHopper дуже легко переключитися з налаштування на карту пам'яті (на основі диска) на налаштування в пам'яті - обидва використовуючи однаковий формат. Налаштування "mmap" навіть дозволяє використовувати мобільні пристрої з обмеженою пам'яттю, і останні працюють набагато швидше, якщо у вас є необхідна оперативна пам'ять, наприклад, на сервері. Наприклад, для всесвітнього графіка (> 100 мільйонів вузлів) тоді вам потрібно близько 8-10 ГБ оперативної пам’яті, а також багато більше оперативної пам’яті, якщо ви хочете прискорити все далі, наприклад, за допомогою Ієрархій скорочень - приблизно на 5-8 Гбіт більше на кожен автомобіль, який ви хочете.

Формат дуже спрощений і в основному зберігає лише потрібні вам дані за допомогою декількох хитрощів, щоб зробити його компактним. Детальніше про це читайте тут . Відмова: Я автор GraphHopper.

Щодо інших відповідей:

Прийнятний алгоритм Dijkstras вважається не оптимальним для цієї проблеми

"Нормальна" Dijkstra може виконувати дуже розумно (<1 для запитів по всій країні, як, наприклад, ваші 3mio вузли) і є оптимальною в "теоретичному сенсі", але потребує трохи налаштування, щоб швидко досягти виробничих сценаріїв. І такі прийоми, як ієрархії скорочень, використовують двосторонню модифікацію цього і дуже добре працюють.

дорожні мережі є ієрархічними та планарними.

дорожні мережі є ієрархічними лише для автомобілів, а не планарними (мости, тунелі, ...)


У мене є ще одне питання. Як знайти NodeIDнайближчий вузол від latitude/longitude? Це потрібно для обчислення найкоротшого шляху A-> B. А також потрібно пам’ятати, що А і В можуть не існувати як вузли, оскільки не кожен квадратний метр містить вузол. Тому нам потрібно знайти 2 найближчих NodeID з A і B.
dimitris93

Це робиться в LocationIndexTree, який є своєрідним квадратом, що ефективно зберігає NodeID в комірці, яка має, наприклад, для GraphHopper радіус ~ 500м. Якщо нічого не знайдено, воно розширює радіус до певної міри. Теоретично це звучить просто, але дуже складне, оскільки у вас можуть бути краї, що перетинають область, вам потрібно бути ефективним при створенні та запитуванні до нього та багато іншого.
Каруссел

Хіба KD-Дерева не ефективніші під час пошуку найближчого сусіда? Чому ви вибрали QuadTrees через KD-Дерева? Я зараз впроваджую KD-Дерева для свого двигуна маршрутизації. Я почав впроваджувати QuadTrees, але зупинився, бо зрозумів, що KD-Trees - це те саме, але простіше кодувати та швидше запитувати найближчого сусіда. Я помиляюся ?
dimitris93

При використанні чотиривіршів немає необхідності чітко зберігати обмежувальний ящик, надаючи йому перевагу зберігання, що було більш критичним для мого використання (також мені здається, що квадри є легше;)). Швидкість запиту - це не проблема. Насправді хтось вивчав такі спроби, і це перевершувало будь-які інші реалізації, в т.ч. KD дерева, але я припускаю, що все залежить від конкретної реалізації ...
Karussell

Якщо ви подивитесь на сторінку 9 цього PDF у Станфорді, пошук найближчого сусіда в KD-Trees зовсім не вимагає, щоб ви знали обмежувальні поля. І ще одна річ у тому, що, оскільки ми заздалегідь знаємо всі моменти, ми можемо створити збалансоване дерево висоти входу. Ви все ще впевнені в тому, що квадрати мають якусь перевагу перед kd-деревами?
dimitris93

2

Не потрібно ставити всі ребра, які є сусідніми, у черзі пріоритетів. "Ляжте" на алгоритм Дейкстри і надайте йому лише найкоротшу вершину, v, що трапляється на вершину, скажімо, w, витягнув стек. Потім, коли v витягується з черги, ти кажеш "ой", я допустив помилку, і я мав би дати вам і цю вершину, яка наступна найближча до вершини w. Зрозуміло, що таким чином ви отримаєте правильне рішення, і розмір черги різко зменшиться до однієї вершини інциденту лише замість багатьох. Вам потрібно хоч слідкувати за випадками, щоб завжди наводити наступну найближчу вершину - коли потрібно. Один із зауважень, які стверджують, що дорожні мережі є планарними, що є неправильним. Фактично, дослідження показало, що вони є дуже непланарними. Подумайте про всі автостради, що перетинають мости через місто, що викликає багато непланарностей.


0

Прийнятний алгоритм Dijkstras вважається не оптимальним для цієї проблеми, хоча ефективніші варіанти можна вважати "подібними". є різні спрощення. дорожні мережі є ієрархічними та планарними . ось основні підходи. ця територія загалом відома як "планування маршруту в дорожніх мережах".

  • структуру графіків можна "скласти" з даних списку суміжності. це підхід у бібліотеці, яку ви цитуєте , SpatiaLite. ці структури графіків зберігаються у стисненому двійковому форматі, де розташування графіків представлені цілими числами, кодованими двійковим кодом тощо, тому представлення та маніпуляція графіком займає набагато менше місця, ніж зберігання всіх назв доріг тощо; виявляється, що алгоритм SpatiaLite не є "он-лайн" і працює повністю в пам'яті.

  • існують паралельні / розподілені алгоритми. див., наприклад, Масштабована обробка графічного графічного процесора / Merrill, Garland, Grimshaw.

  • у питанні використовується термінологія клієнт-сервер, тобто "запити". алгоритми не виконуються шляхом "запиту" на базу даних у сенсі клієнт-сервер. Мови запитів вищого рівня, такі як SQL, є інтерфейсом до бази даних і можуть використовуватися для передачі запиту для обчислення мінімальних маршрутів, але не використовуються алгоритмом внутрішньо. як правило, алгоритм працює "всередині бази даних", тобто повністю "на стороні сервера". Таким чином, написання алгоритму найкоротшого шляху у запитах до бази даних можливо для малих мереж, але не середніх / великих масштабів.

  • існує інший підхід, коли оцінки в межах невеликих відсотків можуть бути прийнятними. основна ідея - зберігати індекс відстаней між вузлами. див., наприклад, Швидка та точна оцінка найкоротших шляхів у великих графах / Губічев, Бедатур, Сеферт, Вейкум

  • ця (235p!) кандидатська дисертація особливо застосовна. Планування маршруту в дорожніх мережах / Шультес

  • деякі алгоритми використовують багато з цих ідей, а інші - високо налагоджені та захищені на основі конкурентних комерційних таємниць. наприклад, Google. з цього приводу можуть бути деякі оманливі ЗМІ. напр . простий, елегантний алгоритм, який робить Карти Google можливими, що заявляє / передбачає, що Google використовує алгоритм Dijkstras без жодного цитування.


1
Карти Google, безумовно, оновили щось краще, ніж Dijskstra. Кожен на півдорозі грамотний розробник використовував би A * для дорожніх карт, але на попередній роботі ми з’ясували, що двигун Google може пересаджувати 2500 км маршрутів через точку руху в <100 мс. Це занадто швидко для A *, тому, ймовірно, вони використовують щось на зразок ArcFlags.
MSalters

Відповідь Карусселя кидає виклик цьому вступному реченню "Алгоритм Дейкстраса при застосуванні вважається не оптимальним для цієї проблеми", який, напевно, не був би суперечливим. є дуже сильна підтримка твердження в тезі Шультеса (на початку), що також є дуже всеосяжним / останнім оглядом місцевості, а також пояснює "ієрархічне та планарне" "наближення". на жаль, схоже, немає жодної вказівки на фактичні алгоритми google у відкритій літературі про побіжний пошук.
vzn

-2

У надзвичайно великих наборах даних, таких як, щоб отримати такі швидкі результати, я вважаю, що найкраще використовувати структуру даних об'єднання-пошуку з стисненням шляху. Однак якщо ви хочете використовувати лише алгоритм Джикстра і оптимізувати це, то зводиться до того, яку інформацію має кожен вузол у графі. Вам, швидше за все, не потрібно робити всі 1500 запитів.

Наприклад, розглянемо наступний приклад. Скажімо, я намагаюся знайти ступінь розлуки між будь-якими двома акторами (число Бекона), і я хочу знайти найменш зважений шлях (шлях, використовуючи новітні фільми, можливі). Скажімо, у мене функція називається shortestPath(actor A, actor B);. Розглянемо наступний сценарій.

Якщо Актор Актер виступає з 1970 року, а Актор Б виступає з 2000 року, то, враховуючи цю інформацію, було б набагато логічніше знайти шлях, починаючи з першого фільму про Актора В, а потім пройти шлях до Актора А. на противагу ітерації через кожен фільм, в якому виступав Актор А.

Таким чином, головний момент полягає в тому, що оптимізація алгоритму Джикстри дійсно залежить від того, яким є ваш набір даних. Вам потрібно буде надати більше інформації про те, що пов'язаний з вашим набором даних, щоб допомогти вам оптимізувати ваш алгоритм.

EDIT: Скажімо, ви намагаєтеся знайти найкоротший шлях між двома містами в одній країні, і якщо ця країна довша, ніж вона ширша, наприклад, Аргентина, то ви можете робити запити на основі довготи та широти країн межі. Потім ви можете почати переходити вертикально (використовуючи довготу) на відміну від горизонталі. Звичайно, потрібно було б обробляти винятки, але ви отримуєте загальне уявлення.


1
Як ви використовуєте Union-Find в Dijkstra?
Рафаель

Дані - це просторові дані, широта та довгота. Я думав, що це було зрозуміло.
dimitris93
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.