Алгоритм D* — различия между версиями
Kabanov (обсуждение | вклад) |
Kabanov (обсуждение | вклад) м (→Ссылки) |
||
| Строка 148: | Строка 148: | ||
* [http://en.wikipedia.org/wiki/D* Wikipedia:D*] | * [http://en.wikipedia.org/wiki/D* Wikipedia:D*] | ||
* [http://idm-lab.org/project-a.html Sven Koenig` web page] | * [http://idm-lab.org/project-a.html Sven Koenig` web page] | ||
| + | * [http://pub1.willowgarage.com/~konolige/cs225b/dlite_tro05.pdf] | ||
[[Категория: Алгоритмы и структуры данных]] | [[Категория: Алгоритмы и структуры данных]] | ||
[[Категория: Кратчайшие пути в графах ]] | [[Категория: Кратчайшие пути в графах ]] | ||
Версия 23:49, 2 января 2014
Алгоритм D* — алгоритм поиска кратчайшего пути во взвешенном ориентированном графе, где структура графа неизвестна заранее или постоянно подвергается изменению. Разработан Свеном Кёнигом и Максимом Лихачевым в 2002 году.
Содержание
Алгоритм LPA*
Постановка задачи
Дан взвешенный ориентированный граф . Даны вершины и . Требуется после каждого изменения графа уметь вычислять функцию для каждой известной вершины
Описание
Обозначим множество как множество вершин, исходящих из вершины .
Аналогично множество как множество вершин, входящих в вершину .
Функция будет возвращать стоимость перехода из вершины в вершину . При этом .
Функция будет возвращать последнее известное (и самое минимальное) значение расстояния от вершины до .
Если
Иначе
Вершина может быть 3-х видов:
- насыщена, если
- переполнена, если
- ненасыщена, если
Очевидно, что если все вершины насыщены, то мы можем найти расстояние от стартовой вершины до любой.
Функция , где - вершина, возвращает вектор из 2-ух значений , . .
Если в конце поиска пути , то мы не смогли найти путь от до на текущей итерации. Но после следующего изменения графа путь вполне может найтись.
Псевдокод
Основная функция, описывающая алгоритм
Main():
{
Initialize();
while (true)
{
ComputeShortestPath();
В данный момент мы знаем кратчайший путь из в .
Ждем каких-либо изменений графа.
for всех ориентированных ребер с измененными весами:
{
Обновляем результат функции ;
UpdateVertex();
}
}
}
Теперь опишем составные элементы подробнее
Initialize():
{
//Заведем приоритетную очередь , в которую будем помещать вершины. Сортировка будет производиться по функции .
for
U.Insert(; CalcKey());
}
Функция . Возвращаемые значения сортируются в лексографическом порядке, т.е. сначала , потом CalcKey(s): { return [;]; }
UpdateVertex(): { if () if () U.Remove(u); if () U.Insert(; CalcKey()); }
ComputeShortestPath():
{
while (U.TopKey() < CalcKey() OR rhs())
u = U.Pop();
if (g(u) > rhs(u))
g(u) = rhs(u);
for
UpdateVertex(s);
else
g(u) = ;
for
UpdateVertex(s);
}
Таким образом мы описали алгоритм LPA*. Он неоднократно определяет путь между вершинами и , используя при этом данные из предыдущих итераций. Очевидно, что в худшем случае (а именно когда все ребра вокруг текущей вершины изменили свой вес) алгоритм будет работать как последовательные вызовы алгоритма А* за . Улучшим эту оценку с помощью алгоритма D* lite.
Примечание: на практике же такой подход тоже имеет место на плотных графах (или матрицах), так как в среднем дает оценку О(n*log(n)).
Алгоритм D*
Псевдокод (Первая версия)
CalcKey(s): return [;];
Initialize(): U = ; for U.Insert(; CalcKey());
UpdateVertex(u): if () rhs(u) = min_{s' \in Succ(u)}(c(u,s')+g(s')); if () U.Remove(u); if () U.Insert(u; CalcKey(u));
ComputeShortestPath() while (U.TopKey() CalcKey() OR ) u = U.Pop(); if (g(u) > rhs(u)) g(u) = rhs(u); for UpdateVertex(s); else g(u) = ; for UpdateVertex(s);
Main(): Initialize(); ComputeShortestPath(); while () // if () тогда путь на данной итерации не найден. s_{start} = argmins02Succ(sstart) Move to ; Scan graph for changed edge costs; if any edge costs changed for all directed edges (u; v) with changed edge costs Update the edge cost c(u; v); UpdateVertex(u); for U.Update(; CalcKey()); ComputeShortestPath();