Ошибка значения: слишком много значений для распаковки (ожидается 3)

Я пытался реализовать алгоритм итерации значений. У меня есть сетка

grid = [[0, 0, 0, +1],
    [0, "W", 0, -1],
    [0, 0, 0, 0]]

Список действий

actlist = {UP:1, DOWN:2, LEFT:3, RIGHT:4}

И функция вознаграждения

reward = [[0, 0, 0, 0],
      [0, 0, 0, 0],
      [0, 0, 0,  0]] 

Я написал функцию T, которая возвращает кортеж из трех кортежей.

def T(i,j,actions):
if(i == 0 and j == 0):
    if(actions == UP):
        return (i,i,0.8),(i,i,0.1),(i,j+1,0.1)
    elif(actions == DOWN):
        return (i+1,j,0.8),(i,j,0.1),(i,j+1,0.1)
    elif(actions == LEFT):
        return (i,j,0.8),(i,j,0.1),(i+1,j,0.1)
    elif(actions == RIGHT):
        return (i,j+1,0.8),(i,i,0.1),(i+1,j,0.1)
elif (i == 0 and j == 1):
    if(actions == UP):
        return (i,i,0.8),(i,j-1,0.1),(i,j+1,0.1)
    elif(actions == DOWN):
        return (i,j,0.8),(i,j-1,0.1),(i,j+1,0.1)
    elif(actions == LEFT):
        return (i,j-1,0.8),(i,j,0.1),(i,j,0.1)
    elif(actions == RIGHT):
        return (i,j+1,0.8),(i,j,0.1),(i,j,0.1)
elif(i == 0 and j == 2):
    if(actions == UP):
        return (i,j,0.8),(i,j-1,0.1),(i,j+1,0.1)
    elif(actions == DOWN):
        return(i+1,j,0.8),(i,j-1,0.1),(i,j+1,0.1)
    elif(actions == LEFT):
        return (i,j-1,0.8),(i,j,0.1),(i+1,j,0.1)
    elif(actions == RIGHT):
        return (i,j+1,0.8),(i,j,0.1),(i+1,j,0.1)
elif(i == 0 and j == 3):
    if(actions == UP):
        return (-1,-1,0.8),(-1,-1,0.1),(-1,-1,0.1)
    elif(actions == DOWN):
        return (-1,-1,0.8),(-1,-1,0.1),(-1,-1,0.1)
    elif(actions == LEFT):
        return (-1,-1,0.8),(-1,-1,0.1),(-1,-1,0.1)
    elif(actions == RIGHT):
        return (-1,-1,0.8),(-1,-1,0.1),(-1,-1,0.1)
# 2nd row
elif (i == 1 and j == 0):
    if(actions == UP):
        return (i-1,j,0.8),(i,j,0.1),(i,j,0.1)
    elif(actions == DOWN):
        return (i+1,j,0.8),(i,j,0.1),(i,j,0.1)
    elif(actions == LEFT):
        return (i,j,0.8),(i-1,j,0.1),(i+1,j,0.1)
    elif(actions == RIGHT):
        return (i,j,0.8),(i-1,j,0.1),(i+1,j,0.1)
elif(i == 1 and j ==1):
    if(actions == UP):
        return (i,j,0.8),(i,j,0.1),(i,j,0.1)
    elif(actions == DOWN):
        return (i,j,0.8),(i,j,0.1),(i,j,0.1)
    elif(actions == LEFT):
        return (i,j,0.8),(i,j,0.1),(i,j,0.1)
    elif(actions == RIGHT):
        return (i,j,0.8),(i,j,0.1),(i,j,0.1)
elif (i == 1 and j == 2):
    if(actions == UP):
        return (i-1,j,0.8),(i,j,0.1),(i,j+1,0.1)
    elif(actions == DOWN):
        return (i+1,j,0.8),(i,j,0.1),(i,j+1,0.1)
    elif(actions == LEFT):
        return (i,j,0.8),(i-1,j,0.1),(i+1,j,0.1)
    elif(actions == RIGHT):
        return (i,j+1,0.8),(i-1,j,0.1),(i+1,j,0.1)
elif(i == 1 and j == 3):
    if(actions == UP):
        return (-2,-2,0.8),(-2,-2,0.1),(-2,-2,0.1)
    elif(actions == DOWN):
        return (-2,-2,0.8),(-2,-2,0.1),(-2,-2,0.1)
    elif(actions == LEFT):
        return (-2,-2,0.8),(-2,-2,0.1),(-2,-2,0.1)
    elif(actions == RIGHT):
        return (-2,-2,0.8),(-2,-2,0.1),(-2,-2,0.1)      
# 3rd row
elif(i == 2 and j == 0):
    if(actions == UP):
        return (i-1,j,0.8),(i,j,0.1),(i,j+1,0.1)
    elif(actions == DOWN):
        return (i,j,0.8),(i,j,0.1),(i,j+1,1,0.1)
    elif(actions == LEFT):
        return (i,j,0.8),(i-1,j,0.1),(i,j,0.1)
    elif(actions == RIGHT):
        return (i,j+1,0.8),(i-1,j,0.1),(i,j,0.1)
elif (i == 2 and j == 1):
    if(actions == UP):
        return (i,j,0.8),(i,j-1,0.1),(i,j+1,0.1)
    elif(actions == DOWN):
        return (i,j,0.8),(i,j-1,0.1),(i,j+1,0.1)
    elif(actions == LEFT):
        return (i,j-1,0.8),(i,j,0.1),(i,j,0.1)
    elif(actions == RIGHT):
        return (i,j+1,0.8),(i,j,0.1),(i,j,0.1)
elif(i == 2 and j == 2):
    if(actions == UP):
        return (i-1,j,0.8),(i,j-1,0.1),(i,j+1,0.1)
    elif(actions == DOWN):
        return (i,j,0.8),(i,j-1,0.1),(i,j+1,0.1)
    elif(actions == LEFT):
        return (i,j-1,0.8),(i-1,j,0.1),(i,j,1)
    elif(actions == RIGHT):
        return (i,j+1,0.8),(i-1,j,0.1),(i,j,0.1)
elif(i == 2 and j == 3):
    if(actions == UP):
        return (i-1,j,0.8),(i,j-1,0.1),(i,j,0.1)
    elif(actions == DOWN):
        return (i,j,0.8),(i,j-1,0.1),(i,j,0.1)
    elif(actions == LEFT):
        return (i,j-1,0.8),(i-1,j,0.1),(i,j,0.1)
    elif(actions == RIGHT):
        return (i,j,0.8),(i-1,j,0.1),(i,j,0.1) 

Эта функция вызывается в функции итерации значений:

def value_iteration():
U1 = [[0, 0, 0, 0],
      [0, 0, 0, 0],
      [0, 0, 0, 0]] 
while True:
    U=U1.copy()
    delta = 0
    for i in range(len(grid)):
        for j in range(len(grid[i])):
            U1[i][j] = max(sum(p*(R(k,l)+gamma*U[k][l]) for (k,l,p) in T(i,j,a)) for a in actlist)
            print(i,j,U1[i][j])
            delta = max(delta, abs(U1[i][j] - U[i][j]))
    if delta <= epsilon*(1 - gamma)/gamma:
        return U

Проблема в том, что первые две итерации цикла for прошли хорошо с выходом

0 0
0 1
0 2
0 3
1 0
1 1
1 2 
1 3 

Но потом код остановился с ошибкой

ValueError: too many values to unpack (expected 3)

person Shifat E Arman    schedule 06.08.2018    source источник
comment
Можете ли вы предоставить полное сообщение об ошибке, чтобы мы знали, где именно возникает ошибка?   -  person vielkind    schedule 06.08.2018
comment
U1[i][j] = max(sum(p*(R(k,l)+gamma*U[k][l]) for (k,l,p) in T(i,j,a)) for a in actlist) Ошибка возникает в этой строке.   -  person Shifat E Arman    schedule 06.08.2018
comment
Дополнительный вопрос: если все ваши функции действуют как таблица, почему бы вам не использовать словарь?   -  person Edward Minnix    schedule 06.08.2018
comment
@EdwardMinnix, я не знаю, как это сделать.   -  person Shifat E Arman    schedule 06.08.2018
comment
@ShifatEArman Вы могли бы просто создать словарь, в котором ключи были бы трехэлементными кортежами, значения которых равны (i, j, action), и чьи значения были результатами, которые вы должны вернуть из функции (хотя они должны быть жестко запрограммированы. Если вы не знакомы с словари, я бы посоветовал вам обратиться к официальной документации   -  person Edward Minnix    schedule 06.08.2018


Ответы (2)


Посмотрите на кортеж в ** **, может быть, это причина

# 3rd row
elif(i == 2 and j == 0):
    if(actions == UP):
        return (i-1,j,0.8),(i,j,0.1),(i,j+1,0.1)
    elif(actions == DOWN):
        return (i,j,0.8),(i,j,0.1),**(i,j+1,1,0.1)**
    elif(actions == LEFT):
        return (i,j,0.8),(i-1,j,0.1),(i,j,0.1)
    elif(actions == RIGHT):
        return (i,j+1,0.8),(i-1,j,0.1),(i,j,0.1)
elif (i == 2 and j == 1):
    if(actions == UP):
        return (i,j,0.8),(i,j-1,0.1),(i,j+1,0.1)
    elif(actions == DOWN):
        return (i,j,0.8),(i,j-1,0.1),(i,j+1,0.1)
    elif(actions == LEFT):
        return (i,j-1,0.8),(i,j,0.1),(i,j,0.1)
    elif(actions == RIGHT):
       return (i,j+1,0.8),(i,j,0.1),(i,j,0.1)
person Piotrek    schedule 06.08.2018
comment
Глупая ошибка. Большое спасибо. :) - person Shifat E Arman; 06.08.2018
comment
Конечно. Другое дело, я обновляю U=U1.copy() после завершения обоих циклов for. Но он автоматически обновляется внутри моего цикла for. Я не могу понять причину. - person Shifat E Arman; 06.08.2018
comment
не уверен, что это решит вашу проблему, но каждый раз, когда вы используете функцию, вы «сбрасываете» U и U1 и возвращаете U, то есть только нули - person Piotrek; 06.08.2018

Как упоминал @EdwardMinnix, вы должны использовать карту и никогда не использовать такую ​​конструкцию if / else. Или, если есть какой-либо шаблон с этими значениями, посмотрите Stragety Pattern .

Это вам немного поможет:

...

VALUE_A = 0.8
VALUE_B = 0.1


def new_T(i, j, actions):
    result_map = {(0, 0, 1): ((i, i, VALUE_A), (i, i, VALUE_B), (i, j + 1, VALUE_B)),
              (0, 0, 2): ((i + 1, j, VALUE_A), (i, j, VALUE_B), (i, j + 1, VALUE_B)),
              (0, 0, 3): ((i, j, VALUE_A), (i, j, VALUE_B), (i + 1, j, VALUE_B)),
              (0, 0, 4): ((i, j + 1, VALUE_A), (i, i, VALUE_B), (i + 1, j, VALUE_B)),
              (0, 1, 1): ((i, i, VALUE_A), (i, j - 1, VALUE_B), (i, j + 1, VALUE_B)),
              (0, 1, 2): ((i, j, VALUE_A), (i, j - 1, VALUE_B), (i, j + 1, VALUE_B)),
              (0, 1, 3): ((i, j - 1, VALUE_A), (i, j, VALUE_B), (i, j, VALUE_B)),
              (0, 1, 4): ((i, j + 1, VALUE_A), (i, j, VALUE_B), (i, j, VALUE_B)),
              (0, 2, 1): ((i, j, VALUE_A), (i, j - 1, VALUE_B), (i, j + 1, VALUE_B)),
              (0, 2, 2): ((i + 1, j, VALUE_A), (i, j - 1, VALUE_B), (i, j + 1, VALUE_B)),
              (0, 2, 3): ((i, j - 1, VALUE_A), (i, j, VALUE_B), (i + 1, j, VALUE_B)),
              (0, 2, 4): ((i, j + 1, VALUE_A), (i, j, VALUE_B), (i + 1, j, VALUE_B))}

    return result_map.get((i, j, actions))


for i, j, action in itertools.product(range(4), range(4), range(1, 5)):
    print('%s %s %s' % (i, j, action))
    T_value = T(i, j, action)
    new_T_value = new_T(i, j, action)
    if T_value != new_T_value:
        raise AssertionError('Error! \nT:     %s \nNew T: %s' % (T_value, new_T_value))
person Dawid Fieluba    schedule 28.10.2018