Я работаю над заданием, найденным на странице курса AI на веб-сайте berkley для удовольствия. Мне нужно написать поиск в глубину для игры pacman, чтобы он мог найти свой путь. Проблема заключается в том, что pacman застревает. Сначала я вставлю код, чтобы сделать то, что я говорю более ясно:
import util
class SearchProblem:
"""
This class outlines the structure of a search problem, but doesn't implement
any of the methods (in object-oriented terminology: an abstract class).
You do not need to change anything in this class, ever.
"""
def getStartState(self):
"""
Returns the start state for the search problem
"""
util.raiseNotDefined()
def isGoalState(self, state):
"""
state: Search state
Returns True if and only if the state is a valid goal state
"""
util.raiseNotDefined()
def getSuccessors(self, state):
"""
state: Search state
For a given state, this should return a list of triples,
(successor, action, stepCost), where 'successor' is a
successor to the current state, 'action' is the action
required to get there, and 'stepCost' is the incremental
cost of expanding to that successor
"""
util.raiseNotDefined()
def getCostOfActions(self, actions):
"""
actions: A list of actions to take
This method returns the total cost of a particular sequence of actions. The sequence must
be composed of legal moves
"""
util.raiseNotDefined()
def tinyMazeSearch(problem):
"""
Returns a sequence of moves that solves tinyMaze. For any other
maze, the sequence of moves will be incorrect, so only use this for tinyMaze
"""
from game import Directions
s = Directions.SOUTH
w = Directions.WEST
return [s,s,w,s,w,w,s,w]
def depthFirstSearch(problem):
"""
Search the deepest nodes in the search tree first [p 74].
Your search algorithm needs to return a list of actions that reaches
the goal. Make sure to implement a graph search algorithm [Fig. 3.18].
To get started, you might want to try some of these simple commands to
understand the search problem that is being passed in:
print 'Start:', problem.getStartState()
print 'Is the start a goal?', problem.isGoalState(problem.getStartState())
print 'Start successors:', problem.getSuccessors(problem.getStartState())
"""
# *** YOUR CODE HERE ***
start = [problem.getStartState()]
for item in start:
Open=[item]
State=[]
Closed=[]
Path=[]
if problem.isGoalState(Open[0]) is True:
return State
else:
while Open:
visit= Open.pop()
Closed.append(visit)
if State:
Path.append(State.pop())
if problem.isGoalState(visit) is True:
print Closed
return Path
else:
Successors= problem.getSuccessors(visit)
for index in Successors:
it=iter(index)
data=it.next()
if data not in Closed :
Open.append(data)
State.append(it.next())
else:
print Path
Теперь, если вы прочитаете мой код под dfs, вы увидите, что открытый список содержит все точки, которые я посещаю и расширяю.
Файл Path содержит направление, заданное для pacman. Проблема возникает, когда я сталкиваюсь с тем условием, что оба преемника, которых я получаю, не рассматриваются, мой пакман берет путь, который ведет в тупик, поэтому ему нужно возвращаться. Мой Open делает это и находит решение, но я не могу найти способ, как обеспечить направления backtracing в моем списке путей. Если вы перейдете на сайт http://inst.eecs.berkeley.edu/~cs188/sp09/projects/search/search.html и загрузите zip и вставьте мой код в search.py
в поисках dfs, вы поймете мою проблему.
Некоторые подсказки:
Как вы храните свой путь, ОЧЕНЬ важная тема, если учесть, что некоторые из ваших поисков могут привести к длительным шагам 200+. Итерируя по списку, который много раз.... O (2 ^ N) или O (3 ^ N)? списки для любого вида поиска в качестве механизма хранения пути являются неправильным ответом, особенно когда вы попадаете в BFS и в любое время имеете несколько целей (что означает, что могут существовать несколько путей через один и тот же узел). Сложность списков и хранение данных смехотворны.
Я рекомендую ссылки в качестве механизма хранения пути. Когда вы нажимаете свои узлы на бахрому, просто введите их в словарь с уникальным ключом и нажмите клавишу. Затем, когда вы вытаскиваете узел из бахромы, вы можете получить все состояние, как есть, из словаря.
Если частью вашего состояния является узел, в котором это состояние было за один шаг ранее, тогда у вас есть путь к началу; конечный узел ссылается на тот, который находится за ним, который связан с ним позади него и т.д. Использование уникальной ключевой системы, такой как это, позволяет использовать несколько путей через одну и ту же точку, при ЧРЕЗМЕРНО низкой стоимости данных; вы все равно должны быть рациональны в отношении путей, которые вы снимаете с края. Тем не менее, в любое время, когда вы вытаскиваете что-либо из бахромы, вы тянете весь путь, всего 1 номер.
Я сделал это, убедившись, что каждый ход - всего лишь 1 дистанция. Одна из проблем с вашим кодом заключалась в том, что он пытался прыгнуть на 5 или 6 мест. Удостоверьтесь, что каждое движение, которое он делает, одно и наоборот, пока расстояние перемещения не станет 1 до вашего следующего пункта назначения. Подсказка manhattanDistance().
start = [problem.getStartState()]
for item in start:
Open=[item]
Closed=[]
Path=[]
if problem.isGoalState(Open[0]) is True:
return
else:
count=0
while Open:
if count==0:
visit=Open.pop()
else:
temp=Open.pop()
visit=temp[0]
Closed.append(visit)
if problem.isGoalState(visit) is True:
return Path
else:
Successors= problem.getSuccessors(visit)
for index in Successors:
if index[0] not in Closed :
Open.append((index[0],index[1]))
print Open
count=count+1
я изменил код, как сказал. прямо сейчас у меня нет ничего в пути.
это открытое после нахождения решения - (1,1 - решение)
[((5, 4), 'South'), ((4, 5), 'West')]
[((5, 4), 'South'), ((3, 5), 'West')]
[((5, 4), 'South'), ((2, 5), 'West')]
[((5, 4), 'South'), ((1, 5), 'West')]
[((5, 4), 'South'), ((1, 4), 'South')]
[((5, 4), 'South'), ((1, 3), 'South')]
[((5, 4), 'South'), ((2, 3), 'East')]
[((5, 4), 'South'), ((2, 2), 'South')]
[((5, 4), 'South'), ((2, 1), 'South'), ((3, 2), 'East')]
[((5, 4), 'South'), ((2, 1), 'South'), ((4, 2), 'East')]
[((5, 4), 'South'), ((2, 1), 'South'), ((4, 3), 'North')]
[((5, 4), 'South'), ((2, 1), 'South'), ((5, 3), 'East')]
[((5, 4), 'South'), ((2, 1), 'South'), ((5, 4), 'North')]
[((5, 4), 'South'), ((2, 1), 'South')]
[((5, 4), 'South'), ((1, 1), 'West')]
теперь, если вы заметите, когда он получит три члена списка, он принимает путь, который был тупиком, теперь Open способен выполнить обратный путь и найти правильный путь, но мне нужен способ как-то указать направление возврата в переменной Path, как
например, Path = ['south', west 'west'.................] и т.д.