Поиск бахромы - Fringe search

В информатике , поиск бахрома является графиком алгоритм поиска , который находит путь с наименьшей стоимостью от заданного начального узла к одной цели узла .

По сути, поиск по краям - это золотая середина между A * и вариантом A * с итеративным углублением (IDA *).

Если g ( x ) - стоимость пути поиска от первого узла до текущего, а h ( x ) - эвристическая оценка стоимости от текущего узла до цели, то ƒ ( x ) =  g ( x ) +  h ( x ) , а h * - фактическая стоимость пути к цели. Рассмотрим IDA *, который выполняет рекурсивный поиск в глубину слева направо от корневого узла, останавливая рекурсию, как только цель была найдена или узлы достигли максимального значения ƒ . Если цель не найдена в первом пороге ƒ , порог затем увеличивается, и алгоритм выполняет поиск снова. IE Он повторяется на пороге.

У IDA есть три основных недостатка. Во-первых, IDA * будет повторять состояния при наличии нескольких (иногда неоптимальных) путей к целевому узлу - это часто решается путем сохранения кеша посещенных состояний. Измененная таким образом IDA * обозначается как IDA * с расширенной памятью (ME-IDA *), поскольку она использует некоторую память. Кроме того, IDA * повторяет все предыдущие операции поиска при итерациях с новым порогом, необходимым для работы без хранилища. Сохраняя листовые узлы предыдущей итерации и используя их в качестве начальной позиции следующей, эффективность IDA * значительно повышается (в противном случае на последней итерации он всегда должен был бы посещать каждый узел в дереве).

Fringe search реализует эти улучшения в IDA *, используя структуру данных, которая представляет собой более или менее двух списков для итерации по границе или краю дерева поиска. В одном списке теперь хранится текущая итерация, а в другом списке позже сохраняется ближайшая следующая итерация. Таким образом, из корневого узла дерева поиска теперь будет корень, а затем будет пусто. Тогда алгоритм принимает один из двух действий: Если ƒ (голова) больше порогового значения тока, удалить голову из ныне и добавить его к концу позже ; т.е. сохранить голову для следующей итерации. В противном случае, если ƒ (голова) меньше или равно пороговому значению, расширить голову и отбрасывания голову , считают своих детей, добавляя их к началу Сейчас . В конце итерации порог увеличивается, более поздний список становится списком « Сейчас» , а затем очищается.

Важное различие между fringe и A * состоит в том, что содержимое списков в fringe не обязательно должно быть отсортировано - значительное преимущество по сравнению с A *, которое требует зачастую дорогостоящего поддержания порядка в его открытом списке. Однако, в отличие от A *, fringe должен будет посещать одни и те же узлы неоднократно, но стоимость каждого такого посещения постоянна по сравнению с логарифмическим временем сортировки списка в A * в худшем случае.

Псевдокод

Реализация обоих списков в одном двусвязном списке, где узлы, предшествующие текущему узлу, являются более поздней частью, а все остальное - списком сейчас . Используя массив предварительно выделенных узлов в списке для каждого узла в сетке, время доступа к узлам в списке сокращается до постоянного. Точно так же массив маркеров позволяет выполнять поиск узла в списке за постоянное время. g хранится как хеш-таблица, а последний массив маркеров сохраняется для постоянного поиска того, был ли ранее посещен узел и действительна ли запись в кэше.

init(start, goal)
    fringe F = s
    cache C[start] = (0, null)
    flimit = h(start)
    found = false

    while (found == false) AND (F not empty)
        fmin = 
        for node in F, from left to right
            (g, parent) = C[node]
            f = g + h(node)
            if f > flimit
                fmin = min(f, fmin)
                continue
            if node == goal
                found = true
                break
            for child in children(node), from right to left
                g_child = g + cost(node, child)
                if C[child] != null
                    (g_cached, parent) = C[child]
                    if g_child >= g_cached
                        continue
                if child in F
                    remove child from F
                insert child in F past node
                C[child] = (g_child, node)
            remove node from F
        flimit = fmin

    if reachedgoal == true
        reverse_path(goal)

Обратный псевдокод.

reverse_path(node)
    (g, parent) = C[node]
    if parent != null
        reverse_path(parent)
    print node

Эксперименты

При тестировании в сеточной среде, типичной для компьютерных игр, включая непроходимые препятствия, fringe превзошел A * примерно на 10-40 процентов, в зависимости от использования тайлов или октилей. Возможные дальнейшие улучшения включают использование структуры данных, которая легче поддается кэшированию.

Рекомендации

  • Бьёрнссон, Ингви; Энценбергер, Маркус; Holte, Роберт C .; Шеффер, Джонатан. Fringe Search: победа над A * в поиске пути на игровых картах. Материалы симпозиума IEEE 2005 г. по вычислительному интеллекту и играм (CIG05). Университет Эссекса, Колчестер, Эссекс, Великобритания, 4–6 апреля 2005 г. IEEE 2005. https://web.archive.org/web/20090219220415/http://www.cs.ualberta.ca/~games/pathfind/ публикации / cig2005.pdf

внешняя ссылка