簡體   English   中英

在直接加權圖中找到從節點A到節點B的所有簡單路徑,權重之和小於某個值?

[英]Find all simple path from node A to node B in direct weighted graph with the sum of weighs less a certain value?

我有一個有向加權圖G =(V,E),它可能有循環

我正在嘗試確定最佳的省時算法來完成任務:• 在源節點和目標節點之間找到G中所有簡單路徑,並且該路徑中的邊的總權重小於某個值 (為方便起見,我們將該值表示為PATH_WEIGHT_LIMIT)

所有權重均為正,可以浮動。

因此,我的函數原型將是:

def find_paths(G, source, target, path_weight_limit) 

結果路徑可能會重疊,這很好。

與此處討論的內容非常相似,例如:

  1. 查找加權有向循環圖中從A到B的不同路徑的數量的算法
  2. 在UNDERICTED圖中找到所有簡單路徑(NP問題)

但是我沒有找到一種算法來解決上面提出的特定任務,該算法無法找到源節點和目標節點之間G中所有簡單的路徑(定向,加權,循環),且該路徑中的邊的總權重小於特定值

我認為應該使用修改后的DFS算法,重點放在路徑當前部分的權重上。 但我認為這並不有效,也許有更好的算法可以解決這個問題。

您問題的答案

從理論上講,每個節點的權重都為1+,因此循環不會成為問題,因為權重會隨着路徑的增長而增加。 但是...如果您的任何節點的成本/權重<= 0,則應包括最大時間或深度以停止尋路。

如果您想要完美的路徑,請使用Djikstra的算法。 如果您不關心完美,請使用A *。 創建候選節點列表時,請先進行驗證,然后再將其添加到搜索列表中。 總權重大於最大權重的所有節點都應從候選列表中刪除。

所以像這樣:

Current node -> List of candidate nodes --(are they less?)-> List of next nodes
merge(list of search nodes, list of next nodes)

找到目標節點時不要停止,而是將目標節點添加到列表中並在完成尋路時創建路徑。 尋路節點的大多數實現如下所示:

Node
- Node previous
- depth, cost
- misc data (coordinates, hp, gold, terrain, entity)

跟蹤路徑非常容易:將目標節點添加到列表中,然后將previous一個添加到列表中, until previous = null 該列表是您的路徑。

尋路是一個非常強大的工具,但是您可以在網上找到的大多數算法和指南都是引言,甚至我找到的最佳指南Amit Patel的A * Tutorial也不是很深入。

許多尋路系統只能找到一條路徑,因為它們太專門了,因此我對算法進行了概括。 在下面,您會找到有關尋路的深入指南,該指南所包含的信息比Google所能找到的更多。 我之所以加入它,是因為它使您能夠導出功能更強大的尋路算法,例如從多個起始位置開始甚至從執行起始時間開始,找到多個路徑和目標。 這將幫助您實現算法。

深度尋路指南

建立新的尋路系統所需的一切

尋路的本質是以下算法:

  1. 打開的節點列表開始(通常包含1個項目)
  2. 選擇最有前途的1個節點
    • 如果節點是目標2 ,則將其添加到列表目標
    • 如果節點有效,則生成相鄰3個候選節點的列表(list cand
  3. 對於每個候選者,如果它無效4 ,請將其從列表cand中刪除。 然后,將list cand添加到list open中
  4. 打開的列表中刪除所選節點,並將其添加到關閉的列表中
  5. 尋路5時重復步驟2

筆記:

[1]:這是大多數尋路算法有所不同的地方; 他們對節點的優先順序不同。

  • 先進先出(最早)是最簡單的算法; 只是檢查節點在它們被添加到列表打開命令。 通常看起來像BFS。
  • 先進先出(最新)選擇添加到列表中的最新節點。 根據您的節點生成器,它看起來很像DFS。
  • BFS搜索的深度最少,通常也不是最佳的選擇算法。
  • DFS優先考慮深度最大的節點。 即使它永遠走下去,它也傾向於選擇一條路徑並繼續走下去。
  • 貪婪選擇要移動的最低成本/重量。 與完美的解決方案相比,搜索可能會停留在高成本區域,並最終導致成本很高的路徑。 通常,A *是速度和最優性之間的更好折衷。
  • Dijkstra選擇成本/重量最低的節點。 在大范圍內速度很慢,但是如果您想要完美的解決方案,那是一個不錯的選擇。
  • 最佳優先選擇具有最低(估計)剩余成本的節點來達到目標​​。 在許多情況下,估算值是到目標的實際距離(歐幾里得,曼哈頓等),但並非總是可能知道。
  • A *是Dijkstra +最佳第一。 這兩種啟發式方法相互抵消,因此在開放區域中,A *會快速移動,但不會卡住。 A *並不完美,但是它比Dijkstra的速度快得多。 您可以權衡試探法以使算法更貪婪或更優化,也可以添加其他成本函數,例如與醫療包,掩護或敵方玩家的距離。
  • 當節點包含大量數據時,自定義試探法通常會發揮作用。 這通常意味着您已經從尋路進入了狀態空間搜索領域,例如預測對手在國際象棋中將采取的下一步行動。 涉及資源管理的問題將使用自定義試探法對每個資源進行優先級排序,以確定節點的權重。

[2]:有時目標節點不是一個位置。 有時您可能想要找到具有特定對象的任何節點,例如健康包,商店或容易殺死的敵方玩家。 通過使用goal()函數檢查節點,可以定義多個端點。

[3]:候選節點不必彼此相鄰。 您正在做的是使用函數f(node) = list(nodes) 搜索游戲狀態以獲取玩家的金錢或生命值時,可以為動作(例如JUMP,ATTACK,REST等)創建節點。在某些情況下,您需要先驗證生成的節點列表, 然后再添加它們。

[4]:無效節點通常只是列表關閉之前已搜索過的節點。 但是,它們可以是距離太遠的節點,與牆壁碰撞的節點(確實很常見),將播放器的健康狀況降低到0的node isn't in closed list ,等等。如果您決定不使用node isn't in closed list作為條件,那么您的算法就可以回溯(可以創建無限循環)。

[5]:您可以實施滿足特定條件時停止的算法。 通常,假定已找到1個目標節點,但是您可以做很多事情! 您可以在一定時間后停止尋路,這對於游戲引擎而言非常有用,因為您可能需要暫停渲染幀並防止延遲。 如果節點列表太大,也可以停止搜索,以保持較低的內存使用率。 一旦有了一定數量的解決方案,您甚至可以停止。

此布爾值停止條件/功能使您可以在探路者花費太長時間,浪費資源或陷入無限循環時中止尋路。 在單線程上,這通常意味着您不再需要路徑查找器。 對於游戲引擎,在線游戲客戶端和GUI應用程序,我喜歡在第二個線程中運行探路器,並在需要時將其喚醒。 如果探路者找不到足夠快的路徑,那么笨拙的AI會做出快速決策,直到尋路完成為止。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM