Алгоритм D* — различия между версиями
Kabanov (обсуждение | вклад) |
Kabanov (обсуждение | вклад) |
||
Строка 24: | Строка 24: | ||
Псевдокод: | Псевдокод: | ||
− | procedure CalcKey(s) | + | procedure CalcKey(s) |
− | { | + | { |
− | return [min(g(s); rhs(s)) + h(s; | + | return [min(g(s); rhs(s)) + h(s;s_{goal});min(g(s); rhs(s))]; |
− | } | + | } |
− | + | '''Initialize'''() | |
− | { | + | { |
− | U = null | + | <tex>U = null;</tex> |
− | for all s \in S | + | <tex>for all s \in S</tex> |
− | + | <tex>rhs(s) = g(s) = 1;</tex> | |
− | rhs(s) = g(s) = 1; | + | <tex>rhs(s_start) = 0;</tex> |
− | + | <tex>U.Insert(s_{start};CalcKey(s_{start}));</tex> | |
− | rhs(s_start) = 0; | + | } |
− | U.Insert(s_{start};CalcKey(s_{start})); | ||
− | } | ||
− | + | '''UpdateVertex'''(<tex>u</tex>): | |
− | { | + | { |
− | if (u != s_{start}) rhs(u) = min_{s' \in Pred(u)}(g(s')+c(s',u)); | + | if (<tex>u != s_{start}</tex>) |
− | if (u \in U) U.Remove(u); | + | <tex>rhs(u) = min_{s' \in Pred(u)}(g(s')+c(s',u));</tex> |
− | if (g(u) != rhs(u)) | + | if (<tex>u \in U</tex>) |
− | + | U.Remove(u); | |
− | U.Insert(u;CalcKey(u)); | + | if (g(u) != rhs(u)) |
− | + | U.Insert(<tex>u</tex>;CalcKey(<tex>u</tex>)); | |
− | } | + | } |
− | + | '''ComputeShortestPath'''(): | |
− | { | + | { |
− | while (U.TopKey()< CalcKey( | + | while (U.TopKey()< CalcKey(s_{goal}) OR rhs(s_{goal}) != g(s_{goal})) |
− | u = U.Pop(); | + | u = U.Pop(); |
− | if (g(u) > rhs(u)) | + | if (g(u) > rhs(u)) |
− | g(u) = rhs(u); | + | g(u) = rhs(u); |
− | for all s 2 Succ(u) UpdateVertex(s); | + | for all s 2 Succ(u) UpdateVertex(s); |
− | else | + | else |
− | g(u) = 1; | + | g(u) = 1; |
− | for all s \in Succ(u) perec {u} | + | for all s \in Succ(u) perec {u} |
− | + | UpdateVertex(s); | |
− | UpdateVertex(s); | + | } |
− | |||
− | } | ||
− | procedure Main() | + | procedure Main() |
− | { | + | { |
− | Initialize(); | + | Initialize(); |
− | while (s_start != s_goal) | + | while (s_start != s_goal) |
− | { | + | { |
− | ComputeShortestPath(); | + | ComputeShortestPath(); |
− | Wait for changes in edge costs; | + | Wait for changes in edge costs; |
− | for all directed edges (u;v) with changed edge costs | + | for all directed edges (u;v) with changed edge costs |
− | { | + | { |
− | Update the edge cost c(u;v); | + | Update the edge cost c(u;v); |
− | UpdateVertex(v); | + | UpdateVertex(v); |
− | } | + | } |
− | } | + | } |
− | } | + | } |
+ | |||
+ | Таким образом мы описали алгоритм LPA*. Он неоднократно определяет путь между вершинами <tex>s_start</tex> и <tex>s_goal</tex>, используя при этом данные из предыдущих итераций. Очевидно, что в худшем случае (а именно когда все ребра вокруг текущей вершины изменили свой вес) алгоритм будет работать как последовательные вызовы алгоритма А* за O(n^2*log(n)). Улучшим эту оценку с помощью алгоритма D* lite. | ||
+ | '''Примечание''': на практике же такой подход тоже имеет место на плотных графах (или матрицах), так как в среднем дает оценку О(n*log(n)). |
Версия 18:29, 17 декабря 2013
D* (pronounced "D star") is any one of the following three related incremental search algorithms.
LPA* Обозначим множество
как множество вершин графа. Обозначим множество как множество вершин, исходящих из вершины . Аналогично множество как множество вершин, входящих в вершину .Функция
будет возвращать перехода из вершины s в вершину s'. При этом s' in Succ(s).Функция g(s) будет возвращать последнее известное значение расстояние от вершины s_start до s.
Если
ИначеБудем говорить, что вершина s @A vertex s is called locally consistent@, если g(s) = rhs(s) Очевидно, что если все вершины "locally consistent", то мы можем найти расстояние от стартовой вершины до любой.
Функция key(s), где s-вершина, возвращает вектор из 2-ух значений k_1(s), k_2(s). k_1(s) = min(g(s), rhs(s)) + h(s, s_goal). k_2(s) = min(g(s), rhs(s))
Если в конце поиска пути g(s_goal) = +inf, то мы не смогли найти путь от s_start до s_goal
Псевдокод:
procedure CalcKey(s) { return [min(g(s); rhs(s)) + h(s;s_{goal});min(g(s); rhs(s))]; }
Initialize() {}
UpdateVertex(): { if ( ) if ( ) U.Remove(u); if (g(u) != rhs(u)) U.Insert( ;CalcKey( )); }
ComputeShortestPath(): { while (U.TopKey()< CalcKey(s_{goal}) OR rhs(s_{goal}) != g(s_{goal})) u = U.Pop(); if (g(u) > rhs(u)) g(u) = rhs(u); for all s 2 Succ(u) UpdateVertex(s); else g(u) = 1; for all s \in Succ(u) perec {u} UpdateVertex(s); }
procedure Main() { Initialize(); while (s_start != s_goal) { ComputeShortestPath(); Wait for changes in edge costs; for all directed edges (u;v) with changed edge costs { Update the edge cost c(u;v); UpdateVertex(v); } } }
Таким образом мы описали алгоритм LPA*. Он неоднократно определяет путь между вершинами
и , используя при этом данные из предыдущих итераций. Очевидно, что в худшем случае (а именно когда все ребра вокруг текущей вершины изменили свой вес) алгоритм будет работать как последовательные вызовы алгоритма А* за O(n^2*log(n)). Улучшим эту оценку с помощью алгоритма D* lite. Примечание: на практике же такой подход тоже имеет место на плотных графах (или матрицах), так как в среднем дает оценку О(n*log(n)).