PythonBFS DFS UCS 贪婪 A*算法解决八数码问题
为了完成人工智能与机器学习实验报告 。。。
本文只需要用到 四个 包
-
#import 相关包
-
import copy
-
import numpy as np
-
import random
-
from datetime import datetime
逆序数判断八数码问题是否有解
-
#逆序数判断:
-
def solution_or_not(initial,goal):
-
initial = initial.replace(" ","") #剔除字符串内空格
-
goal = goal.replace(" ","")
-
init_num = 0 #initial逆序数
-
goal_num = 0 #goal逆序数
-
-
for i in range(1,9): #计算initial逆序数
-
temp = 0
-
for j in range(0,i):
-
if initial[j] > initial[i] and initial[i]!='0':
-
temp=temp 1
-
init_num = init_num temp
-
-
for i in range(1,9): #计算goal逆序数
-
temp = 0
-
for j in range(0,i):
-
if goal[j] > goal[i] and goal[i]!='0':
-
temp=temp 1
-
goal_num = goal_num temp
-
-
if(init_num%2) != (goal_num%2): #判断两逆序数的奇偶性是否相等
-
return 0
-
else:
-
return 1
为了解决八数码问题(移动和判断往哪里移动)需要的一些函数
-
#寻找target的位置
-
def find_local(arr,target): #arr是节点的list,target是寻找的目标
-
for i in arr:
-
for j in i:
-
if j == target:
-
return arr.index(i),i.index(j) #返回target的下标
-
-
#交换位置,并获得子节点
-
def get_child(arr,e):
-
arr_new = copy.deepcopy(arr) #深拷贝,复制一份新的节点
-
r, c = find_local(arr_new,'0') #寻找0的位置的坐标
-
r1, c1 = find_local(arr_new,e) #寻找可交换的位置的坐标
-
-
#交换位置
-
arr_new[r][c], arr_new[r1][c1] = arr_new[r1][c1], arr_new[r][c]
-
return arr_new
-
-
#获取可与0交换的元素
-
def get_elements(arr):
-
r,c =find_local(arr,'0') #寻找0的的下标
-
elements=[]
-
if r > 0:
-
elements.append(arr[r - 1][c]) # 上边的数
-
if r < 2:
-
elements.append(arr[r 1][c]) # 下边的数
-
if c > 0:
-
elements.append(arr[r][c - 1]) # 左边的数
-
if c < 2:
-
elements.append(arr[r][c 1]) # 右边的数
-
return elements
-
-
#曼哈顿距离
-
def mhd_distance(arr1,arr2):
-
distance = []
-
for i in arr1:
-
for j in i:
-
loc1 = find_local(arr1,j)
-
loc2 = find_local(arr2,j)
-
distance.append(abs(loc1[0] loc2[0]) abs(loc1[1] - loc2[1]))
-
return sum(distance)
-
-
#不在位数
-
def not_digits(arr1,arr2):
-
num=0
-
for i in range(0,2):
-
for j in range(0,2):
-
if arr1[i][j] != arr2[i][j] and arr1[i][j] != 0 and arr2[i][j]!= 0:
-
num = num 1
-
return num
创建一个节点类,用来储存每一个八数码的状态
-
#设置节点类
-
class state:
-
#state为八码数的list表示,parent为父节点
-
#deep为节点深度,cost为节点代价
-
#distance为曼哈顿距离,nd_nums为不在位数
-
def __init__(self, state, parent, deep, cost ,distance ,nd_nums):
-
self.state = state
-
self.parent = parent
-
self.deep = deep
-
self.cost = cost
-
self.distance = distance
-
self.nd_nums= nd_nums
-
-
def get_children(self): #获取一层子节点
-
children=[]
-
for i in get_elements(self.state):
-
#逐个元素与0交换位置,生成子节点child
-
child = state(state=get_child(self.state,i),
-
parent = self,
-
deep = self.deep 1,
-
cost = self.cost 1,
-
distance = self.distance mhd_distance(self.state,goal_arr),
-
nd_nums = not_digits(self.state,goal_arr))
-
-
#将每一个交换结果(子节点)都存入children
-
children.append(child)
-
return children
为了实现可视化输出
-
#打印最短路径
-
def best_path(n):
-
if n.parent == None:
-
return
-
else:
-
print("↑")
-
print(np.array(n.parent.state))
-
best_path(n.parent)
-
-
#画分割线
-
def draw_line():
-
print('--' * 20)
-
print('--' * 20)
-
print('--' * 20)
-
-
#整一个搜索路径:
-
def search_line(close):
-
print('搜索路径如下:')
-
for i in close[:-1]:
-
print(np.array(i.state))
-
print('↓')
-
print(np.array(close[-1].state))
将字符串输入转化为八数码
-
#将字符串转化为列表
-
def string_to_list(str):
-
str_list=list(str)
-
return [str_list[i:i 3] for i in range(0,len(str_list),3)]
广度优先搜索BFS
-
#广度优先搜索
-
def BFS(initial_arr,goal_arr):
-
open = [initial_arr]
-
close = []
-
-
while len(open) > 0: #OPEN表是否为空表
-
open_1 = [i.state for i in open] #访问open节点内的state
-
close_1 = [i.state for i in close]
-
-
n = open.pop(0) #删除OPEN队头节点,并且赋值给n
-
close.append(n) #n注入CLOSE表
-
-
if n.state == goal_arr:
-
print('最优路径如下:')
-
print(np.array(n.state)) #转换成矩阵打印最终节点
-
best_path(n)
-
break
-
else:
-
for i in n.get_children(): #添加子节点进OPEN
-
if i.state not in open_1:
-
if i.state not in close_1:
-
open.append(i)
-
-
draw_line()
-
search_line(close)
-
print('搜索步骤为',len(close) - 1)
深度优先搜索DFS
-
#深度优先搜索
-
def DFS(initial_arr,goal_arr):
-
open = [initial_arr]
-
close = []
-
# limit = eval(input('请输入要搜索的深度:'))
-
limit = 20
-
-
while len(open) > 0:
-
open_2 = [i.state for i in open]
-
close_2 = [i.state for i in close]
-
-
n = open.pop(0)
-
close.append(n)
-
-
if n.state == goal_arr:
-
print('最优路径如下:')
-
print(np.array(n.state)) #转换成矩阵打印最终节点
-
best_path(n)
-
break
-
else:
-
if n.deep < limit:
-
for i in n.get_children():
-
if i.state not in open_2:
-
if i.state not in close_2:
-
open.insert(0, i) #DFS从前端插入
-
else:
-
print('该深度下无解') #循环出去后显示无解
-
-
draw_line()
-
search_line(close)
-
print('深度为',close[-1].deep,'下的搜索步数为:',len(close) - 2)
一致代价优先搜索UCS
-
#一致代价优先搜索
-
def UCS(initial_arr,goal_arr):
-
open = [initial_arr]
-
close = []
-
-
while len(open) > 0: #OPEN表是否为空表
-
open_3 = [i.state for i in open] #访问open节点内的state
-
close_3 = [i.state for i in close]
-
-
open_4 = [i.cost for i in open] #OPEN内每个节点的cost
-
min_index = open_4.index(min(open_4))
-
-
n = open.pop(min_index) #删除OPEN队头节点,并且赋值给n
-
close.append(n) #n注入CLOSE表
-
-
if n.state == goal_arr:
-
print('最优路径如下:')
-
print(np.array(n.state)) #转换成矩阵打印最终节点
-
best_path(n)
-
break
-
else:
-
for i in n.get_children(): #添加子节点进OPEN
-
if i.state not in open_3:
-
if i.state not in close_3:
-
open.append(i)
-
-
draw_line()
-
search_line(close)
-
print('搜索步骤为',len(close) - 1, '权重为',close[-1].cost)
贪婪算法
-
#贪婪算法
-
def Greedy(initial_arr,goal_arr):
-
open = [initial_arr]
-
close = []
-
-
while len(open) > 0: #OPEN表是否为空表
-
open_1 = [i.state for i in open] #访问open节点内的state
-
close_1 = [i.state for i in close]
-
-
n = open.pop(0) #删除OPEN队头节点(此点排序后为最小距离和),并且赋值给n
-
close.append(n) #n注入CLOSE表
-
-
if n.state == goal_arr:
-
print('最优路径如下:')
-
print(np.array(n.state)) #转换成矩阵打印最终节点
-
best_path(n)
-
break
-
else:
-
for i in n.get_children(): #添加子节点进OPEN
-
if i.state not in open_1:
-
if i.state not in close_1:
-
open.insert(0,i)
-
open.sort(key = lambda x: x.distance) #按曼哈顿距离进行排序
-
-
draw_line()
-
search_line(close)
-
print('搜索步骤为',len(close) - 1,'总估价为',close[-1].distance)
A*算法-曼哈顿距离
-
#A*算法-曼哈顿距离
-
def AStar_MHT(initial_arr,goal_arr):
-
open = [initial_arr]
-
close = []
-
-
while len(open) > 0: #OPEN表是否为空表
-
open_1 = [i.state for i in open] #访问open节点内的state
-
close_1 = [i.state for i in close]
-
-
n = open.pop(0) #删除OPEN队头节点(此点排序后为最小距离和),并且赋值给n
-
close.append(n) #n注入CLOSE表
-
-
if n.state == goal_arr:
-
print('最优路径如下:')
-
print(np.array(n.state)) #转换成矩阵打印最终节点
-
best_path(n)
-
break
-
else:
-
for i in n.get_children(): #添加子节点进OPEN
-
if i.state not in open_1:
-
if i.state not in close_1:
-
open.insert(0,i)
-
open.sort(key = lambda x: x.distance x.cost) #按曼哈顿距离+cost 进行排序
-
-
draw_line()
-
search_line(close)
-
print('搜索步骤为',len(close) - 1,'总估价为',close[-1].cost close[-1].distance)
A*算法-不在位数
-
#A*算法-不在位数
-
def AStar_ND(initial_arr,goal_arr):
-
open = [initial_arr]
-
close = []
-
-
while len(open) > 0: #OPEN表是否为空表
-
open_1 = [i.state for i in open] #访问open节点内的state
-
close_1 = [i.state for i in close]
-
-
n = open.pop(0) #删除OPEN队头节点(此点排序后为最小距离和),并且赋值给n
-
close.append(n) #n注入CLOSE表
-
-
if n.state == goal_arr:
-
print('最优路径如下:')
-
print(np.array(n.state)) #转换成矩阵打印最终节点
-
best_path(n)
-
break
-
else:
-
for i in n.get_children(): #添加子节点进OPEN
-
if i.state not in open_1:
-
if i.state not in close_1:
-
open.insert(0,i)
-
open.sort(key = lambda x: x.nd_nums x.cost) #按不在位数+cost 进行排序
-
-
draw_line()
-
search_line(close)
-
print('搜索步骤为',len(close) - 1)
主函数如下
-
#主函数
-
if __name__=='__main__':
-
initial='283 104 765'
-
goal='123 804 765'
-
if solution_or_not(initial,goal):
-
goal_arr = string_to_list(goal)
-
initial_arr = state(string_to_list(initial),
-
parent=None,
-
deep=0,
-
cost=0,
-
distance=mhd_distance(string_to_list(initial),goal_arr),
-
nd_nums=not_digits(string_to_list(initial),goal_arr))
-
-
DFS(initial_arr,goal_arr) #深度优先搜索
-
BFS(initial_arr,goal_arr) #宽度优先搜索
-
UCS(initial_arr,goal_arr) #一致代价优先搜索
-
Greedy(initial_arr,goal_arr) #贪婪算法
-
AStar_MHT(initial_arr,goal_arr) #A*算法-曼哈顿距离
-
AStar_ND(initial_arr,goal_arr) #A*算法-不在位数
-
else:
-
print("从逆序数判断来看,该八数码问题无解")
-
部分运行结果如下:
将八数码随机打乱
-
#随机打乱八数码
-
def random_str(str):
-
str_list = list(str)
-
random.shuffle(str_list)
-
return ''.join(str_list)
对比两个A*算法的时间复杂度
-
#算法对比
-
if __name__=='__main__':
-
initial='283104765'
-
goal='123804765'
-
time = []
-
count = 50
-
print("A*曼哈顿距离算法:")
-
for i in range(0,count):
-
initial = random_str(initial)
-
goal = random_str(goal)
-
if solution_or_not(initial,goal):
-
goal_arr = string_to_list(goal)
-
initial_arr = state(string_to_list(initial),
-
parent=None,
-
deep=0,
-
cost=0,
-
distance=mhd_distance(string_to_list(initial),goal_arr),
-
nd_nums=not_digits(string_to_list(initial),goal_arr))
-
start = datetime.now()
-
AStar_MHT(initial_arr,goal_arr) #A*算法-曼哈顿距离
-
end = datetime.now()
-
print("第",i 1,"次迭代结束,时间为",end - start)
-
time.append(end - start)
-
else:
-
print("第",i 1,"次迭代结束,该八数码无解")
-
print('A*曼哈顿距离算法平均耗时:',np.mean(time))
-
-
initial='283104765'
-
goal='123804765'
-
time = []
-
print("A*不在为数算法:")
-
for i in range(0,count):
-
initial = random_str(initial)
-
goal = random_str(goal)
-
if solution_or_not(initial,goal):
-
goal_arr = string_to_list(goal)
-
initial_arr = state(string_to_list(initial),
-
parent=None,
-
deep=0,
-
cost=0,
-
distance=mhd_distance(string_to_list(initial),goal_arr),
-
nd_nums=not_digits(string_to_list(initial),goal_arr))
-
start = datetime.now()
-
AStar_ND(initial_arr,goal_arr) #A*算法-不在位数
-
end = datetime.now()
-
print("第",i 1,"次迭代结束,时间为",end - start)
-
time.append(end - start)
-
else:
-
print("第",i 1,"次迭代结束,该八数码无解")
-
print('A*不在位数算法平均耗时:',np.mean(time))
-
部分运行结果如下 :
八数码问题的代码基于博主AlphaJun_zero的思路做出部分修改,完善与改进
源代码下载(Jupyter)
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhfaeihf
系列文章
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13