2

I'm working on an AI homework, and despite my professor's suggestions, I have no intention of writing this assignment in lisp. However, I do want to write it recursively, the better to keep it concise and simple. Here is my question:

Am I running a major risk of running out of stack space if I perform a search over a large state space? How deep does the Python stack go?

alexgolec
  • 26,898
  • 33
  • 107
  • 159
  • 2
    why aren't you using tail-call recursion in the first place? Stack overflows shouldn't be an issue. – alternative Feb 17 '11 at 21:23
  • 16
    Writing it in lisp is a better idea. – Don Roby Feb 17 '11 at 21:24
  • 1
    @Don Roby: It's probably a better idea to get credits, but solving the program in *both* languages would IMHO be the best. Let the OP try in Python. In my experience, it's easier for more the complicated "classical AI" search algorithms due to the availability of efficient FIFOs and priority queues in the standard library. – Fred Foo Feb 17 '11 at 21:33
  • 9
    Doing the project in a different language than the professor suggests is NEVER EVER a good idea. 1) s/he probably has a good reason for choosing it (Sometimes it's just to show you the other language, so it might not be the easiest language to solve the project in) 2) It's the language that they are expecting to GRADE. By doing the project in a different language than all of your classmates you are making life MUCH more difficult for your prof, and s/he will probably grade you down for the effort. – Brian Postow Feb 17 '11 at 21:37
  • On the issue: http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html – Jim Brissom Feb 17 '11 at 21:40
  • If he's not strong in Lisp, that would be a reason to do it in Python. I'd rather spend time learning the concepts, instead of struggling with the language. – David Yaw Feb 17 '11 at 21:45
  • @Brian Postow: I didn't say *handing it in* in a different language is a good idea. But trying to solve a problem in several languages is. Some of the best discussions I had with my professors followed from such attempts. – Fred Foo Feb 17 '11 at 21:45
  • @mathepic Even if tail-call recursion is used, it won't save stack space if the language does not optimize it accordingly. Incidentally, Lisp is well known for its tail-call optimization. – Santa Feb 17 '11 at 22:23
  • 1
    @Larsmans: I wasn't disagreeing with you, but the OP. I agree that doing any project in multiple languages is almost always informative. (Alex said he had "no intention" of using LISP, which is what I had an issue with...) Perhaps I should have said "Turning in a the project..." instead. – Brian Postow Feb 17 '11 at 22:24
  • I agree with Brian. The major risk the OP is running is a lot of wasted time to acquire a failing grade. If that's acceptable, then hey go for it. I'm going to go out on a limb here and suggest that maybe the professor has seen people attempt to solve the problem in other languages only to end in failure. Which leads us to why the OP is at school to begin with, you know, to listen to the professor and actually learn something. Before continuing down this path I would highly suggest that the OP schedule some face time with the prof (or counselor) and discuss his thoughts on the matter. – NotMe Feb 17 '11 at 23:59

5 Answers5

24

How deep does the Python stack go?

The default recursion limit in python is 1000 frames. You can use sys.setrecursionlimit(n) to change that at your own risk.

If you're set on using python, I would suggest using a pattern more suited to the language. If you want to use the recursive style search, and need arbitrary stack depth, you can make use of python's enhanced generators (coroutines) to create a "trampoline pattern" (there an example in PEP342)

and despite my professor's suggestions, I have no intention of writing this assignment in lisp

If the exercise is intended to be recursion-based, a tail-call optimized language, like a lisp, is probably your best bet.

JimB
  • 104,193
  • 13
  • 262
  • 255
5

Recursion in Python (CPython, that is) cannot go deeper than sys.getrecursionlimit(). You can set this limit to a different value with sys.setrecursionlimit.

I see three options:

  1. Use Lisp after all, it's optimized for recursive problems (and smart Lisp compilers will eliminate tail recursion)
  2. Set the recursion limit in the recursive function to get unbounded recursion (at the risk of the program eating flaming death)
  3. Use iteration with an explicit stack. A simple list will do. append is push, pop is pop.
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • moreover, it's quite slow compared to the iterative version :) – Ant Feb 17 '11 at 21:24
  • 1
    @Ant: And it gets slower if you have to check and reset the recursion limit inside the algorithm, not to mention the hair on that solution. – Fred Foo Feb 17 '11 at 21:30
3
>>> i=0
>>> def a():
...     global i
...     i += 1
...     try:
...             a()
...     except:
...             print(i)
... 
>>> a()
999
>>> import sys
>>> sys.getrecursionlimit()
1000

Not sure if that helps

Rob Lourens
  • 15,081
  • 5
  • 76
  • 91
2

Python limits the depth of recursion to a value you can find out by calling sys.getrecursionlimit and change by calling sys.setrecursionlimit. The default value isn't terribly big. If you set it too high, then you can end up blowing out the C stack when Python recurses. How high "too high" is is platform-dependent, though the default value should be safe (you get a Python exception rather than a crash) on all platforms.

There are languages that make strong guarantees about tail-call optimization. Scheme is the best-known example; it is a Lisp dialect. You should consider learning at least one Lisp-like language no matter how much you may dislike your professor.

Gareth McCaughan
  • 19,888
  • 1
  • 41
  • 62
2

As others have pointed out, you can increase the recursion depth using sys.setrecursiondepth(), though at the risk of overflowing the C stack (assuming you are using CPython). If you run into this problem, you can create a thread with bigger stack size by calling thread.stack_size() with the new stack size, and then spawn a new thread to do the actual work.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841