- PVSM.RU - https://www.pvsm.ru -
При поиске кратчайшего пути на графах большого размера плохо работает традиционная оценка стоимости т.к. данные заведомо не помещаются в памяти и общая стоимость больше зависит от числа обращений к диску нежели от числа просмотренных рёбер. А число дисковых операций — весьма субъективный фактор, зависимый от сложно формализуемой пригодности графа к хранению на диске в форме удобной для конкретного алгоритма. Кроме того, очень важным становится компактность — количество информации в расчете на ребро и вершину.
Под катом представлена обобщенная эвристика к алгоритму A*, полезная именно в свете практической пригодности на больших графах при ограниченных ресурсах, например, на мобилке.
Итак, наша задача — построение кратчайшего пути по графу из точки в точку. При этом граф достаточно велик, чтобы мы не имели возможности держать его целиком в памяти, а также невозможен предрасчет по сколь-нибудь значительному количеству вершин. Отличный образец — дорожный граф OSM. На данный момент число вершин в OSM [1] превысило 4.6 млрд, общее число объектов — 400 млн.
Понятно, что в таких условиях поиск более-менее протяженного маршрута чистым алгоритмом Дейкстры [2] или Левита [3] невозможен в силу того, что мы не располагаем количеством памяти, необходимым для хранения промежуточных данных.
Как поступает алгоритм Дейкстры?
В результате для разреженных (например, геометрических) графов получаем стоимость O(n*log(n) + m*log(n)), где n-число просмотренных вершин, m-число просмотренных ребер.
Фиг.1 Здесь мы видим найденный маршрут и просмотренные при этом ребра.
Проблема в том, что алгоритм Дейкстры не использует никакой информации о свойствах графа и искомого маршрута и при его работе (распространении т.н. «волны») периметр этой «волны» движется от искомой точки во всех направлениях без какой-либо дискриминации.
С другой стороны, на геометрических графах, например, развитой дорожной сети, есть смысл стимулировать распространение «волны» по направлению к цели и штрафовать за остальные направления. Эта идея реализована в алгоритме A* [4], который является обобщением алгоритма Дейкстры.
В A* стоимость вершины при помещении её в приоритетную очередь не просто равна пройденному пути, а включает еще и оценку пути оставшегося. Как нам получить эту оценку?
Стоит отметить, что это должны быть достаточно вычислительно-дешевая оценка т.к. выполняется она большое число раз. Первое что приходит в голову — вычислить геометрическое расстояние от текущей точки до финиша и исходить из этого, например: осталось 10 км — средняя скорость при движении по городу 20 км/ч, значит наша оценка — полчаса.
При этом, если ребро ведет нас по направлению к финишу, оценка для него будет уменьшаться и компенсировать пройденный путь.
Для ребер, ведущих от цели, эта оценка станет расти, в результате такие точки попадут в очередь с большим весом и вполне вероятно, что до них дело так и не дойдёт.
Примерно такого же эффекта можно достичь, кстати, с помощью техники Beam Search, где принудительно ограничивается размер приоритетной очереди и «недостойные» с точки зрения эвристики кандидаты просто отбрасываются.
Фиг.2 Здесь мы видим поиск того же маршрута с использованием описанной эвристики, почувствуйте разницу.
A* превращается в алгоритм Дейкстры если оценка стоимости возвращает 0, как если бы мы считали, что остаток пути промчимся с бесконечной скоростью.
A* относится т.н. информированным алгоритмам [5] т.к. в эвристике мы используем предположение, что движение в направлении цели скорее приведёт нас к успеху.
Каковы должны быть свойства функции оценки? Она должна быть правдоподобной. Как мы уже выяснили, слишком оптимистичная оценка сводит на нет наши попытки уменьшить просматриваемую часть графа. С другой стороны, слишком пессимистичная оценка заставит алгоритм построить путь строго по направлению, невзирая ни на что. Вряд ли это нас устроит.
Реалистичная оценка должна опираться на свойства графа а лучше на модель данных. Например, вычисляться из уровня загруженности дорог в это время суток и уровня транспортной связности графа. Например, в городе без рек хорошо работает Манхэттенское расстояние [6].
Но тут сразу возникает масса нюансов:
Можно использовать и разные эвристики в духе метода ветвей и границ [7]:
Есть еще одна проблема с оценкой стоимости, о которой нельзя не упомянуть.
В жизни геометрически близкие объекты могут быть достаточно удаленными с точки зрения дорожного графа. Например, находиться на разных сторонах реки, горной гряды, моря… В таком случае оценка, основанная на геометрической близости начнёт усугублять ситуацию, упорно направляя «волну» в неправильном направлении.
Фиг.3 Вот так выглядит просмотренная A* часть графа OSM для поиска пути из Италии в Албанию.
Впрочем, это всё равно лучше чем алгоритмом Дейкстры. Хорошо видно как заполнив всю Италию, «волна» начала переливаться через край, набрала скорость и быстро достигла цели.
Фиг.4 А вот так выглядит просмотренная часть графа для алгоритма Дейкстры. По сравнению с ней всё не так уж и мрачно.
А можно ли еще как-то улучшить алгоритм, что по этому поводу говорит Сomputer Sience?
Двунаправленный поиск
Можно пустить две A* волны навстречу друг другу. Это называется bidirectional search [8] и на первый взгляд кажется очень привлекательной идеей. В самом деле, при хорошей транспортной связности “волна” представляет собой эллипсоид, две малых волны, пущенные навстречу, заметут меньшую площадь по сравнению с одной большой. С другой стороны, возникает проблема обнаружения встречи «волн», точек в их периметрах может быть довольно много и проверять на каждом шагу наличие ребра в чужом периметре не так уж и дешево.
Фиг.5 встречные волны Дейкстры
Возможно, с этим можно было бы и смириться при реальном выигрыше в объеме просмотренной части графа. Но вот если мы рассмотрим вышеописанный пример поиска проезда из Италии в Албанию, то обнаружим, что двунаправленный поиск нам ничем не поможет, а только усугубит ситуацию т.к. кроме заливки всей Италии мы вынуждены будем просмотреть и всю Грецию с половиной Балкан, прежде чем волны встретятся. Ибо вместо одной «волны», упёршейся в препятствие, будем иметь две таковых.
Использование иерархии дорог
Некоторые коммерческие системы, например StreetMap USA [9], используют для роутинга тот факт, что хорошо спланированная дорожная сеть имеет двухуровневую природу — есть сеть местных дорог и (значительно меньшая) сеть шоссе для поездок на дальние расстояния. Представляется естественным использовать этот факт. Вводятся шлюзы (transit nodes) — вершины, на которых происходит переход из одного уровня в другой. Нахождение “достаточно длинного” пути сводится к нахождению путей от:
Фиг.6 Кусочек StreetMap
Выгоды такого подхода очевидны. Минусы таковы:
Построение иерархии графа
Если нет возможности и/или желания выверять граф, остаётся возможность построить иерархию автоматически.
Так или иначе, эксплуатируется идея, что хоть граф и не выверен, тем не менее, атрибуты рёбер позволяют строить маршруты приемлемого качества. Но в силу размеров графа, построение тем же A* в рабочем режиме непозволительно дорого.
Например, это может выглядеть так:
Построенный граф может быть снова подвержен описанной процедуре, таким образом строится необходимое число иерархий.
Маршрутизация в таком иерархическом графе осуществляется двунаправленным поиском (A* или алгоритмом Дейкстры).
Сепараторы
Основной идеей метода является попытка разделения графа на компоненты путём удаления небольшой части ребер — сепараторов. Эти сепараторы и предварительно вычисленные пути между ними образуют следующую иерархию. Утверждается [1], что затратив O(n*log(n)**3) времени и пространства на диске для предварительного расчета, можно выполнять запросы за O(sqrt(n)*log(n))
Grid Based Transit Nodes
Это в общем та же идея с сепараторами, но в целях масштабирования и простоты граф делится на фрагменты решеткой или квадро-деревом, ребра, которые пересекают границы фрагментов становятся транзитными. Понятно, что цена этому — эффективность. В плюсах — высокая автоматизация и как следствие отсутствие человеческого фактора.
Таблицы расстояний
На вышестоящих уровнях иерархии в процессе поиска пути не ищутся, а стоимость подсчитывается на основе пред-вычисленных таблиц расстояний между транзитными нодами. Когда маршрут определен, пути восстанавливаются локальным поиском.
Фиг.7 [1]
Reach [3]
Идея метода такова — замечено, что при построении длинных оптимальных маршрутов, «локальные» рёбра посещаются только в самом начале или конце маршрута. Следовательно, построив некоторое количество «обучающих» длинных маршрутов, можно понять, насколько близко расположено то или иное ребро к любому из концов маршрута.
Для некоторого обучающего маршрута P(s…..u.v…...t) вводится показатель reach — минимальное расстояние до концов reach(uv) = min(dist(s…..u), dist(v…..t)).
На всём обучающем множестве reach(uv) — максимальное значение на всех маршрутах, где встретилось ребро (uv).
При «боевом» поиске мы вдали от старта и финиша просто будем стараться избегать рёбер с маленьким значением reach.
Фиг.8 [21]
Идея метода очень красивая, вопросы вызывает лишь качество обучающей выборки, её достаточность и ресурсы, потраченные на обучение.
Arc-Flags [4]
Граф делится на фрагменты. Проводится обучение построением кратчайших маршрутов между предопределенными точками. При построении обучающего пути, для каждого ребра сохраняется факт, что через него проходит кратчайший маршрут в клетку финальной точки.
Таким образом для каждого ребра мы храним маску флагов, в какие фрагменты графа можно через это ребро добраться кратчайшим путём.
Специфические недостатки этого метода видны невооруженным взглядом:
ALT [5]
Из всех вершин выбирается небольшое количество landmarks: λ. В изначальном варианте для каждой вершины предварительно рассчитывались стоимости до каждого λ. Это требовало колоссального количества дополнительной памяти и в дальнейшем требования смягчились и вершины стали группировать.
Поиск в ALT осуществляется как в A*, но оценка оставшегося пути делается на основе рассчитанных стоимостей. Пусть мы рассматриваем ребро (u,v) на пути к целевой вершине t. Для каждой λ в соответствии с неравенством треугольника [10] мы имеем оценку оставшейся части пути (через λ): dist(λ, t) − dist(λ, v) ≤ dist(v, t) и dist(v, λ) − dist(t, λ) ≤ dist(v, t). Минимум для всех λ и даст искомую оценку.
Фиг.9
Мы видим два основных направления, в которых идёт развитие:
Кроме того, на аморфных графах попытка построить иерархию может лишь привести к проблемам. Представим себе граф в виде прямоугольной решетки из равнозначных дорог. При движении в некотором направлении правильным решением будет поворачивать в случайном направлении с вероятностью, связанной с направлением. Т.е. если азимут к цели составляет 45°, стоит с равной вероятностью поворачивать направо и налево, чтобы не создавать пробок.
Попытка же построить на такой сетке иерархию приведет к тому, что дорожная сеть станет использоваться неэффективно.
Кроме того, требуется (нелинейное от размера графа) количество дополнительной памяти.
Вот «если бы губы Никанора Ивановича да приставить к носу Ивана Кузьмича, да взять сколь-нибудь развязности, какая у Балтазара Балтазаровича, да, пожалуй…» ©
Справедливости ради стоит сказать, что таких попыток немало, некоторые из них можно найти в списке источников данной статьи. Но мы, конечно же, не изменим себе и придумаем свой собственный, «не имеющий аналогов» метод.
Поставим задачу разработать простую и дешевую (и вычислительно и с точки зрения дополнительно хранимой информации) эвристику оценки стоимости пути из одной точки в другую на основе их географических координат. Прямое расстояние не подходит, оно может ошибаться весьма сильно, достаточно посмотреть на Гибралтар и Танжер.
Идея восходит к этой [11] работе.
Фиг.10 — число дорог на квадратный градус в логарифмической шкале
Фиг.11 Оценка стоимости проезда из Нск, чем ближе к оранжевому, тем длинней путь.
Итак, для поиска:
Но ведь градус — это довольно грубая сетка, некоторые проливы могут слипнуться, например, «маленький остров» с Нормандией.
Не беда, в OSM есть тип — береговая линия. Мы растеризуем береговые линии и разрешим ходить из клетки, помеченной как прибрежная, только на «материковые» клетки.
Фиг.12 Береговая линия OSM
Но тут выясняется, что:
Ок, придется руками нарисовать разделительные линии в важных проливах, растеризовать их и запрещать пересекать при распространении волны.
Благо, это одноразовая работа, а таких проливов не очень много.
Вот, например, распространение «волны» из Италии, обратим внимание на Гибралтарский пролив.
Фиг.13 Оценка стоимости проезда в Италию, чем ближе к оранжевому, тем длиннее путь.
В целом схема приемлема, но:
Возможно, здесь хорошо сработает вариант, когда каждая «прибрежная» клетка представлена квадро-деревом, распространение волны следует проводить и по элементам квадродерева.
Но всё же чувствуется во всём этом какая-то натяжка, поэтому в дело вступает План Б.
Фиг.14 Путь, проложенный по верхнеуровневому графу.
Фиг. 11 Хорошо видно, как волна начинает расползаться вширь, когда опорный путь резко меняет направление. Тем не менее, общий объем прочитанных данных весьма невелик. Наблюдается также ускорение в ~20 раз.
Выводы
Итак, на суд читателя представлены два варианта эвристики подсчета стоимости остатка пути для A*.
Для обоих вариантов:
Как бы то ни было, это еще один инструмент для работы с графами, весьма полезный в условиях ограниченных ресурсов и/или неограниченных данных. В частности, никто не запрещает использовать эту же технику для двустороннего поиска.
[8] Partitioning Graphs to Speedup Dijkstra’s Algorithm
ROLF H. MOHRING and HEIKO SCHILLING
[9] SHARC: Fast and Robust Unidirectional Routing
Reinhard Bauer Daniel Delling
[10] Cambridge Vehicle Information Technology Ltd. Choice Routing [14]
[12] Fast and Exact Shortest Path Queries Using Highway Hierarchies
Dominik Schultes
[13] Engineering Highway Hierarchies
Peter Sanders and Dominik Schultes
[15] Dynamic Highway-Node Routing
Dominik Schultes and Peter Sanders
[17] Multilevel Algorithms for Partitioning Power-Law Graphs
Amine Abou-rjeili and George Karypis
[18] Impact of Shortcuts on Speedup Techniques?
Reinhard Bauer, Daniel Delling, and Dorothea Wagner
[19] Transit Node Routing based on Highway Hierarchies
Peter Sanders Dominik Schultes
[21] Reach for A∗: an Efficient Point-to-Point Shortest Path Algorithm Andrew V. Goldberg [15]
Автор: 2ГИС
Источник [16]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/algoritmy/252885
Ссылки в тексте:
[1] OSM: https://ru.wikipedia.org/wiki/OpenStreetMap
[2] алгоритмом Дейкстры: https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B
[3] Левита: https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0
[4] A*: https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0_A*
[5] информированным алгоритмам: https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0
[6] Манхэттенское расстояние: https://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D1%81%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D0%B5_%D0%B3%D0%BE%D1%80%D0%BE%D0%B4%D1%81%D0%BA%D0%B8%D1%85_%D0%BA%D0%B2%D0%B0%D1%80%D1%82%D0%B0%D0%BB%D0%BE%D0%B2
[7] метода ветвей и границ: https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%B2%D0%B5%D1%82%D0%B2%D0%B5%D0%B9_%D0%B8_%D0%B3%D1%80%D0%B0%D0%BD%D0%B8%D1%86
[8] bidirectional search: https://en.wikipedia.org/wiki/Bidirectional_search
[9] StreetMap USA: http://www.esri.com/data/streetmap
[10] неравенством треугольника: https://ru.wikipedia.org/wiki/%D0%9D%D0%B5%D1%80%D0%B0%D0%B2%D0%B5%D0%BD%D1%81%D1%82%D0%B2%D0%BE_%D1%82%D1%80%D0%B5%D1%83%D0%B3%D0%BE%D0%BB%D1%8C%D0%BD%D0%B8%D0%BA%D0%B0
[11] этой: https://habrahabr.ru/company/2gis/blog/266753/
[12] R. J. Gutman. Reach-Based Routing: A New Approach to Shortest Path Algorithms Optimized for Road Networks. In Proceedings of the 6th Workshop on Algorithm Engineering, 2004: https://www.researchgate.net/publication/220982082_Reach-Based_Routing_A_New_Approach_to_Shortest_Path_Algorithms_Optimized_for_Road_Networks
[13] Goldberg, A.V., Werneck, R.F.: Computing Point-to-Point Shortest Paths from External Memory. In: Proceedings of the 7th Workshop on Algorithm Engineering and Experiments (ALENEX 2005), pp. 26–40. SIAM (2005): http://www.siam.org/meetings/alenex05/papers/03agoldberg.pdf
[14] Cambridge Vehicle Information Technology Ltd. Choice Routing: http://camvit.com/camvit-technical-english/Camvit-Choice-Routing-Explanation-english.pdf
[15] Reach for A∗: an Efficient Point-to-Point Shortest Path Algorithm Andrew V. Goldberg: http://www.cs.princeton.edu/courses/archive/spr09/cos423/Lectures/reach-mit.pdf
[16] Источник: https://habrahabr.ru/post/326638/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.