Изменения
Нет описания правки
Алгоритмический принцип K* следующий. Будем запускать алгоритмы Дейкстры и A* на G с чередованием. Сначала, мы запустим A* на G пока вершина t не будет выбрана из очереди для рассмотрения. Затем, вы запустим алгоритмы Дейкстры на доступной части P(G). Каждый узел рассмотрел Дейкстрой представляет путь решения. Если точнее, то путь \sigma в P(G), по которому Дейкстра достигла этого узла является решением. Путь s-t может быть построен из \sigma за линейное время путем вычисления последовательности запасных ребер seq(\sigma) и затем s-t пути из неё. Если Дейкстра находит k кратчайших путей, то K* завершается успешно. Иначе, A* возобновляется для исследования большей части G. Это приводит к росту P(G), на котором алгоритм Дейкстры затем будет возобновлен. Мы будем повторять этот процесс до тех пор, пока алгоритм Дейкстры не найдет k кратчайших путей.
Алгоритм 1 содержит псевдокод K*. Код с 8 по 25 строчку образует главный цикл K*. Цикл завершается, когда очереди обоих алгоритмов А* и Дейкстры пусты. До 8 строчки выполняет некоторые подготовительные вещи. После инициализации, А* запускает на 5 строчке пока вершина t не будет выбрана им для рассмотрения, в этом случае кратчайший путь s-t будет найден. Если t не достигнута, то алгоритм завершается без решения. Отметим, что он не завершится на бесконечных графах. Иначе, алгоритм добавляет специальную вершину R, которая назначена корнем P(G), в поисковую очередь алгоритма Дейкстры. Затем, K* входит в главный цикл.
K* поддерживает механизм планирования для контролирования, когда A* или Дейкстра будет возобновлены. Если очередь из A* не пуста, что означает, что А* ещё не завершил исследования всего графа G, то Дейкстра возобновляется тогда и только тогда, когда g(t) + d <= f(u). Значение d является максимальным d-значением среди всех successor-ов головы поисковой очереди n алгоритма Дейкстры. Вершина u является головой поисковой очереди A*. Напомним, что d - функция расстояния, используемая в алгоритме Дейкстры.Если очередь поиска Дейкстры пуста или g(t) + d > f(u), то А* возобновляется для того, чтобы исследовать более большую часть графа G (строка 14). То, как долго мы ему позволим работать, является компромиссом. Если мы запустим его только на маленьком количестве шагов, то мы дадим Дейкстре шанс найти необходимое количество путей скорее, чем они будут доступны в P(G). С другой стороны, мы вызываем накладные расходы путем переключения A* и Дейкстры и поэтому должны ограничить количество переключений. Эти накладные расходы вызваны тем фактом, что после возобновления A* (строка 14), структура графа P(G) может измениться. Следовательно нам необходимо обновить P(G) (строка 15), как мы будет широко обсуждать в разделе 4.5. Это требует последующую проверку статуса Дейкстры. Мы должны быть уверены, что Дейкстра поддерживает согласованное состояние после изменений в P(G). K* предусматривает условие, которые управляет решением, когда остановить A*, которое мы назовем ''условие расширения''. Для того, чтобы поддерживать аналогичную асимптотическую сложность как у EA и LVEA, мы должны определить условие расширения так, чтобы A* выполнялся пока количество рассмотренных вершин и количество внутренних ребер удваивается или G полностью исследован. Мы обсудим эту проблему несколько подробнее позже. В качестве полезного свойства, K* позволяет другое определения этого условия, которое может быть более эффективным на практике. В наших экспериментах в разделе 6, мы определили условие расширения так, что количество рассмотренных вершин или количество рассмотренных ребер ребер возрастает на 20% при каждом запуске A*. Этот механизм планирования включен до тех пор, пока A* не закончит исследовать весь граф G. Как только A* исследует весь граф G (строка 9), механизм планирования отключается и в дальнейшем работает только алгоритм Дейкстры.Строки 18-22 представляют обычный шаг рассмотрения узла алгоритмом Дейкстры. Отметим, что когда successor-узел n' сгенерирован, K* не проверяет был ли n' уже посещен до этого. Другими словами, каждый раз, когда узел генерируется, он рассматривает как новый. Эта стратегия обоснована на наблюдении, что путь s-t может содержать одно и то же ребро несколько раз. Строка 24 добавляет следующий путь s-t в результирующее множество R. Это делается путем конструирования последовательности запасных ребер seq(\sigma) из пути \sigma, через которые Дейкстра достигла узла n, который был только что рассмотрен. Алгоритм завершается, когда в результирующее множество добавлено k последовательностей запасных ребер (строка 25). 4.5 Взаимосвязь алгоритмов Дейкстры и A*