2

So heres my code and it breaks at the line:

 if (suc not in sFrontier) or (suc not in sExplored):

giving the error: TypeError: argument of type 'instance' is not iterable

 """
    The pseudocode I'm following
initialize the frontier using the initial state of the problem
initialize the explored set to be empty
loop do
    if the frontier is empty then return failure
    choose a leaf node and remove it from the frontier
    if the node contains a goal state then return the corresponding solution
    add the node to the explored set
    expand the chosen node, adding the resulting nodes to the frontier
        only if not in the frontier or explored set
"""

sFrontier = util.Stack()
sFrontier.push(problem.getStartState())
sExplored = util.Stack()
lSuccessors = []

while not sFrontier.isEmpty():
  leaf = sFrontier.pop()

  if problem.isGoalState(leaf):
    solution = []
    while not sExplored.isEmpty():
      solution[:0] = (sExplored.pop())[2]
      return solution
  sExplored.push(leaf)
  lSuccessors = problem.getSuccessors(leaf)
  for suc in lSuccessors:
      if (suc not in sFrontier) or (suc not in sExplored):
        sFrontier.push(suc)
return []

problem.getSuccessors returns a list of successor states, the actions they require, and a cost of 1.

so after

lSuccessors = problem.getSuccessors(leaf)

lSuccessors prints

  [((5,4), 'South', 1), ((4,5), 'West', 1)]

and after

  for suc in lSuccessors:

suc prints

  ((5,4), 'South', 1)

Why does it break? Is it because sFrontier and sExplored are stacks and it cannot look in a stack?

Would I need a contain() method or just use a list instead?

All help appreciated :)

mechanical_meat
  • 163,903
  • 24
  • 228
  • 223
user1305599
  • 23
  • 1
  • 2
  • 5
  • The error is a bit confusing, because it's complaining that your `Stack` object is not iterable. The reason for this is that if you don't provide a `__contains__` method, it falls back to trying to iterate the sequence or get its length and use `__getitem__`, and you get the error from the fallback code. So technically, it's asking you to define `__iter__` here… but what you actually want to define is `__contains__`, as Martijn Pieters says. – abarnert Jan 29 '13 at 18:42

4 Answers4

3

It indeed throws the error if your stacks do not support the containment tests. You need to add a __contains__ method to them to support in testing.

There are other ways the in test can find items in your stack, but they are not recommended as they are less effcient than a __contains__ method could be; see the in expression documentation.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
2

I assume util.Stack is your class.

Provide a __contains__(self, x) method to make the objects support a in obj checks.

See the docs: Emulating container types

Kos
  • 70,399
  • 25
  • 169
  • 233
1

SFrontier is a class which contains a list. You in your code checking if suc is in the class sFrontier which you can't because sFrontier is not iterable so you can't check it. You have to write (suc in sFrontier.list) so you check if suc is in the list that your class sFrontier contains.

-1

The problem is on the first side of the if case:

if (succ not in sFrontier)

So you are initializing sFrontier as a Stack but Stack is a class and classes are not iterable. You class must have a list inside it so that it may function as a container. If that's the case what you need to do is this:

if (succ not in sFrontier.list)
P.Kan
  • 1