【问题标题】:N Puzzle in PythonPython中的N拼图
【发布时间】:2017-02-19 17:36:04
【问题描述】:

我正在尝试使用 Python 中的广度优先搜索来构建 N-Puzzle 问题的解决方案。

如果除零之外的所有数字都按顺序排列,我的解决方案很擅长找到答案。例如

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)]"""

【问题讨论】:

  • 它失败了,因为你还没有定义bfsupdownleftright,可能还有其他一些东西。
  • 对不起,我错过了一些我的代码,现在将更新。 @保罗汉金
  • 你是如何测试up的?我相信updown 都不正确。

标签: python algorithm tree artificial-intelligence breadth-first-search


【解决方案1】:

如果您通过在UP, DOWN, LEFT, RIGHT 顺序中移动space 来处理节点(状态)的邻居(子节点),则从初始状态1,2,5,3,4,0,6,7,8 开始的8-puzzlebfs 的解决方案将是如下所示(您可以查看它与您的解决方案的不同之处):

path_to_goal: ['Up', 'Left', 'Left']
cost_of_path: 3

您可能需要参考此https://sandipanweb.wordpress.com/2017/03/16/using-uninformed-informed-search-algorithms-to-solve-8-puzzle-n-puzzle/?frame-nonce=9e97a821bc 了解更多详情。

【讨论】:

    【解决方案2】:

    up 中的这个条件永远不会成立:if n**2 &lt; i &lt;= (n**2 - n)。 而down 中的这个条件差了一个:if i &gt; n

    您的其余代码是否正确尚不清楚,但您需要先调试电路板表示和操作代码的基础。

    在您的空间移动代码中,我个人会将您的索引转换为xy 坐标:

    x, y = i % n, i // n
    

    然后你可以更自然地测试:x&gt;0 左,x&lt;n-1 右,y&lt;n-1 上,y&gt;0 下。

    【讨论】:

      猜你喜欢
      • 2019-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-26
      • 2023-04-07
      • 1970-01-01
      • 2020-10-30
      • 1970-01-01
      相关资源
      最近更新 更多