變種 1 - 束搜索(Beam Search)
在 A* 算法的住循環中,OPEN 集存儲可能需要搜索的節點,用來以查找路徑。
束搜索是 A* 的變體,它限制了OPEN集的大小。
如果集合變得太大,則丟棄給出良好路徑的最差機會的節點。
束搜索的一個缺點是你必須保持你的設置排序這樣做,這限制了你選擇的數據結構的種類。
變種 2 - 迭代加深(Iterative Deepening)
迭代加深是一種在許多AI算法中使用的方法,以近似答案開始,然后使其更准確。
該名稱來自游戲樹搜索,您可以在其中查看前面的一些移動(例如,在國際象棋中)。
您可以通過向前看更多動作來嘗試加深樹木。
一旦你的答案沒有改變或改善很多,你就會認為你有一個非常好的答案,當你試圖讓它再次變得更准確時它不會改善。
在 IDA* 中,“深度”是 f 值的截止值。
當 f 值太大時,甚至不考慮節點(即,它不會被添加到 OPEN 集)。
第一次通過你處理很少的節點。
每次后續傳遞,都會增加您訪問的節點數。
如果您發現路徑有所改善,那么您將繼續增加截止值;否則,你可以停下來。
我個人認為在游戲地圖上不太需要用 IDA* 查找路徑。
因為 ID 算法傾向於增加計算時間,同時減少內存需求。
然而,在地圖尋路中,“節點”非常小 - 它們只是坐標。
我沒有看到節約存儲這些節點有什么巨大優勢。
變種 3 - 動態加權(Dynamic Weighting)
通過動態加權,您可以假設——
在搜索開始時,快速到達目的地所在區域更重要;
在搜索結束時,得到到達目標的最佳路徑更重要。
有一個與啟發式相關的權重(w >= 1)。
隨着你越來越接近目標,你減輕了權重;這降低了啟發式的重要性,並增加了路徑實際成本的相對重要性。
變種 4 - 帶寬搜索(Bandwidth Search)
有一些人可能覺得有用的帶寬搜索有兩個屬性。
這種變化假設 h 是高估的,但它並沒有高估超過一些數e。
如果您的搜索就是這種情況,那么您獲得的路徑的成本不會超過最佳路徑的成本超過e。
再次,您的啟發式越好,您的解決方案就越好。
您獲得的另一個屬性是,如果您可以刪除OPEN集中的某些節點。
每當 h + d 大於路徑的真實成本(對於某些 d ),您可以丟棄任何 f 值至少比 OPEN 中最佳節點的 f 值高 e + d 的節點。
這是一個奇怪的屬性。
你有一個很好的 f 值“帶寬”;這個頻段以外的所有東西都可以丟棄,因為可以保證它不會走在最佳路徑上。
奇怪的是,您可以對這兩個屬性使用不同的啟發式方法,但事情仍然有效。
您可以使用一個啟發式方法來保證您的路徑不是太糟糕,另一個用於確定 OPEN 集中的內容。
注意:
帶寬搜索看起來可能有用,但在游戲行業很少使用到。
搜索 Google 以獲得更多信息,尤其是相關論文。
變種 5 - 雙向搜索(Bidirectional Search)
您可以不從開始到結束搜索,而是並行開始兩次搜索,一次從頭到尾,一次從完成到開始。
當他們見面時,你應該有一條好路。
在某些情況下,這是一個好主意。
雙向搜索背后的想法是搜索結果在地圖上扇出的“樹”。
一棵大樹比兩棵小樹要糟糕得多,所以最好有兩棵小樹。
從面對面的變化將兩個搜索鏈接在一起。
不是選擇最佳前向搜索節點【 g(start, x) + h(x, goal) 】或最佳后向搜索節點【 g(y, goal) + h(start, y) 】
該算法選擇具有最佳【g(start, x) + h(x, y) + g(y, goal)】的節點對。
重定向方法(retargeting approach)放棄了向前和向后方向的同時搜索。
相反,它會在短時間內執行前向搜索,選擇最佳前向候選者 N;
然后在終點執行后向搜索,搜索的目標不是起點,而是最佳前向候選者 N。
過了一會兒,它選擇了一個最好的后向候選人 M ,並執行從 N 到 M 的前向搜索。
這個過程一直持續循環,直到兩個候選人是同一個點。
Holte,Felner,Sharon,Sturtevant 在 2016 年的論文《具有近似最優節點擴展的前端雙向啟發式搜索》 是最近的結果,具有接近最優的 A* 雙向變體。
Pijls 和 Post 在 2009 年的論文 《另一種用於最短路徑的雙向算法》 提出了一種比平衡雙向搜索運行得更快的不平衡雙向 A* 。
變種 6 - 動態 A*(Dynamic A*)和 終身規划 A*(Lifelong Planning A*)
A* 的變體允許在計算初始路徑之后改變世界。
D* 適用於沒有完整信息的情況。
如果你沒有所有的信息,A* 會犯錯誤;D* 的貢獻在於它可以在不花費太多時間的情況下糾正這些錯誤。
LPA* 旨在用於成本變化時使用。
使用A*,路徑可能會因地圖的更改而失效;LPA *可以重復使用先前 A* 的計算來生成新路徑。
但是,D* 和 LPA* 都需要很大的空間 —— 需要保存在最佳路徑周圍的很多節點的內部信息(OPEN / CLOSED集,路徑樹,g值)
然后當地圖改變時,D* 或 LPA* 會告訴您是否需要調整路徑以考慮地圖更改。
對於具有大量移動單位的游戲,您通常不希望保留所有這些信息(因為太大),因此 D* 和 LPA* 不適用。
它們是專為機器人設計的,如果只有一個機器人 —— 您不需要將內存重用於其他機器人的路徑。
如果您的游戲只有一個或少數單位,您可能需要試試 D* 或 LPA* 。
變種 7 - 跳點搜索(Jump Point Search)
許多加速 A* 的技術實際上都是關於減少節點數量。
在具有統一成本的方形網格中,一次一個地查看所有單獨的網格空間是相當浪費的。
一種方法是構建關鍵點(例如角點)的圖形並將其用於尋路。
但是,如果您不希望預先計算航點圖,那就可以了解一下跳轉點搜索,這是 A* 的變體,可以在方格網格上向前跳躍。
當考慮當前節點的子節點可能包含在 OPEN 集中時,跳轉點搜索會向前跳到從當前節點可見的遠端節點。
每個步驟都更昂貴,但它們更少,減少了 OPEN 集中的節點數量。
有關詳細信息,請參閱此博客。
此文章提供了一個很好的可視化程序用來解釋。
另請參閱矩形對稱縮減,它可以分析地圖並將跳轉嵌入到圖形本身中。
這兩種技術都是為方形網格開發的。
這個網站是為六邊形網格擴展的算法。
變種 8 - Theta*
網格用於尋路,是因為地圖是在網格上制作的,而不是因為我們實際上想要在網格上移動。
如果給出關鍵點(例如角點)而不是網格的圖形,A* 將運行得更快並產生更好的路徑。
但是,如果您不想預先計算角點圖形,則可以使用在方形網格上運行的 A* 變體 Theta* 來查找不嚴格遵循網格的路徑。
在構建父指針時,如果該節點與祖先節點有一條視線,互相可見,那么 Theta* 將該節點直接指向祖先節點,並跳過他倆中間的節點。
與路徑平滑不同,路徑平滑在 A* 找到路徑之后拉直路徑;而 Theta* 可以在 A* 過程中分析這些路徑的,是 A* 的一部分。
這可以得到比將網格路徑后處理成任意角度路徑更短的路徑。
這篇文章是對該算法的合理介紹;這里是 Lazy Theta*。
Theta *的想法很可能也適用於導航網格。
另請參閱 Block A*,它聲稱通過使用分層方法比 Theta* 快得多。