中山大學人工智能實驗2 15-Puzzle Problem

描述

在這裏插入圖片描述

算法

在這裏插入圖片描述

任務

在這裏插入圖片描述

解決方案(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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章