解决了最近一个人工智能关于解决八数码难题的作业。
图可能看不清,除了黑块外其他位置是英文字母ABCDEFGH
A*:f(n)=g(n)+h(n)
其中f为总花费,g为已知花费(深度),h为估计花费
关于Nilsson sequence score这个估计花费算法(也就是计算h的,估计函数)
Nilsson's sequence score
A tile in the center scores 1 (since it should be empty)
For each tile not in the center, if the tile clockwise to it is not the one that should be clockwise to it then score 2.
Multiply this sequence by three and finally add the total distance you need to move each tile back to its correct position.
公式:h(n)=P(n)+3S(n)
P(n)是每一个滑块距离正确位置的曼哈顿(Manhattan)距离之和,即P(n)所得分数;
曼哈顿距离P=水平位移+垂直位移
S(n):对于当前状态(块的分布)而言,如果中心的块非空,则得1分(对于八数码问题,目标状态的中心块是空的);然后轮流检查除了中心块之外的每一个块,如果该块的后继结点是错误的后继结点,得2分。其余块不得分;
把P(n)的分数与S(n)的分数的三倍相加即为Nilsson sequence score
举一个例子
初始状态I
*ACHBD
GFE
目标状态T
ABC
H*D
GFE
开始计算
1.计算曼哈顿距离
从初始状态看,
对于A,从I(A)移到T(A)需要一步(向左移一步),得1分;
对于C,D,E,F,G,H位置一致,不得分;
对于B,需要向上移一步,得1分;
P(n)总共得分为1+1=2分。
2.计算S
①B位于中心块,得1分;
②将其他块按顺时针顺序排好:
I:*ACDEFGBH
T:ABCDEFGH
使[当前点,后继点]组成如下数对
目标状态的数对:[A,B], [B,C], [C,D], [D,E], [E,F], [F,G], [G,H], [H,A]
当前状态的数对:[A,C], [C,D], [D,E], [E,F], [F,G], [G,H], [H,*]
([*,A] 不考虑,因为不存在*这样的前继)
其中有2对是当前点相同,后继点不同的:[A,C], [H,*] 因此 2*2=4分;
再把S乘以3:3*(1+2*2)=15分;
总得分h=P+3S=2+15=17分
再通过求所有情况的每一步的总花费f=g+h就可以重新对open表排序来进行选择最优策略了。
附上自己对求单步h值的Python脚本
#h(n)=P(n)+3S(n)
Current=[0,1,3,
8,2,4,
7,6,5]
Target=[1,2,3,
8,0,4,
7,6,5]
#顺时针排序
closewise=[0,1,2,5,8,7,6,4,0]
#左下角代表坐标原点(0,0)
Coordinate=[13,23,33,
12,22,32,
11,21,31]
p=0
s=0
h=0
#ManhattanDistance
for i in range(9):
for j in range(9):
if Current[i]==Target[j] and Current[i]!=0:
x1 = int(Coordinate[i] / 10) - 1
y1 = int(Coordinate[i] % 10) - 1
x2 = int(Coordinate[j] / 10) - 1
y2 = int(Coordinate[j] % 10) - 1
p+=abs(x1-x2)+abs(y1-y2)
#A tile in the center scores 1 (since it should be empty)
if Current[4]:
s+=1
#For each tile not in the center,
# if the tile clockwise to it is not the one that
# should be clockwise to it then score 2.
for i in range(8):
for j in range(8):
if Current[closewise[i]]!=0:
if Target[closewise[i]]==Current[closewise[j]] and Target[closewise[i+1]]!=Current[closewise[j+1]]:
s+=2
h=p+3*s
print(h,p,3*s)
以上是我自己理解的,要是没讲清楚的话大家最好直接去看看这些解释(全英)
http://www.cs.rpi.edu/academics/courses/fall00/ai/assignments/assign3heuristics.html
http://heyes-jones.com/astar.php