標籤:images 集中 函數 分組 ons 帶來 item less 關係
許多工業與科學計算問題都可以轉化為在圖中尋路問題。啟發學習法的尋路方法將問題表示為一個圖,然後利用問題本身的資訊,來加速解的搜尋過程。一個典型的例子是有一些通路串連若干城市,找出從指定起點城市到指定終點城市的路徑。但是有些問題不存在如此明顯的事先定義好的圖,它們的圖是隱式圖,也就是說,問題給定了搜尋起點與一系列操作,對起點進行這些操作得到了它的後繼結點,以及該操作的代價,對這些後繼結點不斷地重複操作,就得到了一個帶權的有向圖,隱式圖就定義好了。
對於解決最小路徑問題,A*演算法效能卓越。首先,對於任何有解路徑,A*總能找到一條最佳路徑,也就是說A*演算法是可採納的。其次,在保證能找到最佳路徑的前提下,A*演算法擴充了最少個數的結點,也就是說A*演算法是最優的。
使用啟發資訊的一種重要方法就是估價函數。A*使用來表示結點的估價函數,它表示從起點到目標,經由結點最小費用路徑上的費用。它由和兩部分組成,即。其中表示從初始結點到的最佳解路徑的費用,表示從到目標結點的最佳解路徑的費用。但想要知道它們的精確值很難,我們可以使用來估計,使用來估計,來估計。表示目前為止,從起始點到的最小費用,因為日後可能找到更小的費用,所以有。而在A*演算法中,對的估計通常是樂觀的,比實際所需的費用要小,即有。它們之間的關係可以用形象地表示:
註:黃色是估計值,黑色是最佳解路徑費用
A*演算法維護兩個集合:OPEN 集和 CLOSED 集。OPEN 集包含待檢測節點。初始狀態的OPEN集僅包含一個元素:開始位置。CLOSED集包含已檢測節點。初始狀態的CLOSED集為空白。從圖形上來看,OPEN集是已訪問地區的邊界,CLOSED集是已訪問地區的內部。每個節點還包含一個指向父節點的指標,以確定追蹤關係。
演算法有一個主迴圈,重複地從OPEN集中取最優節點n(即f值最小的節點)來檢測。如果n是目標節點,那麼演算法結束;否則,將節點n從OPEN集刪除,並添加到CLOSED集中,然後查看n的所有鄰節點n‘。cost= g(n) + movementcost(n, n‘)。n‘有如下三種情況:
- 鄰結點在CLOSED集中,說明它已被檢測過,如果cost<g(n‘),那麼說明找到了一條通過n到達n‘更近的路徑,更新g(n‘)為cost, n‘的父結點為n,把鄰結點從CLOSED集中刪去,並把它重新放入OPEN集中(因為同樣都是到達n‘,h(n‘)是一樣的,g(n‘)小必然能帶來更小的f(n‘)),如果cost>=g(n‘),則跳過該鄰結點。
- 鄰結點在OPEN集中,說明它之前被拓展過,如果cost<g(n‘),那麼說明找到了一條通過n到達n‘更近的路徑,更新g(n‘)為cost, n‘的父結點為n,鄰結點仍留在OPEN集中。如果cost>=g(n‘),則跳過該鄰結點。
- 鄰結點不在CLOSED集或者OPEN集中,則加入OPEN集中。
演算法用虛擬碼表示如下:
OPEN = priority queue containing START
CLOSED = empty set
while lowest rank in OPEN is not the GOAL:
current = remove lowest rank item from OPEN
add current to CLOSED
for neighbors of current:
cost = g(current) + movementcost(current, neighbor)
if neighbor in OPEN and cost less than g(neighbor):
remove neighbor from OPEN, because new path is better
if neighbor in CLOSED and cost less than g(neighbor): **
remove neighbor from CLOSED
if neighbor not in OPEN and neighbor not in CLOSED:
set g(neighbor) to cost
add neighbor to OPEN
set priority queue rank to g(neighbor) + h(neighbor)
set neighbor‘s parent to current
reconstruct reverse path from goal to start
by following parent pointers
在A*演算法中,h(n)越大啟發資訊越多,但是有時計算啟發資訊本身的代價很高,例如計算的開銷較大,可以使用來代替,(總是成立)雖然會擴充多一些的結點,但是依舊是高效的。h(n)=0時,A*退化成了DIjkstra演算法。
當時,演算法不再可採納,不一定能找到最優解,但是能以較快的速度找到滿意解,這在大多數時候是高效的。例如使用來代替。當h(n)很大時,A*變成了貪心演算法。
所以要仔細選擇h(n),在演算法是否可採納、搜尋效率、計算開銷之間權衡。
A*演算法研究