【转】A*算法解决八数码问题

from utils import (  PriorityQueue)
import copy

infinity = float(‘inf‘)

def best_first_graph_search(problem, f):
    #定义初始节点
    node = Node(problem.initial)
    node.fvalue=f(node)
    #如果是最终结果,返回节点
    if problem.goal_test(node):
        return node
    #frotier是一个顺序队列,从小到大排列,排列比较通过f函数
    #如果order是min,最小的先出队
    frontier = PriorityQueue(min, f)
    #加入节点
    frontier.append(node)
    #print(node.fvalue)
    #展开的节点
    explored = set()
    #当栈不为空
    while frontier:
        #节点出队
        node = frontier.pop()
        #print("pop")
        #node.state.display()
        #print(node.fvalue)
        # 如果是最终结果,返回节点
        if problem.goal_test(node):
            return node
        #加入展开的节点
        explored.add(node)
        #对于出栈的子节点
        for child in node.expand(problem):
            #如果节点没有展开,并且子节点没在队中
            if child not in explored and child not in frontier:
                #子节点入队
                frontier.append(child)
                #print(child.fvalue)
                #如果子节点在队中
            elif child in frontier:
                incumbent = frontier[child]
                #如果子节点的f值小于队中节点的f值
                if f(child) < f(incumbent):
                    #删除栈中的节点,子节点入队
                    del frontier[incumbent]
                    frontier.append(child)
                    #print("change fvalue",child.state.display(),child.fvalue)
    return None
#a*算法 f=g+h
def astar_search(problem, h=None):
    h =  problem.h
    return best_first_graph_search(problem, lambda n:h(n) + n.path_cost)

class Problem(object):
    def __init__(self, initial, goal=None):
        self.initial = initial
        self.goal = goal

    def actions(self, state):
        raise NotImplementedError

    def result(self, state, action):
        raise NotImplementedError

    def goal_test(self, node):
        return (node.state.board==self.goal.board)

    def path_cost(self, c, state1, action, state2):
        return c + 1

    def value(self, state):
        raise NotImplementedError

class PuzzleProblem(Problem):
    def __init__(self, initial=None, goal=None):
        Problem.__init__(self, initial, goal)
        self.state=initial
        self.goal=goal

    def actions(self, state):
        x,y=state.location(0)
        #空格在边缘时减少活动
        action=[(0,1),(0,-1),(1,0),(-1,0)]
        if (x == 0):
            action.remove((-1,0))
        if (x == 2):
            action.remove((1, 0))
        if (y == 0):
            action.remove((0, -1))
        if (y == 2):
            action.remove((0, 1))
        return list(action)

    def result(self, state, action):
        #返回移动空格后的棋盘
        x,y=state.location(0)
        a,b=action
        n= state.board[x+a][y+b]
        s=copy.deepcopy(state)
        s.board[x+a][y+b]=0
        s.board[x][y]=n
        return s

    def path_cost( self,node):
        #展开子节点cost+1
        return node.path_cost+1

    def h(self, now):
        #当前棋盘每个格到目标棋盘的距离的平方和
        if now.state or self.goal:
            return now.state.distance(self.goal)
        else:
            return infinity

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.fvalue=0
        self.depth = 0
        if parent:
            self.depth = parent.depth + 1

    def __repr__(self):
        return "<Node {}>".format(self.state.board)

    def __lt__(self, node):
        #<运算符 队列排序使用
        return self.fvalue < node.fvalue

    def expand(self, problem):
        #展开子节点
        l = []
        for action in problem.actions(self.state):
            n=self.child_node(problem, action)
            l.append(n)
        return l

    def child_node(self, problem, action):
        next = problem.result(self.state, action)
        return Node(next, self, action,problem.path_cost(self))

    def solution(self):
        return self.path()

    def printsolution(self):
        l=self.path()
        print("selution:")
        for x in range(len(l)- 1, -1, -1):
          print(" ↓")
          l[x].state.display()

    def path(self):
        #返回父节点路径list
        node, path_back = self, []
        while node:
            path_back.append(node)
            node = node.parent
        return path_back

    def __eq__(self, other):
        #==运算符
        return isinstance(other, Node) and self.state.board==other.state.board

    def __hash__(self):
        #not in 使用 比较对象Node
        board=self.state.board
        sum=0
        for x in range(0, 3):
            for y in range(0, 3):
                number = board[x][y]
                sum=sum*10+number
        return sum

class GameState:
    def __init__(self,board=None,action=None):
        self.board=board
        self.action=action

    def display(state):
        board = state.board
        if board:
            for x in range(0, 3):
                for y in range(0, 3):
                    print(board[x][y], end=‘ ‘)
                print()

    def location(state, number):
        #数字对应坐标
        for x in range(0, 3):
            for y in range(0, 3):
                if state.board[x][y] == number:
                    return (x, y)
        return (0, 0)

    def distance(statea, stateb):
        #棋盘的距离
        board = statea.board
        s = 0
        for x in range(0, 3):
            for y in range(0, 3):
                number = board[x][y]
                a, b = stateb.location(number)
                d = (x - a) ** 2 + (y - b) ** 2
                s = s + d
        return s

"""Provides some utilities widely used by other modules"""

import bisect

class Queue:

    """Queue is an abstract class/interface. There are three types:
        Stack(): A Last In First Out Queue.
        FIFOQueue(): A First In First Out Queue.
        PriorityQueue(order, f): Queue in sorted order (default min-first).
    Each type supports the following methods and functions:
        q.append(item)  -- add an item to the queue
        q.extend(items) -- equivalent to: for item in items: q.append(item)
        q.pop()         -- return the top item from the queue
        len(q)          -- number of items in q (also q.__len())
        item in q       -- does q contain item?
    Note that isinstance(Stack(), Queue) is false, because we implement stacks
    as lists.  If Python ever gets interfaces, Queue will be an interface."""

    def __init__(self):
        raise NotImplementedError

    def extend(self, items):
        for item in items:
            self.append(item)
class PriorityQueue(Queue):

    """A queue in which the minimum (or maximum) element (as determined by f and
    order) is returned first. If order is min, the item with minimum f(x) is
    returned first; if order is max, then it is the item with maximum f(x).
    Also supports dict-like lookup.
    如果是order=MIN,最小f(x)值的item将出队"""

    def __init__(self, order=min, f=lambda x: x):
        self.A = []
        self.order = order
        self.f = f

    #按顺序插入,按f(x)从小到大
    def append(self, item):
        item.fvalue=self.f(item)
        bisect.insort(self.A,  item)
        #print("push")
        #item.state.display()

    def __len__(self):
        return len(self.A)

    #order=min输出最小 否则输出最大
    def pop(self):
        if self.order == min:
            return self.A.pop(0)
        else:
            return self.A.pop()

    def __contains__(self, item):
        return any(item.state.board == pair.state.board for pair in self.A)

    def __getitem__(self, key):
        for item in self.A:
            if item == key:
                return item

    def __delitem__(self, key):
        for item in enumerate(self.A):
            if item == key:
                self.A.pop(item)

from eightpuzzle import *

goal = GameState( [[7,1,6],
                   [5,3,2],
                   [0,8,4]] )
start = GameState([[2,0,3,],
                   [1,8,4,],
                   [7,6,5]] )
goal.action=PuzzleProblem().actions(goal)
start.action=PuzzleProblem().actions(start)
p=PuzzleProblem(start,goal)
result=astar_search(p)
result.printsolution()

  

原文地址:https://www.cnblogs.com/AHappyBird/p/9748180.html

时间: 2024-11-10 14:41:57

【转】A*算法解决八数码问题的相关文章

A*算法解决八数码问题

以下内容仅是我个人对八数码问题和A*寻路算法的理解,因为我是菜鸟一个,所以写的比较通俗.  八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的某一数字,不同棋子上标的数字不相同.棋盘上还有一个空格,与空格相邻的棋子可以移到空格中.要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤. A*算法: A*算法是一种在静态路网中求解最短路径的有效算法,通俗地讲,它不是像深度优先搜索算法和广度优先搜索算法一样的傻瓜式的埋头

人工智能作业homework2--------A*算法解决八数码

1.启发式搜索算法A 启发式搜索算法A,一般简称为A算法,是一种典型的启发式搜索算法.其基本思想是:定义一个评价函数f,对当前的搜索状态进行评估,找出一个最有希望的节点来扩展. 评价函数的形式如下: f(n)=g(n)+h(n) 其中n是被评价的节点. f(n).g(n)和h(n)各自表述什么含义呢?我们先来定义下面几个函数的含义,它们与f(n).g(n)和h(n)的差别是都带有一个"*"号. g*(n):表示从初始节点s到节点n的最短路径的耗散值: h*(n):表示从节点n到目标节点

每天刷个算法题20160526:BFS解决八数码问题(九宫格问题)

版权所有.所有权利保留. 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/51524864 为了防止思维僵化,每天刷个算法题.已经刷了几天了,现在发点代码. 我已经建了一个开源项目,每天的题目都在里面: https://github.com/Xiaofei-it/Algorithms 绝大部分算法都是我自己写的,没有参考网上通用代码.读者可能会觉得有的代码晦涩难懂,因为那是我自己的理解. 最近几天都是在写一些原来的东西

【算法】BFS+哈希解决八数码问题

15拼图已经有超过100年; 即使你不叫这个名字知道的话,你已经看到了.它被构造成具有15滑动砖,每一个从1到15上,并且所有包装成4乘4帧与一个瓦块丢失.让我们把丢失的瓷砖"X"; 拼图的目的是安排瓷砖以便它们排序为: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15× 这里唯一合法经营是交流'X'与它共享一个边缘的瓷砖之一.作为一个例子,举动下列顺序解决了一个稍微加扰难题: 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 7 8 5 6

有很多种方法来解决八数码

AI实验报告,改变了重定向.希望通过翼牛. 我很纳闷ida*然而,如何快速的双搜索.还找到了灵感不在位的基础上A*和Ida*来到慢.特别ida* 搜索31步骤甚至十几秒.我写的代码是有问题?忘记丹尼尔路过指点啊.!! ! 另外声明一下,有些东西也是看网上各路牛人的blog学来的,因为比較杂,再次无法一一列出.总之再次感谢把自己的思考的结果放到网上与大家分享的大牛们.谢谢! 八数码问题 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每一个棋子上标有1至8的某一数字.不同棋子上标的数字不同

广度优先搜索解决八数码问题

八数码简介 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每一个棋子上标有1至8的某一数字,不同棋子上标的数字不同样.棋盘上另一个空格,与空格相邻的棋子能够移到空格中.要求解决的问题是:给出一个初始状态和一个目标状态,找出一种从初始转变成目标状态的移动棋子步数最少的移动步骤.所谓问题的一个状态就是棋子在棋盘上的一种摆法.棋子移动后,状态就会发生改变.解八数码问题实际上就是找出从初始状态到达目标状态所经过的一系列中间过渡状态. 求解八数码问题要懂得的知识 1.康托展开,八数码在交换的过程

A*算法实现 八数码问题

有关八数码问题及其参考: http://wenku.baidu.com/view/87c92ef1ba0d4a7302763a29.html http://blog.csdn.net/damotiansheng/article/details/40017107 http://blog.csdn.net/wsywl/article/details/5726617 下面的代码实现可以在poj上验证其正确性,估价函数可以进行修改. poj 原题网址:http://bailian.openjudge.c

BFS解决八数码问题和狼人过河问题

1.八数码问题 问题描述: 初态: 0    1    2 3    4    5 6    7    8 如何移动交换0的位置达到终态 1    2     3 4    5     6 7    8     0 思路如下: 先将图转换为一个整数 初态:876543210终态:087654321 构造状态的数据结构 struct node{int x;int where0;} 运动规则如下 switch where0:case0: d,rcase1: d,l,rcase2: d,lcase3:

八数码问题解析

八数码的问题描述为: 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用-1来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初始状态)和目标布局,找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变. 解决八数码的方法很多,本文采用1.广度优先搜索的策略,和A星算法两种比较常用的算法思想解决此问题 广度优先搜索的策略一般可以描述为以下过程: 状态空间的一般搜索过程 OPEN表:用于存放刚生成的节点 CLOSE表:用于存放将要扩