啟發函數的介紹
是一種函數用來估算當前state和 目標state之間的距離,用于路徑決策。
也就是說,該函數的IQ直接決定了尋找路徑的快慢和準確度(accuracy)
在A*算法里:
Evaluation function: f(n) = g(n) + h(n)
h(n)就是啟發函數,如果我們將該算法用于電腦在游戲中的角色,那么該函數將直接決定游戲地難度,當我們在調整游戲難度的時候,其實就是在重新選擇一個更完美或者弱智的啟發函數。
相關性質
1.admissibility(決定了啟發函數得到最佳solution)
一個啟發函數是admissible,那么當
a是非最佳goal,b是最佳goal,c 是起始點,n 是一個中間點。
通過該啟發函數,最后得到的應該是b,而不是a。
c-->a: f(a) = g(a) + h(a) =g(a)-----since a is a goal node, hence, h(a) = 0
c-->b: f(b) = g(b) + h(b) = g(b)
即:f(a)>=f(b)>=f(n)
since h is admissible, f(n) does not overestimate g(b)
2.consistency(確保該啟發函數在最小cost的qing'kuai'xai能夠找到最優解)
如果,一個啟發函數是consistent,那么
h(n) ≤ c(n, a, n′) + h(n′)
也就是說,一旦一個node 的state被expended,那么,這個cost ( h(node) )就是最小的cost。
所以,一個啟發函數是consistent,它也是admissible。反之,不可。
3.Dominance(用于表現不同啟發函數的關系)
two admissible heuristics ha, hb:如果對于所有n, ha(n) >hb(n),那么,我們可以說 ha dominates hb,對于這個search問題,我們最好使用ha作為啟發函數。
一些想法
1.很多問題都不會像tree的結構那么簡單,graph更適合表示現實問題。
2.環形結構可以避免不必要的termination。
3.在探測node時,要避免對同一個node的重復test,不然會使計算復雜度以指數形式增長。
練習
有一只紅鳥,要吃五只黃鳥。請設計不同的啟發算法,使其成功完成任務。
def null_heuristic(pos, problem):
""" The null heuristic. It is fast but uninformative. It always returns 0.
(State, SearchProblem) -> int
"""
return 0
def manhattan_heuristic(pos, problem):
""" The Manhattan distance heuristic for a PositionSearchProblem.
((int, int), PositionSearchProblem) -> int
"""
return abs(pos[0] - problem.goal_pos[0]) + abs(pos[1] - problem.goal_pos[1])
def euclidean_heuristic(pos, problem):
""" The Euclidean distance heuristic for a PositionSearchProblem
((int, int), PositionSearchProblem) -> float
"""
return ((pos[0] - problem.goal_pos[0]) ** 2 + (pos[1] - problem.goal_pos[1]) ** 2) ** 0.5
#Abbreviations
null = null_heuristic
manhattan = manhattan_heuristic
euclidean = euclidean_heuristic
#-------------------------------------------------------------------------------
# You have to implement the following heuristics for Q4 of the assignment.
# It is used with a MultiplePositionSearchProblem
#-------------------------------------------------------------------------------
#You can make helper functions here, if you need them
def bird_counting_heuristic(state, problem) :
position, yellow_birds = state
heuristic_value = len(yellow_birds) - len(problem.heuristic_info) # the number of rest yellow birds
for index in range(0,len(yellow_birds)):
if position == yellow_birds[index]: # if find the yellow birds
if position in problem.heuristic_info: # if it has been found before
heuristic_value = len(yellow_birds) - len(problem.heuristic_info)
else :
problem.heuristic_info[position] = 1 # record the yellow birds' position caught by red birds
heuristic_value = len(yellow_birds) - len(problem.heuristic_info) # the number of rest yellow birds
return heuristic_value
bch = bird_counting_heuristic
def every_bird_heuristic(state, problem):
"""
(((int, int), ((int, int))), MultiplePositionSearchProblem) -> number
"""
position, yellow_birds = state
heuristic_value = 0
for index in (0, len(yellow_birds)): # go through all the yellow birds
if yellow_birds[index] in problem.heuristic_info: # if this yellow bird has been found before
continue
else:
# calculate the distance between the red bird and the closest yellow bird
heuristic_value_test = abs(yellow_birds[index][0] - position[0]) + abs(yellow_birds[index][1] - position)[1]
if heuristic_value > heuristic_value_test: # compare the distance and find the closest yellow bird
heuristic_value = heuristic_value_test
if heuristic_value == 0:
problem.heuristic_info[position] = 1 # add the yellow bird position visited into dic
return heuristic_value
every_bird = every_bird_heuristic
以上code中有完整的4種方法,一是計算歐幾里得距離;二是計算曼哈頓距離;三是計算剩余的黃鳥數量;最后是計算該紅鳥與最近黃鳥的距離,返回最小值。