描述
算法
任務
解決方案(Python)
class pos:
def __init__(self,x,y):
self.x = x
self.y = y
import random
from copy import deepcopy
l = [i for i in range(16)]
std = [l[:4],l[4:8],l[8:12],l[12:16]]
stdspace = pos(0,0)
class node:
def __init__(self,puzzle = 0,space = 0):#初始化
if puzzle==0 and space==0:
l = [i for i in range(1,16)]
l.append(0)
std = [l[:4],l[4:8],l[8:12],l[12:16]]
stdspace = pos(3,3)
self.puzzle = std
self.space = stdspace
else:
self.puzzle = puzzle
self.space = space
def shuffle(self):#隨機產生一個15pullze問題的初始狀態
for i in range(100):
sp = self.space;
d = [pos(sp.x-1,sp.y),pos(sp.x+1,sp.y),pos(sp.x,sp.y+1),pos(sp.x,sp.y-1)]
d = [p for p in d if 0<=p.x<4 and 0<=p.y<4]
ran = random.choice(d)
x,y = ran.x,ran.y
self.puzzle[x][y],self.puzzle[self.space.x][self.space.y]=\
self.puzzle[self.space.x][self.space.y],self.puzzle[x][y]
self.space = pos(x,y)
def successors(self):
sp = self.space;
d = [pos(sp.x-1,sp.y),pos(sp.x+1,sp.y),pos(sp.x,sp.y+1),pos(sp.x,sp.y-1)]
d = [p for p in d if 0<=p.x<4 and 0<=p.y<4]
res = []
for move in d:
newpuz = [[num for num in row] for row in self.puzzle]
newpuz[move.x][move.y],newpuz[sp.x][sp.y]=\
newpuz[sp.x][sp.y],newpuz[move.x][move.y]
res.append(node(newpuz,move))
return sorted(res,key=lambda x:h(x))
def __eq__(self,other):
return other.puzzle==self.puzzle
#設計計算h(n)估算距離的函數
dic = {}
num = 1
for i in range(4):
for j in range(4):
dic[num] = (i, j)
num += 1
def h(n):
n.puzzle
dist = 0
for i in range(4):
for j in range(4):
if (n.puzzle[i][j]==0):continue
x = dic[n.puzzle[i][j]][0]
y = dic[n.puzzle[i][j]][1]
dist+=abs(x-i)+abs(y-j)
return dist
#設計計算h(n)估算距離的函數
dic = {}
num = 1
for i in range(4):
for j in range(4):
dic[num] = (i, j)
num += 1
def h(n):
n.puzzle
dist = 0
for i in range(4):
for j in range(4):
if (n.puzzle[i][j]==0):continue
x = dic[n.puzzle[i][j]][0]
y = dic[n.puzzle[i][j]][1]
dist+=abs(x-i)+abs(y-j)
return dist
#設計goal test函數
def is_goal(n):
p = n.puzzle
for i in range(4):
for j in range(4):
if p[i][j]==0:continue
x = dic[p[i][j]][0]
y = dic[p[i][j]][1]
if x!=i or y!=j:
return False
return True
path = []#路徑向量
found = -12345#尋找標誌
inf = 9999999
visited = {}
def encode(n):
#把n編碼爲便於記錄的形式
ans = 0
radix = 16
for i in range(4):
for j in range(4):
ans += n.puzzle[i][j]*radix
radix*=16
return ans
def search(g,bound):
n = path[-1]
f = g+h(n)
if f>bound:return f
if is_goal(n):
return found
mincost = inf
for succ in n.successors():
code = encode(succ)
if not visited.get(code):
path.append(succ)
visited[code] = 1
t = search(g+1,bound)
if t==found:return found
elif t<mincost:mincost = t
visited.pop(code)
path.pop()
return mincost
root.shuffle()
#root.puzzle = [[0, 12, 13, 1], [7, 4, 15, 5], [10, 11, 2, 8], [9, 14, 6, 3]]
#root.space = pos(0,0)
print(root.puzzle)
def ida_star(root):
path.clear()
bound = h(root)
path.append(root)
while(1):
t = search(0,bound)
if t==found:return (path,bound)
if t>70:return (False,bound)
bound = t
import numpy as np
path,bound = ida_star(root)
cnt = 1
for p in path:
print("Status ",cnt )
print(np.array(p.puzzle))
cnt+=1
print("Bound:",bound)
對隨機的初始問題生成的解決方案
[[4, 6, 7, 11], [1, 0, 8, 12], [5, 2, 3, 14], [9, 13, 10, 15]]
Status 1
[[ 4 6 7 11]
[ 1 0 8 12]
[ 5 2 3 14]
[ 9 13 10 15]]
Status 2
[[ 4 0 7 11]
[ 1 6 8 12]
[ 5 2 3 14]
[ 9 13 10 15]]
Status 3
[[ 0 4 7 11]
[ 1 6 8 12]
[ 5 2 3 14]
[ 9 13 10 15]]
Status 4
[[ 1 4 7 11]
[ 0 6 8 12]
[ 5 2 3 14]
[ 9 13 10 15]]
Status 5
[[ 1 4 7 11]
[ 6 0 8 12]
[ 5 2 3 14]
[ 9 13 10 15]]
Status 6
[[ 1 4 7 11]
[ 6 2 8 12]
[ 5 0 3 14]
[ 9 13 10 15]]
Status 7
[[ 1 4 7 11]
[ 6 2 8 12]
[ 5 3 0 14]
[ 9 13 10 15]]
Status 8
[[ 1 4 7 11]
[ 6 2 8 12]
[ 5 3 14 0]
[ 9 13 10 15]]
Status 9
[[ 1 4 7 11]
[ 6 2 8 0]
[ 5 3 14 12]
[ 9 13 10 15]]
Status 10
[[ 1 4 7 0]
[ 6 2 8 11]
[ 5 3 14 12]
[ 9 13 10 15]]
Status 11
[[ 1 4 0 7]
[ 6 2 8 11]
[ 5 3 14 12]
[ 9 13 10 15]]
Status 12
[[ 1 0 4 7]
[ 6 2 8 11]
[ 5 3 14 12]
[ 9 13 10 15]]
Status 13
[[ 1 2 4 7]
[ 6 0 8 11]
[ 5 3 14 12]
[ 9 13 10 15]]
Status 14
[[ 1 2 4 7]
[ 6 3 8 11]
[ 5 0 14 12]
[ 9 13 10 15]]
Status 15
[[ 1 2 4 7]
[ 6 3 8 11]
[ 5 14 0 12]
[ 9 13 10 15]]
Status 16
[[ 1 2 4 7]
[ 6 3 8 11]
[ 5 14 10 12]
[ 9 13 0 15]]
Status 17
[[ 1 2 4 7]
[ 6 3 8 11]
[ 5 14 10 12]
[ 9 13 15 0]]
Status 18
[[ 1 2 4 7]
[ 6 3 8 11]
[ 5 14 10 0]
[ 9 13 15 12]]
Status 19
[[ 1 2 4 7]
[ 6 3 8 0]
[ 5 14 10 11]
[ 9 13 15 12]]
Status 20
[[ 1 2 4 7]
[ 6 3 0 8]
[ 5 14 10 11]
[ 9 13 15 12]]
Status 21
[[ 1 2 4 7]
[ 6 0 3 8]
[ 5 14 10 11]
[ 9 13 15 12]]
Status 22
[[ 1 2 4 7]
[ 0 6 3 8]
[ 5 14 10 11]
[ 9 13 15 12]]
Status 23
[[ 1 2 4 7]
[ 5 6 3 8]
[ 0 14 10 11]
[ 9 13 15 12]]
Status 24
[[ 1 2 4 7]
[ 5 6 3 8]
[ 9 14 10 11]
[ 0 13 15 12]]
Status 25
[[ 1 2 4 7]
[ 5 6 3 8]
[ 9 14 10 11]
[13 0 15 12]]
Status 26
[[ 1 2 4 7]
[ 5 6 3 8]
[ 9 0 10 11]
[13 14 15 12]]
Status 27
[[ 1 2 4 7]
[ 5 6 3 8]
[ 9 10 0 11]
[13 14 15 12]]
Status 28
[[ 1 2 4 7]
[ 5 6 3 8]
[ 9 10 11 0]
[13 14 15 12]]
Status 29
[[ 1 2 4 7]
[ 5 6 3 0]
[ 9 10 11 8]
[13 14 15 12]]
Status 30
[[ 1 2 4 0]
[ 5 6 3 7]
[ 9 10 11 8]
[13 14 15 12]]
Status 31
[[ 1 2 0 4]
[ 5 6 3 7]
[ 9 10 11 8]
[13 14 15 12]]
Status 32
[[ 1 2 3 4]
[ 5 6 0 7]
[ 9 10 11 8]
[13 14 15 12]]
Status 33
[[ 1 2 3 4]
[ 5 6 7 0]
[ 9 10 11 8]
[13 14 15 12]]
Status 34
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 0]
[13 14 15 12]]
Status 35
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]
[13 14 15 0]]
Bound: 34