Task1
1.迭代加深算法(盲目搜索和启发式搜索算法)完成九宫图的求解
盲目搜索算法选择了生成再测试算法,广度优先算法,迭代有界深度优先算法,为了优化,同样引入了OPEN表和CLOSE表。
这里选择的初始状态和目标状态如下,可以通过命令行输入对状态设定
init = np.array([2, 8, 3, 1, 6, 4, 7, 0, 5]).reshape(3, 3)
goal = np.array([1, 2, 3, 8, 0, 4, 7, 6, 5]).reshape(3, 3)
盲目搜索
迭代有界深度
for delimit in range(3, 100, 3):
if queue.empty():
queue.put(((-1)*start_node.depth, start_node))
visited.clear()
# 这里结合启发式搜索配置了close表,如果删除可能会出现死循环
# 或者使用random包对direction集合随机选择方向
while not queue.empty():
node = queue.get()[1] # (node.cost, node)
if np.array_equal(node.state, self.goal):
path = []
while node.parent:
path.append(node.state)
node = node.parent
path.append(node.state)
return path[::-1]
for direction in self.detect_actionset(node.state):
new_state = self.move(node.state, direction)
if str(new_state) in visited:
continue
# 5
# 迭代有界加深,cost 为目前深度*(-1)
if node.depth+1 < delimit:
new_node = Node(new_state, node, node.depth+1,
(-1)*(node.depth+1))
queue.put((node.cost, node))
queue.put((new_node.cost, new_node))
visited.add(str(new_state))
break

算法结果|结果为5步,如果初始状态不算为一步
生成再测试
如果没有引入OPEN和CLOSE表或者对移动位置进行随机,那么会出现死循环的状况。下面是采用了记录表的盲目搜索
while not queue.empty():
node = queue.get()[1] # (node.cost, node)
if np.array_equal(node.state, self.goal):
path = []
while node.parent:
path.append(node.state)
node = node.parent
path.append(node.state)
return path[::-1]
for direction in self.detect_actionset(node.state):
new_state = self.move(node.state, direction)
# 如果new_node在close表里:
if str(new_state) in visited:
continue
# 将cost改为0即可
new_node = Node(new_state, node, node.depth+1,
0)
queue.put((new_node.cost, new_node))
visited.add(str(new_state))
return None

盲目搜索结果
广度优先
while not queue.empty():
node = queue.get()[1] # (node.cost, node)
if np.array_equal(node.state, self.goal):
path = []
while node.parent:
path.append(node.state)
node = node.parent
path.append(node.state)
return path[::-1]
for direction in self.detect_actionset(node.state):
new_state = self.move(node.state, direction)
# 如果new_node在close表里:
if str(new_state) in visited:
continue
# 广度优先,cost 为目前深度
new_node = Node(new_state, node, node.depth+1,
node.depth+1)
queue.put((new_node.cost, new_node))
visited.add(str(new_state))
return None
最后结果为同迭代有界深度算法得到的最优结果(因为该问题的搜索空间较小,同时解的深度较低)
启发式搜索
这里选择了GBFS算法和算法,其中GBFS算法使用了OPEN表和CLOSE表,但是扩展节点的时候没有考虑比较新节点是否在这两个表里面,所以得到是可行解而不是最优解。也有使用了比较的GBFS算法,该问题中两个得到解一致。
GBFS算法
while not queue.empty():
node = queue.get()[1] # (node.cost, node)
if np.array_equal(node.state, self.goal):
path = []
while node.parent:
path.append(node.state)
node = node.parent
path.append(node.state)
return path[::-1]
for direction in self.detect_actionset(node.state):
new_state = self.move(node.state, direction)
# 如果new_node在close表里:
for obj in visited:
if (obj.state == new_state).any():
if node.cost - (node.depth+1+self.count_distance(new_state)) < obj.parent.cost - (node.depth+1+self.count_distance(new_state)):
visited.remove(obj)
obj.parent = node
queue.put(obj)
continue
# 1
# 启发式搜索A*,cost为目前深度+目前状态到目标状态的距离
new_node = Node(new_state, node, node.depth+1,
node.depth+1+self.count_distance(new_state))
if not queue.empty():
if if_in_priority_queue(queue, new_node):
continue
queue.put((new_node.cost, new_node))
visited.append(new_node)
最后结果也是5步完成,将对close表和open表的比较删除即可得到一般的GBFS算法
IDA*算法
if case == 3:
start_node = Node(self.start, None, 0, 0)
# 生成一个优先队列,代价(cost)越小的出列优先级越高
queue = PriorityQueue()
queue.put((self.Manhattan(self.start), start_node))
visited = set()
# IDA*
delimit1 = 4
delimit2 = 100
while not queue.empty():
node = queue.get()[1] # (node.cost, node)
if np.array_equal(node.state, self.goal):
path = []
while node.parent:
path.append(node.state)
node = node.parent
path.append(node.state)
return path[::-1]
for direction in self.detect_actionset(node.state):
new_state = self.move(node.state, direction)
# 如果new_node在close表里:
if str(new_state) in visited:
continue
# 5
# IDA*,cost为目前深度+目前状态到目标状态的距离
if node.depth+1+self.count_distance(new_state) <= delimit1:
new_node = Node(new_state, node, node.depth+1,
node.depth+1+self.count_distance(new_state))
queue.put((new_node.cost, new_node))
# visited.add(str(new_state))
else:
delimit2 = min(delimit2, node.depth+1+self.count_distance(new_state))
if queue.empty():
if 1 < delimit1 <= 200:
delimit1 = delimit2
queue.put((self.Manhattan(self.start), start_node))
elif delimit1 > 200:
return None
最后结果也是5步完成。
其他启发式函数
除了曼哈顿距离外,这里的Puzzle
类还有二范数,处于目标状态的数字个数作为距离等距离函数。在该问题中,所选用的三种距离结合GBFSA得到的结果相同,均为5步.