HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Recursive uniform cost search that needs to be optimized

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
searchneedsoptimizeduniformrecursivethatcost

Problem

I have this uniform cost search that I created to solve Project Euler Questions 18 and 67. It takes the numbers in the txt file, places them into a two dimensional list, and then traverses them in a uniform cost search (that I hoped was a kind of implementation of an a* search). It looks like this:

f = open('triangle.txt', 'r')
actualRows = [[n for n in p.split(" ")] for p in f.read().split('\n')]
actualRows.pop()
actualRows = [[int(n) for n in p] for p in actualRows]
rows = [[100 - n for n in p] for p in actualRows]

def astar(pq):
    m = min(pq,key=lambda w: w[3])
    if len(m[2]) + 1 is len(actualRows):
        return m
    pq.remove(m)
    toAdd = list(m[2])
    toAdd.append(m[0])
    pq.append((actualRows[m[4]+1][m[5]], rows[m[4]+1][m[5]], toAdd, m[3] + m[1], m[4]+1, m[5]))
    pq.append((actualRows[m[4]+1][m[5]+1], rows[m[4]+1][m[5]+1], toAdd, m[3] + m[1], m[4]+1, m[5]+1))
    return astar(pq)

# Each tuple is: (actualScore, minScore, previous, totalScore, y, x)
priorityQueue = [(actualRows[0][0], rows[0][0], [], 0, 0, 0)]
a = astar(priorityQueue)
print a
print str(sum(a[2]) + a[0])


I'm not asking for you to tell me how to solve the Problem, I just want to optimize this search so that it doesn't crash going past the 17th row of numbers. How would I optimize this? Or how would I write a proper uniform cost search?

Solution

-
Unpack your tuple to improve readability. There's already a comment

# Each tuple is: (actualScore, minScore, previous, totalScore, y, x)


Put those names in code like this so you can use eg. actualScore instead of m[0]:

(actualScore, minScore, previous, totalScore, y, x) = m


-
You are using recursion to implement a simple loop. I get RuntimeError: maximum recursion depth exceeded even from problem 18. That's because you recurse from every node on every path until you find a solution. Just use a while loop instead.

  • Use the heapq module to implement a priority queue to avoid the linear search done by min.



  • Compare numbers using ==. Only use is for object identity.



  • To learn about the A algorithm, see the highly readable tutorial at Amit’s A Pages.



  • You'll notice that your approach is different. In particular, you don't compute a heuristic. On the other hand I'm not sure if a useful heuristic exists for this problem, but in any case your approach is more like Dijkstra'a algorithm.



  • You should keep track of already visited nodes to avoid exploring the same multiple times.



  • When you add nodes to the priority queue, you should already compute their scores. Now you add both children with the score of the parent. When you eventually pop these nodes from the queue, you get the left child even though you need the better one first. Try the small example at the top of the problem 18 page: program answers 19 instead of 23, because at the bottom row the 5 pops from the queue before the 9.

Code Snippets

# Each tuple is: (actualScore, minScore, previous, totalScore, y, x)
(actualScore, minScore, previous, totalScore, y, x) = m

Context

StackExchange Code Review Q#46883, answer score: 4

Revisions (0)

No revisions yet.