理论
问题描述:八数码问题是在一个3×3的方格盘上,放有1~8八个数码,余下一格为空格。空格可以与其四周的数码交换位置,从而改变八个数码在方格盘上的摆法。问题中可以使用的操作算子有四种:空格上移(up)、空格下移(down)、空格左移(left)、空格右移(right)
实验要求: 给定如下初始状态S0和目标状态Sg,要求编程实现:当输入初始状态S0后,通过搜索得到目标状态Sg,并记录下从S0到Sg的所有中间状态以及每一次状态改变所使用的操作算子。
(1)宽度优先搜索算法(伪代码):
Procedure_breadth_first_search:
Begin
open:=[Initial state]; closed:=[Initial state]; //初始化
while open ≠ [ ] do
begin
从open表中删除第一个状态,记作n;
将n放入closed表中;
if n = 目标状态, then return(success); //成功,返回求解路径
生产n的所有子状态;
从n的子状态中删除已在open或closed表中出现的状态;//避免重复搜索
将n的其余子状态,按生成的次序加入open表中已有结点的后面;
end
end
(2)深度优先算法(伪代码):
Procedure_breadth_first_search:
Begin
open:=[Initial state]; closed:=[Initial state]; d:=深度限制值; //初始化
while open ≠ [ ] do
begin
从open表中删除第一个状态,记作n;
将n放入closed表中;
if n = 目标状态, then return(success); //成功,返回求解路径
if n的深度<d, then continue; //继续向深度方向搜索
生产n的所有子状态;
从n的子状态中删除已在open或closed表中出现的状态;//避免重复搜索
将n的其余子状态,按生成的次序加入open表中已有结点的前面;
end
end
代码
宽度优先搜索算法 (python代码)
import numpy as np
import copy
class test:
def __init__(self,initial,goals):
self.length = int(math.sqrt(len(initial)))
self.initial=np.reshape(initial,(self.length,self.length))
self.goals=np.reshape(goals,(self.length,self.length))
##初始化程序
self.open_=[self.initial]
self.close_=[]
#展示数据函数
def __show_data(self,a):
for i in a:
print(i)
#移动函数
def __move(self,n,postion,row,col):
if postion =="left":
n[row,col] , n[row,col-1] = n[row,col-1], n[row,col]
elif postion == "right":
n[row,col] , n[row,col+1] = n[row,col+1], n[row,col]
elif postion == "up":
n[row,col] , n[row-1,col] = n[row-1,col], n[row,col]
elif postion == "down":
n[row,col] , n[row+1,col] = n[row+1,col], n[row,col]
return n
def __ifexists(self,three_result,close,open_):
for i in range(len(close)):
if (three_result == close[i]).all():
#print("在close表中有重复")
return True
for i in range(len(open_)):
if (three_result == open_[i]).all():
#print("在open表中有重复")
return True
return False
def find_do(self):
flag = 0
#print(self.open_)
while self.open_:
flag = flag+1
#初始化算子
direction=['up', 'down', 'right', 'left']
#从open表中删除第一个状态并放入close表中
n = self.open_.pop(0)
self.close_.append(n)
#print(n)
#print(self.initial)
#print(n==b)
#如果n为目标状态则返回求解路径
'''
np.all所有都是true才能是true
np.any一个是true就是true
'''
#print(n)
#print(self.goals)
if (n == self.goals).all():
print("展示搜索到的目标值")
self.__show_data(n)
print("----------------------------------找到目标值啦-----------------------------------")
break
#生产n的所有子状态,并加入到open表后方
postion = np.where(n == 0)
#print(postion)
#print("aa")
i = postion[0]
j = postion[1]
length_down=n.shape[0]
length_right=n.shape[1]
#清除左操作
if i==0:
direction.remove("up")
#清除上操作
if j==0:
direction.remove("left")
#清除下操作
if i == length_down-1:
direction.remove("down")
#清除右操作
if j == length_right-1:
direction.remove("right")
#print(direction)
#找到子状态
for p in range(len(direction)):
copy_n = copy.deepcopy(n)
three_result = self.__move(copy_n,direction[p],i,j)
#print(three_result)
#判断是否存在于close表
if (self.__ifexists(three_result,self.close_,self.open_)):
#直接跳出此次循环 不加入open表
continue
self.open_.append(three_result)
print("完成第"+str(flag)+"次查找,此轮中间项为:\n",n)
##初始化状态
a=[0,1,3,4,2,5,7,8,6]
b=[4,1,3,7,0,5,8,2,6]
#初始化类
test1 = test(a,b)
test1.find_do()
深度优先算法(python代码)
import numpy as np
import copy
class Node:
def __init__(self,data,level):
self.data=data
self.level=level
class test1:
def __init__(self,initial,goals):
self.initial=Node(np.reshape(initial,(3,3)),0)
self.goals=Node(np.reshape(goals,(3,3)),0)
##初始化程序
self.open_=[self.initial]
self.close_=[]
self.b=15
#展示数据函数
def __show_data(self,a):
for i in a.data:
print(i)
#移动函数
def __move(self,n,postion,row,col):
if postion =="left":
n[row,col] , n[row,col-1] = n[row,col-1], n[row,col]
elif postion == "right":
n[row,col] , n[row,col+1] = n[row,col+1], n[row,col]
elif postion == "up":
n[row,col] , n[row-1,col] = n[row-1,col], n[row,col]
elif postion == "down":
n[row,col] , n[row+1,col] = n[row+1,col], n[row,col]
return n
def __ifexists(self,three_result,close,open_):
for i in range(len(close)):
if (three_result == close[i].data).all():
#print("在close表中有重复")
return True
for i in range(len(open_)):
if (three_result == open_[i].data).all():
#print("在open表中有重复")
return True
return False
def find_do(self):
#遍历个数
flag = 0
#level
level=1
while self.open_:
flag = flag+1
#初始化算子
direction=['up', 'down', 'right', 'left']
#从open表中删除第一个状态并放入close表中
n = self.open_.pop(0)
self.close_.append(n)
#print(n)
#print(self.initial)
#print(n==b)
#如果n为目标状态则返回求解路径
'''
np.all所有都是true才能是true
np.any一个是true就是true
'''
#print(n.data)
#print(self.goals)
if (n.data == self.goals.data).all():
print("展示搜索到的目标值")
self.__show_data(n)
print("----------------------------------找到目标值啦-----------------------------------")
break
#生产n的所有子状态,并加入到open表后方
postion = np.where(n.data == 0)
i = postion[0]
j = postion[1]
length_down=n.data.shape[0]
length_right=n.data.shape[1]
#清除左操作
if i==0:
direction.remove("up")
#清除上操作
if j==0:
direction.remove("left")
#清除下操作
if i == length_down-1:
direction.remove("down")
#清除右操作
if j == length_right-1:
direction.remove("right")
if n.level>=self.b:
continue
#print(direction)
# level = level+1
#找到子状态
for p in range(len(direction)):
copy_n = copy.deepcopy(n)
three_result = self.__move(copy_n.data,direction[p],i,j)
#print(three_result)
#判断是否存在于close表
if (self.__ifexists(three_result,self.close_,self.open_)):
#直接跳出此次循环 不加入open表
continue
self.open_.insert(0,Node(three_result,n.level+1))
print("完成第"+str(flag)+"次查找,此轮中间项为:\n",n.data)
print("层数",n.level)
#print("open表第一个数的内容",self.open_[0].data)
# print("open表第一个数的内容",self.open_[0].data)
# print("open表第一个数的level",self.open_[0].level)
# print("open表第二个数的内容",self.open_[1].data)
# print("open表第一个数的level",self.open_[0].level)
# if flag==3:
# break
##初始化状态
a=[0,1,3,4,2,5,7,8,6]
b=[4,1,3,7,0,5,8,2,6]
#初始化类
test1 = test1(a,b)
test1.find_do()