1

バークレーのウェブサイトのAIコースページにある課題に取り組んでいます。パックマンのパスを見つけることができるように、深さ優先探索を作成する必要があります。問題は、パックマンがスタックすることです。私が言っていることをより明確にするために、最初にコードを貼り付けます:

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's 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の下で私のコードを読むと、開いているリストに私が訪れて展開したすべてのポイントが含まれていることがわかります。

パスファイルには、pacmanに設定された方向が含まれています。問題は、私が取得した両方の後継者が訪問されていないという条件に直面したときに発生します。私のpacmanは行き止まりにつながるパスをたどるので、バックトレースする必要があります。My Openはそれを実行して解決策を見つけますが、パスリストでバックトレースの方向を提供する方法を見つけることができません。http://inst.eecs.berkeley.edu/~cs188/sp09/projects/search/search.htmlにアクセスし、zipをダウンロードして、search.pydfs searchの下にコードを貼り付けると、私の問題が理解できます。

4

4 に答える 4

3

いくつかのヒント:

  • チェックする各ノードは、そこに到達した方法のデータをカプセル化する必要があります。
  • DFSはスタックのようなものです。開始状態をプッシュすることから始めます。スタックをポップし、ポップしたノードから続くことができるノードをプッシュバックします。
  • 最終的にパスを見つけようとしているので、ノードデータはあなたの場所とそこに到達するためにたどったパスを保持している必要があります。
于 2011-09-15T22:15:58.563 に答える
2

パスの保存方法は非常に重要なトピックです。検索の一部でパスが200ステップ以上になる可能性があることを考えると。リストを何度も繰り返す.... O(2 ^ N)またはO(3 ^ N)?パス保存メカニズムとしてのあらゆる種類の検索のリストは、特にBFSにアクセスし、複数の目的がある場合(つまり、同じノードを通る複数のパスが存在する可能性がある場合)は間違った答えです。リストの複雑さとデータストレージはばかげています。

パスストレージメカニズムとしてリンクリストをお勧めします。ノードをフリンジにプッシュするときは、一意のキーを使用してノードを辞書にキー入力し、キーをプッシュするだけです。次に、フリンジからノードをプルすると、ディクショナリからそのまま状態全体を取得できます。

状態の一部が、その状態が前に1つのステップにあったノードである場合、開始へのパスがあります。エンドノードは、背後にあるノードにリンクし、背後にあるノードにリンクします。このような独自のキーシステムを使用すると、非常に低いデータコストで、同じポイントを通る複数のパスが可能になります。あなたはまだあなたがフリンジを引っ張る道について合理的でなければなりません。ただし、フリンジから何かを引っ張るときはいつでも、1つの番号だけでパス全体を引っ張ることになります。

于 2012-10-09T05:29:28.117 に答える
1

私は、各動きが1つの距離だけであることを確認することによってそれを機能させました。コードの問題の1つは、最後に5〜6か所ジャンプしようとすることでした。それが行うすべての動きが1つであることを確認し、次の目的地までの移動距離が1になるまで逆にします。ヒントmanhattanDistance()。

于 2011-10-16T03:45:27.503 に答える
0
 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')]

これで、3つのリストメンバーを取得したときに行き止まりのパスを使用することに気付くと、Openはバックトレースして正しいパスを見つけることができますが、Path変数で戻り方向を指定する方法が必要です。

たとえば、Path = ['south'、west'west'.................]など

于 2011-09-16T15:49:49.377 に答える