我尝试使用Python中的广度优先搜索来构建N-Puzzle问题的解决方案。
我的解决方案是擅长找到答案,如果所有数字都是零的顺序。 e.g。
initial_state = [1,2,3,4,0,5,6,7,8]
或
initial_state = [1,2,3,4,5,6,7,0,8]
但是
失败了initial_state = [1,2,5,3,4,0,6,7,8]
请在下面找到我的实施。如果有人能指出我的逻辑中的缺陷,那就非常感激。
提前致谢!
def right(state):
items = list(state)
i = items.index(0)
n = int(math.sqrt(len(items)))
if (i+1) % n != 0:
del items[i]
items.insert(i+1, 0)
return tuple(items)
else:
pass
def left(state):
items = list(state)
i = items.index(0)
n = int(math.sqrt(len(items)))
if i % n != 0:
del items[i]
items.insert(i-1, 0)
return tuple(items)
else:
pass
def up(state):
items = list(state)
i = items.index(0)
n = int(math.sqrt(len(items)))
if n**2 < i <= (n**2 - n):
del items[i]
items.insert(i+n, 0)
return tuple(items)
else:
pass
def down(state):
items = list(state)
i = items.index(0)
n = int(math.sqrt(len(items)))
if i > n:
del items[i]
items.insert(i-n, 0)
return tuple(items)
else:
pass
class Problem(object):
def __init__(self, initial, goal=None):
self.initial = initial
self.goal = goal
self.n = len(initial)
self.size = int(math.sqrt(self.n))
self.blank = self.initial.index(0)
self.top_row = [i for i in range(self.n) if i < self.size]
self.bottom_row = [i for i in range(self.n) if self.n - (self.size) <= i < self.n]
self.left_column = [i for i in range(self.n) if i % self.size == 0]
self.right_column = [i for i in range(self.n) if (i + 1) % self.size == 0]
def actions(self):
result_list = ["UP","DOWN","LEFT","RIGHT"]
return result_list
def result(self, state, action):
if action == "RIGHT":
return right(state)
if action == "LEFT":
return left(state)
if action == "UP":
return up(state)
if action == "DOWN":
return down(state)
def goal_test(self, state):
return state == self.goal
def path_cost(self, c):
return c + 1
class Node:
def __init__(self, state, parent=None, action=None, path_cost=0):
self.state = state
self.parent = parent
self.action = action
self.path_cost = path_cost
self.depth = 0
if parent:
self.depth = parent.depth + 1
def __repr__(self):
return "<Node %s>" % (self.state,)
def __lt__(self, node):
return self.state < node.state
def expand(self, problem):
return [self.child_node(problem, action)
for action in problem.actions() if self.child_node(problem,action) is not None]
def child_node(self, problem, action):
next = problem.result(self.state, action)
if next:
return Node(next, self, action,
problem.path_cost(self.path_cost))
else:
pass
def solution(self):
return [node.action for node in self.path()[1:]]
def path(self):
node, path_back = self, []
while node:
path_back.append(node)
node = node.parent
return list(reversed(path_back))
def __eq__(self, other):
return isinstance(other, Node) and self.state == other.state
def __hash__(self):
return hash(self.state)
def bfs(problem):
node = Node(problem.initial)
frontier = deque([node])
explored = set()
while frontier:
node = frontier.pop()
explored.add(node.state)
if problem.goal_test(node.state):
return node
for child in node.expand(problem):
if child.state not in explored and child not in frontier:
frontier.append(child)
return [child for child in explored]
p = Problem((1,2,5,3,4,0,6,7,8), (0,1,2,3,4,5,6,7,8))
bfs(p)
#returns
"""[(1, 2, 5, 3, 4, 0, 6, 7, 8),
(1, 2, 0, 5, 3, 4, 6, 7, 8),
(0, 1, 2, 5, 3, 4, 6, 7, 8),
(1, 2, 5, 3, 0, 4, 6, 7, 8),
(1, 2, 5, 0, 3, 4, 6, 7, 8),
(1, 0, 2, 5, 3, 4, 6, 7, 8)]"""
答案 0 :(得分:1)
如果您通过space
按UP, DOWN, LEFT, RIGHT
顺序移动8-puzzle
来处理节点(州)的邻居(子),则bfs
与1,2,5,3,4,0,6,7,8
的解决方案一起开始初始状态path_to_goal: ['Up', 'Left', 'Left']
cost_of_path: 3
将如下所示(您可以查看它与您的解决方案的不同之处):
time()
答案 1 :(得分:0)
up
中的这种情况永远不会成立:if n**2 < i <= (n**2 - n)
。
down
中的这个条件是一个:if i > n
。
代码的其余部分是否正确尚不清楚,但您需要首先调试电路板表示和操作代码的基础知识。
在您的空间移动代码中,我个人会将您的索引转换为x
和y
坐标:
x, y = i % n, i // n
然后您可以更自然地进行测试:左侧为x>0
,右侧为x<n-1
,向上为y<n-1
,向下为y>0
。