人工智能状态空间搜索之转盘问题

1. 问题: 四个同心园盘的扇区数字如图所示,每个圆盘可以单独转动,如何设计搜索算法转动 圆盘使得 8 个扇区径向数字之和均为 12.

2.节点的初态以及终态:

    
  
 

3. 搜索策略的设计:

设计一个A 算法,利用一个评价函数来引导搜索的进行。

       f(n) = g(n) + h(n)

       f(n):评价函数,对当前节点的状态进行评估。依据此评估的结果对决定搜索的优先次序。

       g(n): 表示搜索的深度。

       h(n): 表示为扇区和不为12的扇区的个数。由于对于任意一种状态来说,转盘只需要转动三次就可以达到要求,而当前的h(n) 显然大于h*(n) 因此,不满足A*算法的要求,故此算法为A算法。

4. 代码实现。

import numpy as np


class Node:
    def __init__(self, status, parent, gValue, hValue, id, chage):  # 当一个节点被创建的时候,其父节点 g , h  的 值都应该知道
        self.status = status
        self.parent = parent
        self.gValue = gValue
        self.hValue = hValue
        self.children = []  # 用于存储基于当前节点的孩子节点
        self.fValue = gValue + hValue
        self.id = id
        self.chage = chage

    def __lt__(self, other):  # 可以根据此函数对该类型的节点进行排序
        return self.fValue < other.fValue


def computer_hValue(data):  # 获取当前状态的hValue
    rowSum = np.sum(data, axis=1)
    return sum(rowSum != 12)

def isFinish(data):
    rowSum = np.sum(data, axis=1)
    return sum(rowSum != 12)


def exchange(data, start, end):  # 列表数据的交换 在转动的循环过程中使用
    while start < end:
        data[start], data[end] = data[end], data[start]
        start += 1
        end -= 1


def getNewState(data, i, j):  # 应用规则生成新状态
    exchange(data[:, i], 0, len(data[:, i]) - j - 1)  # 前半部分进行倒置
    exchange(data[:, i], len(data[:, i]) - j, len(data) - 1)  # 后半部分进行倒置
    exchange(data[:, i], 0, len(data[:, i]) - 1)  # 所有的元素全部进行倒置


def isIn(node, Nodes):
    for n in Nodes:
        if (n.status == node.status).all():
            return n
    return None


def huisu(result):
    print("开始回溯")
    while result:
        print(result.status)
        result = result.parent


def getResult(openList, closeList):
    count = 0
    id = 0
    while openList:  # 当open 表不为空的时候
        node = openList.pop(0)  # 从open 表中取出第一个节点
        print("我的id",node.id)
        if node.parent:
            print("父节点的id",node.parent.id)
        if node.chage:
            print(node.chage)
        print("当前选中的节点", " g:", node.gValue, "h: ", node.hValue)
        print("当前节点的状态", node.status)
        if isFinish(node.status) == 0:
            print("结束", "g: ", node.gValue, "f", node.hValue)
            print(node.status)
            print("一共扩展了 ", count, "次")
            return newNode
        closeList.append(node)  # 将其加入到close表中
        count+=1
        for i in range(4):  # 一共四个圆盘 转哪个都可以
            for j in range(1, 8):  # 每一个圆盘8个数 转动的幅度一共可以产生其中不同的结果 j 表示转动的幅度
                id += 1
                newNodeStatus = node.status.copy()  # 新的节点的状态是以上上一个节点为基础产生的
                getNewState(newNodeStatus, i, j)  # 获取新节点的状态
                hValue = computer_hValue(newNodeStatus)  # 计算新节点的fValue
                change =f'转盘{i+1}顺时针旋转了{j*45}度'
                newNode = Node(newNodeStatus, node, node.gValue + 1, hValue, id, change)  # 利用新状态创建新节点 新创建的结点的g值为其父节点g值+1
                nodeOpen = isIn(newNode, openList)   # 是不是在open表中
                nodeClose = isIn(newNode, closeList)  # 是不是在close 表中
                if nodeOpen is not None:  # 表示新生成的节点在open表中
                    if nodeOpen.fValue > newNode.fValue: # 如果后面的节点最优的话 调整节点
                        nodeOpen.gValue = newNode.gValue
                        nodeOpen.fValue = newNode.fValue
                        nodeOpen.parent = newNode.parent
                if nodeClose is not None:   # 表示节点在close表中
                    if nodeClose.fValue > newNode.fValue:    # 判断节点是否需要重新加入到open表中
                        closeList.remove(nodeClose)
                        openList.append(newNode)
                if not isIn(newNode, openList) and not isIn(newNode, closeList):  # 表示新节点既不在open表也不在close表
                    openList.append(newNode)
        openList.sort()


if __name__ == '__main__':
    data = np.array([[5, 5, 2, 3], [3, 1, 2, 2], [2, 3, 1, 2], [3, 2, 3, 5], [4, 1, 4, 1], [1, 3, 5, 5], [3, 4, 3, 3],
                     [4, 2, 5, 4]])  # 数据集 表示轮盘 四列表示一个扇区的四个数字, 8行表示8个扇区
    openList = []  # +表示open表
    closeList = []  # 表示close表
    start = Node(data, None, 0, computer_hValue(data),0,None)
    openList.append(start)  # 讲初始结点加入open表
    result = getResult(openList, closeList)
    huisu(result)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值