8具有重复节点的平铺解算器-Python

8具有重复节点的平铺解算器-Python,python,depth-first-search,breadth-first-search,heuristics,solver,Python,Depth First Search,Breadth First Search,Heuristics,Solver,我正在尝试使用BFS搜索、DFS、贪婪和A*等技术来解决8tile难题,使用曼哈顿距离作为启发式解决方案 问题是,虽然我可以解决很多问题,但问题在于一些谜题,我在扩展父节点时得到的子节点可能已经在较旧的节点中 我不知道我是否能够很好地解释我自己,但我的主要问题是,我试图查看我创建的新节点是否已经在旧节点上 有了这个问题,我通常会进入深度9,然后我的程序就不能前进或给出解决方案 我的一个想法是使用代码: if node in prev: continue prev.append(node)

我正在尝试使用BFS搜索、DFS、贪婪和A*等技术来解决8tile难题,使用曼哈顿距离作为启发式解决方案

问题是,虽然我可以解决很多问题,但问题在于一些谜题,我在扩展父节点时得到的子节点可能已经在较旧的节点中

我不知道我是否能够很好地解释我自己,但我的主要问题是,我试图查看我创建的新节点是否已经在旧节点上

有了这个问题,我通常会进入深度9,然后我的程序就不能前进或给出解决方案

我的一个想法是使用代码:

if node in prev:
    continue
prev.append(node)
但我想我走错了方向

我在python上做这件事,下面是我的代码,以防有人能帮助我

#!/usr/bin/python

import sys
import copy


class Board:
    def __init__(self, matrix, whitepos=None):
        self.matrix = matrix
        self.whitepos = whitepos
        if not whitepos:
            for y in xrange(3):
                for x in xrange(3):
                    if board[y][x] == 0:
                        self.whitepos = (x, y)


def is_final_state(board):
    final = [[1, 2, 3], [8, 0, 4], [7, 6, 5]]
    for y in xrange(3):
        for x in xrange(3):
            if board.matrix[y][x] != final[y][x]:
                return False
    return True


def get_whitepos(board):
    return board.whitepos


def move(board, x, y, dx, dy):
    b = copy.deepcopy(board.matrix)
    b[y][x] = b[y + dy][x + dx]
    b[y + dy][x + dx] = 0
    return Board(b, (x + dx, y + dy))


def manhattan_heur(board):
    finalpos = [(1, 1), (0, 0), (1, 0), (2, 0), (2, 1), (2, 2), (1, 2), (0, 2),
                (0, 1)]
    cost = 0
    for y in xrange(3):
        for x in xrange(3):
            t = board.matrix[y][x]
            xf, yf = finalpos[t]
            cost += abs(xf - x) + abs(yf - y)
    return cost


def wrongplace_heur(board):
    finalpos = [(1, 1), (0, 0), (1, 0), (2, 0), (2, 1), (2, 2), (1, 2), (0, 2),
                (0, 1)]
    cost = 0
    for y in xrange(3):
        for x in xrange(3):
            t = board.matrix[y][x]
            if finalpos[t] != (x, y):
                cost += 1
    return cost


def heuristic(board):
    return manhattan_heur(board)


class Node:
    def __init__(self, board, parent):
        self.state = board
        self.parent = parent
        if not parent:
            self.g = 0
        else:
            self.g = parent.g + 1
        self.h = heuristic(board)

    def test_goal(self):
        return is_final_state(self.state)

    def expand(self):
        children = []
        b = self.state
        x, y = get_whitepos(b)
        if x > 0:
            children.append(Node(move(b, x, y, -1, 0), self))
        if x < 2:
            children.append(Node(move(b, x, y, +1, 0), self))
        if y > 0:
            children.append(Node(move(b, x, y, 0, -1), self))
        if y < 2:
            children.append(Node(move(b, x, y, 0, +1), self))
        return children


class Solution:
    def __init__(self, node, mem_needed, steps):
        self.node = node
        self.mem_needed = mem_needed
        self.iterations = steps

    def inc(self, other):
        self.node = other.node
        self.mem_needed = max(self.mem_needed, other.mem_needed)
        self.iterations += other.iterations


def search(board, queue_fn, queue_arg=None):
    max_nodes = 1
    steps = 0
    nodes = [Node(Board(board), None)]
    prev = []
    depth = 0
    while nodes:
        node = nodes.pop(0)

        if node.g > depth:
            depth = node.g
            print depth

        if node in prev:
            continue
        prev.append(node)

        if node.test_goal():
            return Solution(node, max_nodes, steps)
        new_nodes = node.expand()
        nodes = queue_fn(nodes, new_nodes, queue_arg)

        max_nodes = max(max_nodes, len(nodes))
        steps += 1
    return Solution(None, max_nodes, steps)


def fifo_queue(nodes, new_nodes, _):
    nodes.extend(new_nodes)
    return nodes


def bl_search(board):
    return search(board, fifo_queue)


def lifo_queue(nodes, new_nodes, _):
    new_nodes.extend(nodes)
    return new_nodes


def dfs_search(board):
    return search(board, lifo_queue)


def bpl_queue(nodes, new_nodes, max_depth):
    def f(n):
        return n.g <= max_depth

    new_nodes = filter(f, new_nodes)
    new_nodes.extend(nodes)
    return new_nodes


def bpi_search(board):
    solution = Solution(None, 0, 0)
    for max_depth in xrange(0, sys.maxint):
        sol = search(board, bpl_queue, max_depth)
        solution.inc(sol)
        if solution.node:
            return solution


def sort_queue(nodes, new_nodes, cmp):
    nodes.extend(new_nodes)
    nodes.sort(cmp)
    return nodes


def guloso2_search(board):
    def cmp(n1, n2):
        return n1.h - n2.h

    return search(board, sort_queue, cmp)


def astar_search(board):
    def cmp(n1, n2):
        return (n1.g + n1.h) - (n2.g + n2.h)

    return search(board, sort_queue, cmp)


def print_solution(search, sol):
    print
    print "*", search
    node = sol.node
    if node:
        print "moves:", node.g
        while node:
            print "\t", node.state.matrix
            node = node.parent
    else:
        print "no solution found"
    print "nodes needed:", sol.mem_needed
    print "iterations:  ", sol.iterations


board = [[6, 5, 7], [2, 0, 1], [8, 4, 3]]

print_solution("bl", bl_search(board))
print_solution("dfs", dfs_search(board))
print_solution("bpi", bpi_search(board))
print_solution("guloso2", guloso2_search(board))
print_solution("astar", astar_search(board))
#/usr/bin/python
导入系统
导入副本
班级委员会:
def u u init u u;(self、matrix、whitepos=None):
self.matrix=矩阵
self.whitepos=whitepos
如果不是白色POS:
对于X范围内的y(3):
对于x范围内的x(3):
如果电路板[y][x]==0:
self.whitepos=(x,y)
def为最终状态(板):
final=[[1,2,3],[8,0,4],[7,6,5]]
对于X范围内的y(3):
对于x范围内的x(3):
if board.matrix[y][x]!=最终[y][x]:
返回错误
返回真值
def get_白板:
返回板.whitepos
def移动(板,x,y,dx,dy):
b=副本.deepcopy(board.matrix)
b[y][x]=b[y+dy][x+dx]
b[y+dy][x+dx]=0
返回板(b,(x+dx,y+dy))
董事会:
最终结果=[(1,1),(0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),
(0, 1)]
成本=0
对于X范围内的y(3):
对于x范围内的x(3):
t=板.矩阵[y][x]
xf,yf=finalpos[t]
成本+=abs(xf-x)+abs(yf-y)
退货成本
def错误放置(板):
最终结果=[(1,1),(0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),
(0, 1)]
成本=0
对于X范围内的y(3):
对于x范围内的x(3):
t=板.矩阵[y][x]
如果最终结果[t]!=(x,y):
成本+=1
退货成本
def(电路板):
返回曼哈顿(董事会)
类节点:
定义初始化(自身、板、父级):
self.state=board
self.parent=parent
如果不是家长:
self.g=0
其他:
self.g=parent.g+1
self.h=启发式(电路板)
def测试_目标(自我):
返回为最终状态(self.state)
def扩展(自):
儿童=[]
b=自我状态
x、 y=获取(b)的位置
如果x>0:
附加(节点(移动(b,x,y,-1,0),self))
如果x<2:
附加(节点(移动(b,x,y,+1,0),self))
如果y>0:
附加(节点(移动(b,x,y,0,-1),self))
如果y<2:
附加(节点(移动(b,x,y,0,+1),self))
返回儿童
类解决方案:
定义初始化(自身、节点、需要的成员、步骤):
self.node=节点
self.mem_needed=mem_needed
self.iterations=步骤
def公司(自身、其他):
self.node=other.node
self.mem_needed=max(self.mem_needed,other.mem_needed)
self.iterations+=其他.iterations
def搜索(板、队列、队列参数=无):
最大节点数=1
步数=0
节点=[节点(板,无)]
prev=[]
深度=0
而节点:
node=nodes.pop(0)
如果node.g>深度:
深度=节点.g
打印深度
如果节点位于上一个:
持续
上一个追加(节点)
if node.test_goal():
返回解决方案(节点、最大节点、步骤)
new_nodes=node.expand()
节点=队列(节点、新节点、队列参数)
max_节点=max(max_节点,len(节点))
步数+=1
返回解决方案(无、最大节点、步骤)
def fifo_队列(节点、新_节点、u):
节点。扩展(新节点)
返回节点
def bl_搜索(板):
返回搜索(板、先进先出队列)
def后进先出队列(节点、新节点、后进先出):
新节点。扩展(节点)
返回新的_节点
def dfs_搜索(板):
返回搜索(板、后进先出队列)
def bpl_队列(节点、新节点、最大深度):
def f(n):

return n.g看起来您的操作方式是正确的,但是您需要在Node类中定义
\uuuu eq\uuu
\uu ne\uuu
方法;否则,prev中的
节点将始终返回
False
,因为Python不知道如何将
节点
与列表中的项目进行比较。有关比较如何在用户定义类型上工作的更多信息,请查看

我抓取了你的代码,添加了两个(非常幼稚的)方法来进行平等性检查,它似乎不再挂起。还值得注意的是,您的类应该从基
对象继承(见下文)。以下是我(在上下文中)所做的更改:


希望这有帮助

八个空格对于Python编程来说有点不规则。如果您切换到四个空格,人们可能会觉得更容易阅读(也更容易回答)。我在发布代码时遇到了问题,因为这是我第一次在这里发布代码,这就是为什么它带有8个空格。为您重新格式化它,并替换一些奇怪的
如果x==None:
如果x!=无:
如果不是x:
如果是x:
。谢谢。我必须多练习一下代码格式。我试图做一些比较方法,但我开始对使用parentNode=Node(Node.state,Node.parent)和类似的行感到困惑,我的程序开始出现很多错误。xD在我更加沮丧之前,我想寻求帮助,看看是否有一种简单的方法可以让重复节点真正消失?我复制了他的代码并添加了naiveclass Board(object): def __init__(self, matrix, whitepos=None): self.matrix = matrix self.whitepos = whitepos if not whitepos: for y in xrange(3): for x in xrange(3): if board[y][x] == 0: self.whitepos = (x, y) def __eq__(self, o): # Note that comparing whitepos is not strictly necessary; but I left # it in as a safety measure in case the board state gets corrupted. # If speed becomes an issue, take it out. return (self.matrix, self.whitepos) == (o.matrix, o.whitepos) class Node(object): def __init__(self, board, parent): self.state = board self.parent = parent if not parent: self.g = 0 else: self.g = parent.g + 1 self.h = heuristic(board) def test_goal(self): return is_final_state(self.state) def expand(self): children = [] b = self.state x, y = get_whitepos(b) if x > 0: children.append(Node(move(b, x, y, -1, 0), self)) if x < 2: children.append(Node(move(b, x, y, +1, 0), self)) if y > 0: children.append(Node(move(b, x, y, 0, -1), self)) if y < 2: children.append(Node(move(b, x, y, 0, +1), self)) return children def __eq__(self, o): # Note that you don't have to compare parents, since your goal # is to eliminate ANY nodes with the same position. return self.state == o.state class Solution(object): def __init__(self, node, mem_needed, steps): self.node = node self.mem_needed = mem_needed self.iterations = steps def inc(self, other): self.node = other.node self.mem_needed = max(self.mem_needed, other.mem_needed) self.iterations += other.iterations #... print_solution("bl", bl_search(board)) # I commented out all but the first search to avoid cluttering up the output.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

* bl
moves: 20
    [[1, 2, 3], [8, 0, 4], [7, 6, 5]]
    [[1, 2, 3], [8, 6, 4], [7, 0, 5]]
    [[1, 2, 3], [8, 6, 4], [0, 7, 5]]
    [[1, 2, 3], [0, 6, 4], [8, 7, 5]]
    [[1, 2, 3], [6, 0, 4], [8, 7, 5]]
    [[1, 0, 3], [6, 2, 4], [8, 7, 5]]
    [[0, 1, 3], [6, 2, 4], [8, 7, 5]]
    [[6, 1, 3], [0, 2, 4], [8, 7, 5]]
    [[6, 1, 3], [2, 0, 4], [8, 7, 5]]
    [[6, 1, 3], [2, 7, 4], [8, 0, 5]]
    [[6, 1, 3], [2, 7, 4], [8, 5, 0]]
    [[6, 1, 3], [2, 7, 0], [8, 5, 4]]
    [[6, 1, 0], [2, 7, 3], [8, 5, 4]]
    [[6, 0, 1], [2, 7, 3], [8, 5, 4]]
    [[6, 7, 1], [2, 0, 3], [8, 5, 4]]
    [[6, 7, 1], [2, 5, 3], [8, 0, 4]]
    [[6, 7, 1], [2, 5, 3], [8, 4, 0]]
    [[6, 7, 1], [2, 5, 0], [8, 4, 3]]
    [[6, 7, 0], [2, 5, 1], [8, 4, 3]]
    [[6, 0, 7], [2, 5, 1], [8, 4, 3]]
    [[6, 5, 7], [2, 0, 1], [8, 4, 3]]
nodes needed: 44282
iterations:   59930