Flame of udun
Flame of udun

Reputation: 2237

What is wrong with this python code snippet?

Overview : I am a novice in python and am implementing a Localization algorithm in python. The robot executing this code first senses its environment and and multiplies the probability distribution by sensor_right if the color of the cell matches the color in the measurements list. The move function moves the robot to the desired location with a 0.8 probability of a successful movement:

Code :

colors = [['red', 'green', 'green', 'red' , 'red'],
          ['red', 'red', 'green', 'red', 'red'],
          ['red', 'red', 'green', 'green', 'red'],
          ['red', 'red', 'red', 'red', 'red']]

measurements = ['green', 'green', 'green' ,'green', 'green']


motions = [[0,0],[0,1],[1,0],[1,0],[0,1]]

sensor_right =1

p_move = 0.8

def show(p):
    for i in range(len(p)):
        print p[i]

p = []
sum=0
for i in range(len(colors)):
    for j in range(len(colors[i])):
        sum+=1

p=[[1.0/sum for j in range(len(colors[i]))] for i in range(len(colors))]

def sense(p,z):
    q=[]
    sum=0
    for i in range(len(colors)):
        new=[]
        for j in range(len(colors[i])):
            if (colors[i][j]==z) :
                new.append(p[i][j]*sensor_right)
                sum+=p[i][j]*sensor_right
            else :
                new.append(p[i][j]*(1-sensor_right))
                sum+=p[i][j]*(1-sensor_right)

        q.append(new)
    for i in range(len(q)):
        for j in range(len(q)):
            q[i][j]/=sum

    return q

def move(lst,u=[]):
    q=[]
    if (u[0]!=0) :
        for i in range(len(lst)):
            new=[]
            for j in range(len(lst[i])):
                val=lst[j-u[0]][i]*p_move
                new.append(val)
            q.append(new)



    elif (u[1]!=0) :
        for i in range(len(lst)):
            new=[]
            for j in range(len(lst[i])):
                val=lst[i][j-u[1]]*p_move
                new.append(val)
            q.append(new)

    return q

for i in range(len(measurements)):
    p=sense(p,measurements[i])
    p=move(p,motions[i])


show(p)

Problem : The compiler returns the following ouput :

in sense new.append(p[i][j]*(1-sensor_right)) IndexError: list index out of range

When I called commented the motions method, the compiler didn't throw the error and showed the correct output . Oddly though, when I checked the output of the motions method, the 2 d list returned by it had the same dimensions as the 2-d list passed to the sense method when it is called in the loop.Also, why didn't the compiler throw the error at

new.append(p[i][j]*sensor_right)
sum+=p[i][j]*sensor_right

if the index was out of range.

Why is the compiler throwing this error?

Upvotes: 0

Views: 148

Answers (3)

AChampion
AChampion

Reputation: 30268

The first time through your for i in range(len(measurements)): p is a 5x4 list, the return of sense() is a 5x4 list assigned to p. p is then assign to the output of move(p,[0,0]) as both conditions in move() are false move() returns an empty list. The second time around you get the exception which just happens to be down the else: branch of sense().

Upvotes: 1

elyase
elyase

Reputation: 40973

I suggest you take a look at numpy if you are going to be working with this kind of matrix manipulations. I have rewritten a part of your code so that you can compare and get a feeling on how it goes:

import numpy as np

colors = np.array([['red', 'green', 'green', 'red' , 'red'],
                   ['red', 'red', 'green', 'red', 'red'],
                   ['red', 'red', 'green', 'green', 'red'],
                   ['red', 'red', 'red', 'red', 'red']])

sensor_right = 1
p = np.ones_like(colors, dtype=np.float) / colors.size

def sense(p, z):
    condition = colors == z
    p[condition] *= sensor_right
    p[~condition] *= 1 - sensor_right
    return p / p.sum()

Upvotes: 0

Joe
Joe

Reputation: 47639

You keep mentioning 'the compiler'. There is no complier with Python. It is an interpreted language, which means it executes the text of the program directly as it finds it. (There is an intermediary step with pyc, which is the compiled version of the text, but that's not actually relevant).

If you are used to compiled languages then this could be confusing. The problem isn't that the compiler is giving you an error in the static context, it's the result of your program actually running and either i being outside the bounds of p, or j being outside the bounds of p[i].

You can separate out syntax errors (which will get triggered when the Python runtime loads and tries to parse your program) from runtime errors, but there is no middle step. This is philosophically different from compiled programs because at runtime one bit of your program can change the value (and hence type) of a variable.

To solve your current problem, print out i and j, and also p and you will be able to narrow down where the problem is happening.

If you do this, you will see that the call to move is returning [] and this is being assigned back to p. So next time the range loop runs, sense is called with p = [], and any index access is going to throw an out of bounds error.

To solve this, look at the logic of your program and decide why sense is returning [] and why your functions are trying to index p with invalid indexes.

Upvotes: 1

Related Questions