В алгоритме A* отсутствует вычисление

Я пытаюсь заставить вражеский узел следовать за узлом игрока на С# с помощью алгоритма A*. Я прочитал учебники и загрузил несколько примеров С#. Теперь мой алгоритм A* работает в определенной степени. Он будет следовать за игроком на открытом пространстве, но застревает при попытке обвести объект.

Поэтому, когда мой алгоритм проверяет и движется в направлении наименьшего значения F, он может зайти в тупик, и в этот момент ему нужно повторить свои шаги назад, но это невозможно, потому что мой код сообщает ему, что ранее проверенный node закрыт и не может быть перемещен, поэтому он зависает.

Как мне пересчитать закрытый узел, чтобы сообщить моему алгоритму, что можно вернуться таким образом.

Кроме того, если я скажу своему алгоритму вернуться к самому себе, что помешает ему вернуться СНОВА к лучшему узлу, из которого он только что пришел; эффективно возвращаясь между двумя узлами неоднократно.

Я вижу, что он должен иметь возможность проверить узел в закрытом списке и определить, лучше ли он находится на этом конкретном пути, но я не уверен, как это делается.

Эвристика, которую я использую.

G = Math.Abs(StartNodeX - TargetNodeX) + Math.Abs(StartNodeY - TargetNodeY)

H = Math.Abs(CurrentNodeX - TargetNodeX) + Math.Abs(CurrentNodeY - CurrentNodeY)

F = G + H

Псевдокод.

  1. Добавить все соседние узлы в список открытых
  2. Проверьте все эти узлы на наличие самой низкой оценки F и добавьте этот узел в список лучших путей.
  3. Добавить все проверенные узлы в закрытый список (они все проверены, не хочу проверять их снова)
  4. Повторяйте, пока цель не будет достигнута
  5. Переместите врага на 1 узел в направлении наилучшего пути
  6. Повторить все сначала

person user1359819    schedule 28.04.2012    source источник
comment
Моя серия статей о том, как реализовать этот алгоритм на C#, может вам помочь. blogs.msdn.com/b/ericlippert/archive/tags/astar   -  person Eric Lippert    schedule 28.04.2012


Ответы (4)


Как мне пересчитать закрытый узел, чтобы сообщить моему алгоритму, что можно вернуться таким образом?

Нет, потому что это не нормально. Оптимальный путь никогда не включает в себя заход в тупик и выход обратно! Это по определению неоптимальный путь. Алгоритм A* находит оптимальный путь.

если я скажу своему алгоритму вернуться к самому себе, что помешает ему вернуться СНОВА к лучшему узлу, из которого он только что пришел; эффективно возвращаясь между двумя узлами неоднократно.

Ничто не мешает этому. Вот почему это плохая идея делать то, что вы описываете. Если вам больно, когда вы это делаете, не делайте этого.

Эвристика, которую я использую...

Выглядит довольно запутанным.

У вас есть G — манхэттенское расстояние от начала до цели, H — манхэттенское расстояние от текущей точки до цели, а F — их сумма.

Во-первых, манхэттенское расстояние является допустимой метрикой только в том случае, если эвристика предназначена для квадратной сетки без диагонального движения. Вы разрешаете движение по диагонали? Если да, то эта эвристика неверна. Помните, что эвристика необходима, чтобы занизить стоимость. Если вы можете двигаться куда угодно по диагонали, то манхэттенское расстояние завышает стоимость. Вместо этого рассмотрите возможность использования евклидовой метрики.

Во-вторых, расстояние от начала до цели является постоянным, так как же оно релевантно и зачем вы его добавляете к чему-либо? Похоже, вы говорите, что стоимость каждого пути увеличивается на расстояние от начала до цели, что не имеет никакого смысла.

Судя по вашим вопросам, я думаю, что вы не понимаете алгоритм и почему он работает. Мой совет — понять, как работает алгоритм, прежде чем пытаться его реализовать. Вот алгоритм на английском:

The closed set is an empty set of points.
The queue is an empty queue of paths, ordered by path cost.
Enqueue a path from the start to the start with zero cost.
START: 
If the queue is empty, then there is no solution.
The current path is the cheapest path in the queue.
Remove that path from the queue.
If the last step on the current path is closed then 
    the current path is necessarily bad. (Do you see why?)
    Discard it and go back to the START of the loop.
Otherwise, if the last step on the current path is the destination then
    the current path is the optimal path to the destination, so we're done.
Otherwise, we have the cheapest path *to the last 
    point in that path*. (Do you see why?) 
Therefore, every other path that could possibly go through that point is worse.
Therefore, close off that point. Add it to the closed set so that we can 
    automatically discard any future path that goes through that point.
For each possible direction from the last point of the current path,
    make a new path that extends the current path in that direction.
    The estimated cost of that new path is the known cost to get 
    to its end from the start, plus the estimated cost to get from
    its end to the destination.
    Enqueue the new path with that cost.
Go back to the START of the loop.

Имеет ли это смысл?

person Eric Lippert    schedule 28.04.2012
comment
Мой алгоритм может двигаться только вверх, вниз, влево и вправо. Так что расстояние Манхэттена должно быть в порядке. Если цель и цель находятся всего в 2 узлах друг от друга, но на пути есть объект, который охватывает несколько узлов, как он может двигаться вокруг объекта, когда ему нужно отойти дальше от цели, чтобы перемещаться по объекту. ? - person user1359819; 28.04.2012
comment
@ user1359819: Он перемещается вокруг объекта, находя самый дешевый путь. Если окажется, что самый дешевый путь включает некоторое время назад, чтобы обойти объект, алгоритм в конце концов найдет его, когда исчерпает пути, которые выглядят так, как будто они должны быть дешевыми, но на самом деле требуют возврата. Те будут отброшены. - person Eric Lippert; 28.04.2012
comment
@user1359819: Мой совет: создайте небольшую ситуацию, а затем на бумаге следуйте инструкциям английской версии алгоритма. Помните, что очередь — это очередь путей. Кроме того, когда вы делаете это, просто всегда используйте ноль в качестве эвристики. Это дает вам алгоритм Дейкстры, который представляет собой более простую версию A*, которая не так быстра, но выполняет ту же работу. - person Eric Lippert; 28.04.2012
comment
Хорошо, это очень помогает, спасибо. Я почитаю об этом больше. Я думаю, что я не тестирую несколько путей, а на самом деле просто тестирую один и застреваю на нем, не рассматривая другие. - person user1359819; 28.04.2012
comment
@ user1359819: Хорошая идея. Помните, что стоимость пути — это известная стоимость всего пути на данный момент, включая все его изгибы и повороты, плюс оценочная стоимость расстояния от конца. текущего пути к цели. - person Eric Lippert; 28.04.2012

Итак, если я правильно понимаю ваш вопрос, это случай, когда базовый алгоритм A * не подходит. A * говорит вам, что этот мир дает мне кратчайший путь из A в B. Я предполагаю, что в этом мире все меняется. A* не работает с динамическими мирами, поэтому единственным решением, если вы хотите использовать A*, является повторный запуск A* каждый раз с нуля. Сбросьте свои очереди и т. д.

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

http://www.cs.unh.edu/~ruml/papers/rtds-socs10.pdf

http://www.cs.unh.edu/~ruml/papers/rtds-socs10-talk.pdf

person David Mokon Bond    schedule 28.04.2012
comment
Я перезапускаю свой алгоритм A* с нуля каждую секунду, и враг перемещается каждую секунду, если он нашел цель. Все списки инициируются каждый раз при запуске A*, поэтому каждый раз они начинаются пустыми, и при каждом запуске он пытается найти цель. - person user1359819; 28.04.2012
comment
Хорошо, если это так, закрытый список должен сбрасываться каждый раз, когда вы перемещаетесь. Это должно помешать вам попасть в тупик. Вы сбрасываете список закрытых узлов? - person David Mokon Bond; 28.04.2012
comment
Да, я сбрасываю свой закрытый список. По сути, алгоритм ищет лучший путь, затем перемещает врага на 1 узел (первый лучший узел пути в списке), а затем повторяет. Но проблема все еще возникает, поскольку он застревает при попытке вернуться к себе во время алгоритма поиска, если он находит тупик и должен вернуться через ранее закрытый узел. - person user1359819; 28.04.2012

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

Ваша эвристика неприемлема. Вы должны найти другую эвристику.

person Esben Skov Pedersen    schedule 28.04.2012
comment
Недопустимая эвристика все равно вернет решение, просто не всегда оптимальное. Так что это не проблема - person David Mokon Bond; 28.04.2012
comment
Например, взвешенная A* делает эвристику недопустимой, но в некоторых случаях ускоряет поиск. Вы можете выбрать ужасный путь, но для вычисления этого пути требуется, скажем, 10% времени. en.wikipedia.org/wiki/A*_search_algorithm#Admissibility_and_optimality - person David Mokon Bond; 28.04.2012
comment
Правильно, я неправильно прочитал ваш комментарий. Да A* не вернет кратчайшее расстояние, если используется недопустимая эвристика. Я не знаю, действительно ли сломанная эвристика вернет результат. - person Esben Skov Pedersen; 28.04.2012

Я бегаю, пытаясь закрыть старые проблемы здесь, на SO. Я надеюсь, что это все еще помогает так поздно.

Я решал аналогичную проблему в Matlab пару месяцев назад.

Г - твоя проблема. G говорит вам, в чем сложность перемещения из вашего начального местоположения по пути, это не эвристика. Это познаваемо, и вам не нужно его оценивать.

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

Ваша G работает на открытом воздухе, потому что манхэттенское расстояние (ваша метрика G) — это кратчайший путь в беспрепятственной погоне, где вы можете двигаться только в 4 основных направлениях.

рассмотрим следующий пример, в котором вы пытаетесь перейти от A к B. Согласно вашему уравнению, местоположение T будет G = 4, H = 2 и F = 4 + 2 = 6.

00000
00X00
00X00
00XT0
A0X0B

Реальный путь A* будет представлен знаком + с G=10, H=2 и F=12.

0+++0
0+X+0
0+X+0
0+XT0
A+X0B

вычисление G таким образом должно решить проблему.

person Semicolons and Duct Tape    schedule 01.12.2013