Алгоритм A* — различия между версиями
| м (→Ссылки) |  (→Реализация) | ||
| (не показано 11 промежуточных версий 7 участников) | |||
| Строка 1: | Строка 1: | ||
| − | Алгоритм '''А*'''( | + | Алгоритм '''А*''' (англ. ''A star'') {{---}} алгоритм поиска, который находит во взвешенном графе маршрут наименьшей стоимости от начальной вершины до выбранной конечной. | 
| ==Описание== | ==Описание== | ||
| + | [[Файл:Astar_progress_animation.gif|right|frame|Пример работы А*. Пустые кружки принадлежат к открытому списку, а окрашенные к закрытому.]] | ||
| В процессе работы алгоритма для вершин рассчитывается функция <tex>f(v) = g(v) + h(v)</tex>, где   | В процессе работы алгоритма для вершин рассчитывается функция <tex>f(v) = g(v) + h(v)</tex>, где   | ||
| *<tex>g(v)</tex> {{---}} наименьшая стоимость пути в <tex>v</tex> из стартовой вершины,   | *<tex>g(v)</tex> {{---}} наименьшая стоимость пути в <tex>v</tex> из стартовой вершины,   | ||
| − | *<tex>h(v)</tex> {{---}} эвристическое приближение стоимости пути от <tex>v</tex> до конечной цели | + | *<tex>h(v)</tex> {{---}} эвристическое приближение стоимости пути от <tex>v</tex> до конечной цели.   | 
| − | |||
| − | + | Фактически, функция <tex>f(v)</tex> {{---}} длина пути до цели, которая складывается из пройденного расстояния <tex>g(v)</tex> и оставшегося расстояния <tex>h(v)</tex>. Исходя из этого, чем меньше значение <tex>f(v)</tex>, тем раньше мы откроем вершину <tex>v</tex>, так как через неё мы предположительно достигнем расстояние до цели быстрее всего. | |
| − | + | Открытые алгоритмом вершины можно хранить в очереди с приоритетом по значению <tex>f(v)</tex>. А* действует подобно [[Алгоритм Дейкстры | алгоритму Дейкстры]] и просматривает среди всех маршрутов ведущих к цели сначала те, которые благодаря имеющейся информации (эвристическая функция) в данный момент являются наилучшими.  | |
| − | + | <br clear="all"> | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| ==Свойства== | ==Свойства== | ||
| − | = | + | Чтобы A* был оптимален, выбранная функция <tex>h(v)</tex> должна быть '''допустимой''' эвристической функцией. | 
| − | + | {{Определение | |
| + | |definition=Говорят, что эвристическая оценка <tex>h(v)</tex> '''допустима''', если для любой вершины <tex>v</tex> значение <tex>h(v)</tex> меньше или равно весу кратчайшего пути от <tex>v</tex> до цели. | ||
| + | }} | ||
| − | === | + | Допустимая оценка является оптимистичной, потому что она предполагает, что стоимость решения меньше, чем оно есть на самом деле. <br> | 
| − | + | Второе, более сильное условие {{---}} функция <tex>h(v)</tex> должна быть '''монотонной'''. | |
| − | == | + | |
| − | *[ | + | {{Определение | 
| − | *[ | + | |definition=Эвристическая функция <tex>h(v)</tex> называется '''монотонной''' (или '''преемственной'''), если для любой вершины <tex>v_1</tex> и ее потомка <tex>v_2</tex> разность <tex>h(v_1)</tex> и <tex>h(v_2)</tex> не превышает фактического веса ребра <tex>c(v_1, v_2)</tex> от <tex>v_1</tex> до <tex>v_2</tex>, а эвристическая оценка целевого состояния равна нулю. | 
| − | *[http://theory.stanford.edu/~amitp/GameProgramming/] | + | }} | 
| − | *[http://dl.acm.org/citation.cfm?id=3830&coll=portal&dl=ACM ] | + | |
| + | {{Теорема | ||
| + | |statement=Любая монотонная эвристика допустима, однако обратное неверно. | ||
| + | |proof=Пусть <tex>k(v)</tex> {{---}} длина кратчайшего пути из вершины <tex>v</tex> до цели.  | ||
| + | Докажем индукцией по числу шагов до цели, что <tex>h(v) \leqslant k(v)</tex>.<br><br> | ||
| + | Если до цели расстояние <tex>0</tex>, то <tex>v</tex> {{---}} цель и <tex>h(v) = 0 \leqslant k(v)</tex>.<br><br> | ||
| + | Пусть <tex>v</tex> находится на расстоянии <tex>i</tex> от цели. Тогда существует потомок <tex>v'</tex>, который находится на кратчайшем пути от <tex>v</tex> до цели и <tex>v'</tex>лежит на расстоянии <tex>i - 1</tex> шагов до цели. Следовательно, <tex>h(v) \leqslant c(v, v') + h(v')</tex>. <br> | ||
| + | По предположению, <tex>h(v') \leqslant k(v')</tex>. Следовательно, <tex>h(v) \leqslant c(v, v') + k(v') = k(v)</tex>. <br><br>Таким образом, монотонная эвристика <tex>h(v)</tex> допустима. | ||
| + | }} | ||
| + | |||
| + | {{Утверждение | ||
| + | |statement=Если <tex>h(v)</tex> монотонна, то последовательность значений <tex>f(v)</tex> на любом пути неубывает. | ||
| + | |proof=Доказательство следует из определения монотонности.<br> | ||
| + | Пусть <tex>v'</tex> {{---}} потомок <tex>v</tex>, тогда <tex>g(v') = g(v) + c(v, v')</tex>. <br>Следовательно, <tex>f(v') = g(v') + h(v') = g(v) + c(v, v') + h(v') \geqslant g(v) + h(v) = f(v)</tex>. | ||
| + | }} | ||
| + | |||
| + | {{Утверждение | ||
| + | |statement=Алгоритм A* является оптимальным, если функция <tex>h(v)</tex> монотонна. | ||
| + | |proof=Последовательность вершин "развёрнутых" во время работы алгоритма находится в неубывающем порядке значений <tex>f</tex>. Поэтому очередная выбираемая вершина должна представлять собой оптимальное решение, поскольку все дальнейшие узлы будут, по меньшей мере, столь же дорогостоящими.  | ||
| + | }} | ||
| + | |||
| + | ==Примеры эвристик== | ||
| + | Поведение алгоритма сильно зависит от того, какая эвристика используется. В свою очередь, выбор эвристики зависит[[Файл:Diagonal.png|thumb|right|Пример А* на сетке с возможностью ходить в восьми напрвлениях]] от постановки задачи. Часто А* используется для моделирования перемещения по поверхности, покрытой координатной сеткой. | ||
| + | |||
| + | * Если мы можем перемещаться в четырех направлениях, то в качестве эвристики стоит выбрать манхэттенское расстояние<ref>[https://en.wikipedia.org/wiki/Manhattan_distance Wikipedia {{---}} Manhattan distance]</ref><br> <tex>h(v) = |{v.x-goal.x}| + |{v.y-goal.y}|</tex>.  | ||
| + | |||
| + | * Расстояние Чебышева<ref>[https://ru.wikipedia.org/wiki/Расстояние_Чебышева Википедия {{---}} Расстояние Чебышева]</ref> применяется, когда к четырем направлениям добавляются диагонали:<br> <tex>h(v) = \max{(|{v.x-goal.x}|, |{v.y-goal.y}|)}</tex>. | ||
| + | |||
| + | * Если передвижение не ограничено сеткой, то можно использовать евклидово расстояние по прямой:<br> <tex>h(v) = \sqrt{(v.x-goal.x)^2 + (v.y-goal.y)^2}</tex>. | ||
| + | |||
| + | Также стоит обратить внимание на то как соотносятся <tex>f(v)</tex> и <tex>h(v)</tex>. Если они измеряются в разных величинах (например, <tex>g(v)</tex> {{---}} это расстояние в километрах, а <tex>h(v)</tex> {{---}} оценка времени пути в часах) А* может выдать некорректный результат. | ||
| + | |||
| + | ==Реализация== | ||
| + | В приведённой реализации: | ||
| + | * <tex>Q</tex> {{---}} множество вершин, которые требуется рассмотреть, | ||
| + | * <tex>U</tex> {{---}} множество рассмотренных вершин, | ||
| + | * <tex>f[x]</tex> {{---}} значение эвристической функции "расстояние + стоимость" для вершины <tex>x</tex>, | ||
| + | * <tex>g[x]</tex> {{---}} стоимость пути от начальной вершины до <tex>x</tex>, | ||
| + | * <tex>h(x)</tex> {{---}} эвристическая оценка расстояния от вершины <tex>x</tex> до конечной вершины. | ||
| + | На каждом этапе работы алгоритма из множества <tex>Q</tex> выбирается вершина с наименьшим значением эвристической функции и просматриваются её соседи. Для каждого из соседей обновляется расстояние, значение эвристической функции и он добавляется в множество <tex>Q</tex>.<br> | ||
| + | Псевдокод: | ||
| + |  '''bool''' A*(start, goal)''':''' | ||
| + |      U = <tex> \varnothing </tex> | ||
| + |      Q = <tex> \varnothing </tex> | ||
| + |      Q.push(start) | ||
| + |      g[start] = 0 | ||
| + |      f[start] = g[start] + h(start) | ||
| + |      '''while''' Q.size() != 0 | ||
| + |          current = вершина из <tex>Q</tex> с минимальным значением <tex>f</tex> | ||
| + |          '''if''' current == goal | ||
| + |              '''return''' ''true''                                           <font color="green">// нашли путь до нужной вершины</font> | ||
| + |          Q.remove(current) | ||
| + |          U.push(current) | ||
| + |          '''for''' v : смежные с current вершины | ||
| + |              tentativeScore = g[current] + d(current, v)           <font color="green">// d(current, v) {{---}} стоимость пути между current и v</font>  | ||
| + |              '''if''' <tex>v \in U</tex> '''and''' tentativeScore >= g[v] | ||
| + |                  '''continue''' | ||
| + |              '''if''' <tex>v \notin U</tex> '''or''' tentativeScore < g[v] | ||
| + |                  parent[v] = current | ||
| + |                  g[v] = tentativeScore | ||
| + |                  f[v] = g[v] + h(v) | ||
| + |                  '''if''' <tex>v \notin Q</tex> | ||
| + |                      Q.push(v) | ||
| + |      '''return''' ''false'' | ||
| + | |||
| + | ==См. также== | ||
| + | * [[Эвристики для поиска кратчайших путей]] | ||
| + | * [[Алгоритм Флойда]] | ||
| + | * [[Алгоритм Дейкстры]] | ||
| + | * [[Алгоритм Форда-Беллмана]] | ||
| + | |||
| + | ==Примечания== | ||
| + | <references/> | ||
| + | |||
| + | ==Источники информации== | ||
| + | * С. Рассел, П. Норвиг {{---}} Искусственный интеллект. Современный подход, 2е издание | ||
| + | * [https://ru.wikipedia.org/wiki/Алгоритм_поиска_A* Википедия {{---}} Алгоритм поиска A*] | ||
| + | * [https://en.wikipedia.org/wiki/A*_search_algorithm Wikipedia {{---}} A* search algorithm] | ||
| + | * [http://theory.stanford.edu/~amitp/GameProgramming/ Статья о поиске кратчайших путей] | ||
| + | * [http://dl.acm.org/citation.cfm?id=3830&coll=portal&dl=ACM Generalized best-first search strategies and the optimality of A*] | ||
| [[Категория: Алгоритмы и структуры данных]] | [[Категория: Алгоритмы и структуры данных]] | ||
| [[Категория: Кратчайшие пути в графах ]] | [[Категория: Кратчайшие пути в графах ]] | ||
Текущая версия на 22:59, 6 мая 2019
Алгоритм А* (англ. A star) — алгоритм поиска, который находит во взвешенном графе маршрут наименьшей стоимости от начальной вершины до выбранной конечной.
Содержание
Описание
В процессе работы алгоритма для вершин рассчитывается функция , где
- — наименьшая стоимость пути в из стартовой вершины,
- — эвристическое приближение стоимости пути от до конечной цели.
Фактически, функция  — длина пути до цели, которая складывается из пройденного расстояния  и оставшегося расстояния . Исходя из этого, чем меньше значение , тем раньше мы откроем вершину , так как через неё мы предположительно достигнем расстояние до цели быстрее всего.
Открытые алгоритмом вершины можно хранить в очереди с приоритетом по значению . А* действует подобно  алгоритму Дейкстры и просматривает среди всех маршрутов ведущих к цели сначала те, которые благодаря имеющейся информации (эвристическая функция) в данный момент являются наилучшими. 
Свойства
Чтобы A* был оптимален, выбранная функция должна быть допустимой эвристической функцией.
| Определение: | 
| Говорят, что эвристическая оценка допустима, если для любой вершины значение меньше или равно весу кратчайшего пути от до цели. | 
Допустимая оценка является оптимистичной, потому что она предполагает, что стоимость решения меньше, чем оно есть на самом деле. 
Второе, более сильное условие — функция  должна быть монотонной.
| Определение: | 
| Эвристическая функция называется монотонной (или преемственной), если для любой вершины и ее потомка разность и не превышает фактического веса ребра от до , а эвристическая оценка целевого состояния равна нулю. | 
| Теорема: | 
| Любая монотонная эвристика допустима, однако обратное неверно. | 
| Доказательство: | 
| Пусть  — длина кратчайшего пути из вершины  до цели. 
Докажем индукцией по числу шагов до цели, что . Таким образом, монотонная эвристика допустима. | 
| Утверждение: | 
| Если  монотонна, то последовательность значений  на любом пути неубывает. | 
| Доказательство следует из определения монотонности. Следовательно, . | 
| Утверждение: | 
| Алгоритм A* является оптимальным, если функция  монотонна. | 
| Последовательность вершин "развёрнутых" во время работы алгоритма находится в неубывающем порядке значений . Поэтому очередная выбираемая вершина должна представлять собой оптимальное решение, поскольку все дальнейшие узлы будут, по меньшей мере, столь же дорогостоящими. | 
Примеры эвристик
Поведение алгоритма сильно зависит от того, какая эвристика используется. В свою очередь, выбор эвристики зависит от постановки задачи. Часто А* используется для моделирования перемещения по поверхности, покрытой координатной сеткой.-  Если мы можем перемещаться в четырех направлениях, то в качестве эвристики стоит выбрать манхэттенское расстояние[1]
 .
-  Расстояние Чебышева[2] применяется, когда к четырем направлениям добавляются диагонали:
 .
-  Если передвижение не ограничено сеткой, то можно использовать евклидово расстояние по прямой:
 .
Также стоит обратить внимание на то как соотносятся и . Если они измеряются в разных величинах (например, — это расстояние в километрах, а — оценка времени пути в часах) А* может выдать некорректный результат.
Реализация
В приведённой реализации:
- — множество вершин, которые требуется рассмотреть,
- — множество рассмотренных вершин,
- — значение эвристической функции "расстояние + стоимость" для вершины ,
- — стоимость пути от начальной вершины до ,
- — эвристическая оценка расстояния от вершины до конечной вершины.
На каждом этапе работы алгоритма из множества  выбирается вершина с наименьшим значением эвристической функции и просматриваются её соседи. Для каждого из соседей обновляется расстояние, значение эвристической функции и он добавляется в множество .
Псевдокод:
bool A*(start, goal):
    U = 
    Q = 
    Q.push(start)
    g[start] = 0
    f[start] = g[start] + h(start)
    while Q.size() != 0
        current = вершина из  с минимальным значением 
        if current == goal
            return true                                           // нашли путь до нужной вершины
        Q.remove(current)
        U.push(current)
        for v : смежные с current вершины
            tentativeScore = g[current] + d(current, v)           // d(current, v) — стоимость пути между current и v 
            if  and tentativeScore >= g[v]
                continue
            if  or tentativeScore < g[v]
                parent[v] = current
                g[v] = tentativeScore
                f[v] = g[v] + h(v)
                if 
                    Q.push(v)
    return false
См. также
Примечания
Источники информации
- С. Рассел, П. Норвиг — Искусственный интеллект. Современный подход, 2е издание
- Википедия — Алгоритм поиска A*
- Wikipedia — A* search algorithm
- Статья о поиске кратчайших путей
- Generalized best-first search strategies and the optimality of A*


