A* algorithm TypeError: cannot unpack non-iterable int object
A* algorithm TypeError: cannot unpack non-iterable int object
这是 python 代码,它使用 A* 算法寻找 8 道难题的解决方案,我收到了一些错误消息,我该如何解决?(错误消息在代码下方)
There are several object-oriented programming concepts for Problems
class, Node
class that are implemented to express the problem solution search that you need to understand in order to make the Python program complete. The priority queue is to make the nodes to be explored to be sorted according to their f-evaluation function score and return the min one as the first node to be searched next.
There is also a memorize
function to memorize the heuristic value of state as a look-up table so that you don’t need to calculate the redundant computing of heuristic estimation value, so you can ignore it at this point if you don’t understand.
The components you need to implement is to make the abstract part of the program realizable for 8 -puzzle with the successor methods attached to a problem class which consists of initial state and goal state. Make sure the program can run correctly to generate the solution sequence that move the empty tile so that the 8-puzzle can move "Up", "Down", "Left", "Right", from initial state to goal state.
import math
infinity = math.inf
from itertools import chain
import numpy as np
import bisect
class memoize:
def __init__(self, f, memo={}):
self.f = f
self.memo = {}
def __call__(self, *args):
if not str(args) in self.memo:
self.memo[str(args)] = self.f(*args)
return self.memo[str(args)]
def coordinate(state):
index_state = {}
index = [[0,0], [0,1], [0,2], [1,0], [1,1], [1,2], [2,0], [2,1], [2,2]]
for i in range(len(state)):
index_state[state[i]] = index[i]
return index_state
def getInvCount(arr):
inv_count = 0
empty_value = -1
for i in range(0, 9):
for j in range(i + 1, 9):
if arr[j] != empty_value and arr[i] != empty_value and arr[i] > arr[j]:
inv_count += 1
return inv_count
def isSolvable(puzzle) :
inv_count = getInvCount([j for sub in puzzle for j in sub])
return (inv_count % 2 == 0)
def linear(state):
return sum([1 if state[i] != goal[i] else 0 for i in range(9)])
@memoize
def manhattan(state):
index_goal = coordinate(goal)
index_state = coordinate(state)
mhd = 0
for i in range(9):
for j in range(2):
mhd = abs(index_goal[i][j] - index_state[i][j]) + mhd
return mhd
@memoize
def sqrt_manhattan(state):
index_goal = coordinate(goal)
index_state = coordinate(state)
mhd = 0
for i in range(9):
for j in range(2):
mhd = (index_goal[i][j] - index_state[i][j])**2 + mhd
return math.sqrt(mhd)
@memoize
def max_heuristic(state):
score1 = manhattan(state)
score2 = linear(state)
return max(score1, score2)
class PriorityQueueElmt:
def __init__(self,val,e):
self.val = val
self.e = e
def __lt__(self,other):
return self.val < other.val
def value(self):
return self.val
def elem(self):
return self.e
class Queue:
def __init__(self):
pass
def extend(self, items):
for item in items: self.append(item)
class PriorityQueue(Queue):
def __init__(self, order=min, f=None):
self.A=[]
self.order=order
self.f=f
def append(self, item):
queueElmt = PriorityQueueElmt(self.f(item),item)
bisect.insort(self.A, queueElmt)
def __len__(self):
return len(self.A)
def pop(self):
if self.order == min:
return self.A.pop(0).elem()
else:
return self.A.pop().elem()
# Heuristics for 8 Puzzle Problem
class Problem:
def __init__(self, initial, goal=None):
self.initial = initial; self.goal = goal
def successor(self, state):
reachable = []
def get_key(val):
for key, value in index_state.items():
if val == value:
return key
return -1
def candidate(state, Position):
state = state.copy()
zero_index = state.index(0)
swap_index = state.index(get_key(Position))
state[zero_index], state[swap_index] = state[swap_index], state[zero_index]
return state
index_state = coordinate(state)
zero_position = index_state[0]
move_pair = {"left":[zero_position[0], zero_position[1] - 1],
"right":[zero_position[0], zero_position[1] + 1],
"up":[zero_position[0] - 1, zero_position[1]],
"down":[zero_position[0] + 1, zero_position[1]]
}
for action, position in move_pair.items():
#print(action, position)
if get_key(position) != -1:
reachable.append((action, candidate(state, position)))
#print(reachable)
return reachable
def goal_test(self, state):
return state == self.goal
def path_cost(self, c, state1, action, state2):
return c + 1
def value(self):
abstract
class Node:
def __init__(self, state, parent=None, action=None, path_cost=0, depth =0):
self.parent = parent
if parent:
self.depth = parent.depth + 1
else:
self.depth = 0
self.path_cost = path_cost
self.state = state
if action:
self.action = action
else: self.action = "init"
def __repr__(self):
return "Node state:\n " + str(np.array(self.state).reshape(3,3)) +"\n -> action: " + self.action + "\n -> depth: " + str(self.depth)
def path(self):
x, result = self, [self]
while x.parent:
result.append(x.parent)
x = x.parent
return result
def expand(self, problem):
for (act,n) in problem.successor(self.state):
if n not in [node.state for node in self.path()]:
yield Node(n, self, act,
problem.path_cost(self.path_cost, self.state, act, n))
def graph_search(problem, fringe):
closed = {}
fringe.append(Node(problem.initial,depth=0))
while fringe:
node = fringe.pop()
if problem.goal_test(node.state):
return node
if str(node.state) not in closed:
closed[str(node.state)] = True
fringe.extend(node.expand(problem))
return None
def best_first_graph_search(problem, f):
return graph_search(problem, PriorityQueue(min, f))
def astar_search(problem, h = None):
h = h or problem.h
def f(n):
return max(getattr(n, 'f', -infinity), n.path_cost + h(n.state))
return best_first_graph_search(problem, f)
def print_path(path, method):
print("*" * 30)
print("\nPath: (%s distance)" % method)
for i in range(len(path)-1, -1, -1):
print("-" * 15)
print(path[i])
goal = [1, 2, 3, 4, 5, 6, 7, 8, 0]
# Solving the puzzle
puzzle = [7, 2, 4, 5, 0, 6, 8, 3, 1]
if(isSolvable(np.array(puzzle).reshape(3,3))): # even true
# checks whether the initialized configuration is solvable or not
print("Solvable!")
problem = Problem(puzzle,goal)
path = astar_search(problem, manhattan).path()
print_path(path, "manhattan")
path = astar_search(problem, linear).path()
print_path(path, "linear")
path = astar_search(problem, sqrt_manhattan).path()
print_path(path, "sqrt_manhattan")
path = astar_search(problem, max_heuristic).path()
print_path(path, "max_heuristic")
else :
print("Not Solvable!") # non-even false
TypeError Traceback (most recent call last)
<ipython-input-124-2a60ddc8c009> in <module>
9 problem = Problem(puzzle,goal)
10
---> 11 path = astar_search(problem, manhattan).path()
12 print_path(path, "manhattan")
13
<ipython-input-123-caa97275712e> in astar_search(problem, h)
18 def f(n):
19 return max(getattr(n, 'f', -infinity), n.path_cost + h(n.state))
---> 20 return best_first_graph_search(problem, f)
21
22 def print_path(path, method):
<ipython-input-123-caa97275712e> in best_first_graph_search(problem, f)
12
13 def best_first_graph_search(problem, f):
---> 14 return graph_search(problem, PriorityQueue(min, f))
15
16 def astar_search(problem, h = None):
<ipython-input-123-caa97275712e> in graph_search(problem, fringe)
8 if str(node.state) not in closed:
9 closed[str(node.state)] = True
---> 10 fringe.extend(node.expand(problem))
11 return None
12
<ipython-input-121-e5a968bd54f0> in extend(self, items)
18
19 def extend(self, items):
---> 20 for item in items: self.append(item)
21
22 class PriorityQueue(Queue):
<ipython-input-122-db21613469b9> in expand(self, problem)
69
70 def expand(self, problem):
---> 71 for (act,n) in problem.successor(self.state):
72 if n not in [node.state for node in self.path()]:
73 yield Node(n, self, act,
TypeError: cannot unpack non-iterable int object
I got some error messages, how can I fix it?
有一条错误信息,你在错误信息中得到的代码片段是堆栈跟踪,这可能有助于你了解执行是如何到达错误发生的最后一点的。在这种情况下,这并不那么重要。错误的本质是这样的:
for (act,n) in problem.successor(self.state)
TypeError: cannot unpack non-iterable int object
所以这意味着 successor
方法 return 编辑了 int
而不是列表。
查看 successor
的代码,我注意到它打算 return 一个名为 reachable
的列表,但中间有一个 return
语句代码的最大部分未执行(所谓的“死代码”):
return state
这条语句放在什么地方是没有意义的。这似乎是一个缩进问题:return
属于它上面的函数内部,如下所示:
def candidate(state, Position):
state = state.copy()
zero_index = state.index(0)
swap_index = state.index(get_key(Position))
state[zero_index], state[swap_index] = state[swap_index], state[zero_index]
return state # <-- indentation!
这是 python 代码,它使用 A* 算法寻找 8 道难题的解决方案,我收到了一些错误消息,我该如何解决?(错误消息在代码下方)
There are several object-oriented programming concepts for
Problems
class,Node
class that are implemented to express the problem solution search that you need to understand in order to make the Python program complete. The priority queue is to make the nodes to be explored to be sorted according to their f-evaluation function score and return the min one as the first node to be searched next.There is also a
memorize
function to memorize the heuristic value of state as a look-up table so that you don’t need to calculate the redundant computing of heuristic estimation value, so you can ignore it at this point if you don’t understand.The components you need to implement is to make the abstract part of the program realizable for 8 -puzzle with the successor methods attached to a problem class which consists of initial state and goal state. Make sure the program can run correctly to generate the solution sequence that move the empty tile so that the 8-puzzle can move "Up", "Down", "Left", "Right", from initial state to goal state.
import math
infinity = math.inf
from itertools import chain
import numpy as np
import bisect
class memoize:
def __init__(self, f, memo={}):
self.f = f
self.memo = {}
def __call__(self, *args):
if not str(args) in self.memo:
self.memo[str(args)] = self.f(*args)
return self.memo[str(args)]
def coordinate(state):
index_state = {}
index = [[0,0], [0,1], [0,2], [1,0], [1,1], [1,2], [2,0], [2,1], [2,2]]
for i in range(len(state)):
index_state[state[i]] = index[i]
return index_state
def getInvCount(arr):
inv_count = 0
empty_value = -1
for i in range(0, 9):
for j in range(i + 1, 9):
if arr[j] != empty_value and arr[i] != empty_value and arr[i] > arr[j]:
inv_count += 1
return inv_count
def isSolvable(puzzle) :
inv_count = getInvCount([j for sub in puzzle for j in sub])
return (inv_count % 2 == 0)
def linear(state):
return sum([1 if state[i] != goal[i] else 0 for i in range(9)])
@memoize
def manhattan(state):
index_goal = coordinate(goal)
index_state = coordinate(state)
mhd = 0
for i in range(9):
for j in range(2):
mhd = abs(index_goal[i][j] - index_state[i][j]) + mhd
return mhd
@memoize
def sqrt_manhattan(state):
index_goal = coordinate(goal)
index_state = coordinate(state)
mhd = 0
for i in range(9):
for j in range(2):
mhd = (index_goal[i][j] - index_state[i][j])**2 + mhd
return math.sqrt(mhd)
@memoize
def max_heuristic(state):
score1 = manhattan(state)
score2 = linear(state)
return max(score1, score2)
class PriorityQueueElmt:
def __init__(self,val,e):
self.val = val
self.e = e
def __lt__(self,other):
return self.val < other.val
def value(self):
return self.val
def elem(self):
return self.e
class Queue:
def __init__(self):
pass
def extend(self, items):
for item in items: self.append(item)
class PriorityQueue(Queue):
def __init__(self, order=min, f=None):
self.A=[]
self.order=order
self.f=f
def append(self, item):
queueElmt = PriorityQueueElmt(self.f(item),item)
bisect.insort(self.A, queueElmt)
def __len__(self):
return len(self.A)
def pop(self):
if self.order == min:
return self.A.pop(0).elem()
else:
return self.A.pop().elem()
# Heuristics for 8 Puzzle Problem
class Problem:
def __init__(self, initial, goal=None):
self.initial = initial; self.goal = goal
def successor(self, state):
reachable = []
def get_key(val):
for key, value in index_state.items():
if val == value:
return key
return -1
def candidate(state, Position):
state = state.copy()
zero_index = state.index(0)
swap_index = state.index(get_key(Position))
state[zero_index], state[swap_index] = state[swap_index], state[zero_index]
return state
index_state = coordinate(state)
zero_position = index_state[0]
move_pair = {"left":[zero_position[0], zero_position[1] - 1],
"right":[zero_position[0], zero_position[1] + 1],
"up":[zero_position[0] - 1, zero_position[1]],
"down":[zero_position[0] + 1, zero_position[1]]
}
for action, position in move_pair.items():
#print(action, position)
if get_key(position) != -1:
reachable.append((action, candidate(state, position)))
#print(reachable)
return reachable
def goal_test(self, state):
return state == self.goal
def path_cost(self, c, state1, action, state2):
return c + 1
def value(self):
abstract
class Node:
def __init__(self, state, parent=None, action=None, path_cost=0, depth =0):
self.parent = parent
if parent:
self.depth = parent.depth + 1
else:
self.depth = 0
self.path_cost = path_cost
self.state = state
if action:
self.action = action
else: self.action = "init"
def __repr__(self):
return "Node state:\n " + str(np.array(self.state).reshape(3,3)) +"\n -> action: " + self.action + "\n -> depth: " + str(self.depth)
def path(self):
x, result = self, [self]
while x.parent:
result.append(x.parent)
x = x.parent
return result
def expand(self, problem):
for (act,n) in problem.successor(self.state):
if n not in [node.state for node in self.path()]:
yield Node(n, self, act,
problem.path_cost(self.path_cost, self.state, act, n))
def graph_search(problem, fringe):
closed = {}
fringe.append(Node(problem.initial,depth=0))
while fringe:
node = fringe.pop()
if problem.goal_test(node.state):
return node
if str(node.state) not in closed:
closed[str(node.state)] = True
fringe.extend(node.expand(problem))
return None
def best_first_graph_search(problem, f):
return graph_search(problem, PriorityQueue(min, f))
def astar_search(problem, h = None):
h = h or problem.h
def f(n):
return max(getattr(n, 'f', -infinity), n.path_cost + h(n.state))
return best_first_graph_search(problem, f)
def print_path(path, method):
print("*" * 30)
print("\nPath: (%s distance)" % method)
for i in range(len(path)-1, -1, -1):
print("-" * 15)
print(path[i])
goal = [1, 2, 3, 4, 5, 6, 7, 8, 0]
# Solving the puzzle
puzzle = [7, 2, 4, 5, 0, 6, 8, 3, 1]
if(isSolvable(np.array(puzzle).reshape(3,3))): # even true
# checks whether the initialized configuration is solvable or not
print("Solvable!")
problem = Problem(puzzle,goal)
path = astar_search(problem, manhattan).path()
print_path(path, "manhattan")
path = astar_search(problem, linear).path()
print_path(path, "linear")
path = astar_search(problem, sqrt_manhattan).path()
print_path(path, "sqrt_manhattan")
path = astar_search(problem, max_heuristic).path()
print_path(path, "max_heuristic")
else :
print("Not Solvable!") # non-even false
TypeError Traceback (most recent call last)
<ipython-input-124-2a60ddc8c009> in <module>
9 problem = Problem(puzzle,goal)
10
---> 11 path = astar_search(problem, manhattan).path()
12 print_path(path, "manhattan")
13
<ipython-input-123-caa97275712e> in astar_search(problem, h)
18 def f(n):
19 return max(getattr(n, 'f', -infinity), n.path_cost + h(n.state))
---> 20 return best_first_graph_search(problem, f)
21
22 def print_path(path, method):
<ipython-input-123-caa97275712e> in best_first_graph_search(problem, f)
12
13 def best_first_graph_search(problem, f):
---> 14 return graph_search(problem, PriorityQueue(min, f))
15
16 def astar_search(problem, h = None):
<ipython-input-123-caa97275712e> in graph_search(problem, fringe)
8 if str(node.state) not in closed:
9 closed[str(node.state)] = True
---> 10 fringe.extend(node.expand(problem))
11 return None
12
<ipython-input-121-e5a968bd54f0> in extend(self, items)
18
19 def extend(self, items):
---> 20 for item in items: self.append(item)
21
22 class PriorityQueue(Queue):
<ipython-input-122-db21613469b9> in expand(self, problem)
69
70 def expand(self, problem):
---> 71 for (act,n) in problem.successor(self.state):
72 if n not in [node.state for node in self.path()]:
73 yield Node(n, self, act,
TypeError: cannot unpack non-iterable int object
I got some error messages, how can I fix it?
有一条错误信息,你在错误信息中得到的代码片段是堆栈跟踪,这可能有助于你了解执行是如何到达错误发生的最后一点的。在这种情况下,这并不那么重要。错误的本质是这样的:
for (act,n) in problem.successor(self.state)
TypeError: cannot unpack non-iterable int object
所以这意味着 successor
方法 return 编辑了 int
而不是列表。
查看 successor
的代码,我注意到它打算 return 一个名为 reachable
的列表,但中间有一个 return
语句代码的最大部分未执行(所谓的“死代码”):
return state
这条语句放在什么地方是没有意义的。这似乎是一个缩进问题:return
属于它上面的函数内部,如下所示:
def candidate(state, Position):
state = state.copy()
zero_index = state.index(0)
swap_index = state.index(get_key(Position))
state[zero_index], state[swap_index] = state[swap_index], state[zero_index]
return state # <-- indentation!