[Python] A*(A-Star) 演算法實作

更新於 2024/11/30閱讀時間約 11 分鐘

A* (A-Star)演算法實作

A* (A-Star)是一種啟發式搜尋演算法,除了最短距離,還會考慮目標的估計距離(啟發式函數)。

實作步驟

  1. 定義地圖和啟發式函數
  2. 初始化開放節點(Open Set)和已訪問節點(Closed Set)
  3. 計算代價函數 f(n) = g(n) + h(n)
    • g(n):起點到當前節點的實際距離。
    • h(n):當前節點到目標的估計距離。
  4. 重複尋找最小代價路徑,直到找到目標或無法到達

程式碼

import heapq

def a_star(graph, start, goal, heuristic):
# 優先佇列 (open_set) 用於儲存需要探索的節點及其估計總代價 (f_score)
# 初始包含起點,f_score 設為 0
open_set = [(0, start)] # (估計代價, 節點)

# 字典 (came_from) 用於回溯路徑,儲存每個節點的父節點
came_from = {}

# 字典 (g_score) 儲存從起點到每個節點的實際距離,初始設為無限大
# 起點的距離設為 0,表示起點到自身的距離為 0
g_score = {node: float('inf') for node in graph}
g_score[start] = 0

while open_set:
# 從 open_set 中取出代價最低的節點 (current_node)
current_cost, current_node = heapq.heappop(open_set)

# 如果已到達目標節點,回溯並返回完整路徑
if current_node == goal:
path = [] # 用於儲存最終路徑的列表
while current_node: # 回溯每個節點,從目標節點到起點
path.append(current_node)
current_node = came_from.get(current_node) # 取得父節點
return path[::-1] # 反轉路徑順序,從起點到目標

# 遍歷當前節點的所有鄰居 (neighbor)
for neighbor, weight in graph[current_node].items():
# 計算從起點到鄰居的臨時距離 (tentative_g_score)
tentative_g_score = g_score[current_node] + weight

# 如果新的距離小於已知的距離,更新資訊
if tentative_g_score < g_score[neighbor]:
# 更新鄰居的父節點為當前節點
came_from[neighbor] = current_node
# 更新鄰居的 g_score (實際距離)
g_score[neighbor] = tentative_g_score
# 計算鄰居的估計總代價 f_score
f_score = tentative_g_score + heuristic[neighbor]
# 將鄰居及其估計代價加入 open_set
heapq.heappush(open_set, (f_score, neighbor))

# 如果無法到達目標節點,返回 None
return None

# 啟發式函數 (heuristic),估計從每個節點到目標節點的距離
heuristic = {
'A': 7, # 節點 A 到目標節點 D 的估計距離為 7
'B': 6, # 節點 B 到目標節點 D 的估計距離為 6
'C': 2, # 節點 C 到目標節點 D 的估計距離為 2
'D': 1 # 節點 D 到自身 (目標) 的估計距離為 1
}

# 測試地圖 (graph),以鄰接表表示每個節點及其相鄰節點的距離
graph = {
'A': {'B': 1, 'C': 4}, # 節點 A 連接到 B (距離 1),C (距離 4)
'B': {'A': 1, 'C': 2, 'D': 5}, # 節點 B 連接到 A、C、D
'C': {'A': 4, 'B': 2, 'D': 1}, # 節點 C 連接到 A、B、D
'D': {'B': 5, 'C': 1} # 節點 D 連接到 B、C
}

# 起點和目標節點
start_node = 'A' # 起點節點 A
goal_node = 'D' # 目標節點 D

# 執行 A* 演算法
path = a_star(graph, start_node, goal_node, heuristic)
print("Shortest path using A* from A to D:", path)

A 演算法輸出*

Shortest path using A* from A to D: ['A', 'B', 'C', 'D']

這段輸出是執行* 演算法 後的結果,表示從起點節點 A 出發,到達其他節點(BCD)的最短距離。


1. a_star 函數簡介

這個函數用來執行 A* 演算法,計算從起點節點 start 到目標節點 goal 的最短路徑,並返回節點列表作為結果。

2. 主要變數和結構

輸入參數

  • graph:
    • 表示地圖的鄰接表結構,包含節點及其相鄰節點的連線權重。
    • 格式:{'節點': {'鄰居1': 距離, '鄰居2': 距離}}
  • start:
    • 起點節點名稱。
  • goal:
    • 目標節點名稱。
  • heuristic:
    • 啟發式函数,用於估算當前節點到目標節點的距离。

變數初始化

  • open_set:
    • 優先佇列(用 heapq 實現),儲存目前需要探索的節點及其估計總代價(f(n))。
    • 初始為起點 (0, start),代價為 0。
  • came_from:
    • 字典,儲存每個節點的父節點,用來回溯最短路徑。
  • g_score:
    • 字典,儲存從起點到某節點的實際距離(g(n))。
    • 初始設為無限大,起點距離設為 0。

3. 主要邏輯

(1) while open_set:

  • 當 open_set 不為空時,繼續處理。
  • 每次處理時:
    1. 從 open_set 中取出代價最小的節點(heapq.heappop 保證最小堆結構)。
    2. 如果當前節點是目標節點,則回溯並返回路徑。
    3. 否則,更新相鄰節點的距離和父節點。

(2) 回溯路徑

當到達目標節點 goal 時:

  • 初始化空列表 path
  • 從目標節點 goal 開始回溯 came_from,直到找到起點。
  • 返回路徑(反轉順序 [::-1])。

(3) 更新相鄰節點

  • 對於當前節點的所有鄰居:
    • 計算臨時距離 tentative_g_score:

tentative_g_score = g_score[current_node] + weight

    • 如果新距離小於已知距離:更新 g_score[neighbor] 為新距離。更新 came_from[neighbor] 為當前節點。

計算估計總代價 f(n):f(n)=g(n)+h(n)將鄰居及其代價加入 open_set。


4. 啟發式函數(heuristic

啟發式函數估算當前節點到目標節點的距離:

  • 範例中,直接提供每個節點到目標的距離作為估計值。
  • heuristic = {'A': 7, 'B': 6, 'C': 2, 'D': 1}
    • A 到 D 的估計距離是 7。
    • B 到 D 的估計距離是 6,依此類推。

5. 測試地圖解讀

圖結構(graph)表示節點及其相鄰關係:

A --(1)-- B --(5)-- D
\ / \ /
(4) (2) (1)
\ / \
C --------- D
  • 節點:
    • A 連接到 B 和 C,權重分別是 1 和 4。
    • B 連接到 A、C 和 D,權重分別是 1、2 和 5。
    • C 連接到 A、B 和 D,權重分別是 4、2 和 1。
    • D 連接到 B 和 C,權重分別是 5 和 1。

6. 路徑計算流程

初始設定

  • open_set[(0, 'A')]
  • g_score{'A': 0, 'B': inf, 'C': inf, 'D': inf}
  • came_from{}

步驟

  1. 處理節點 A
    • g(A) = 0, h(A) = 7, f(A) = 7
    • 鄰居:B:g(B) = 1, f(B) = 1 + 6 = 7C:g(C) = 4, f(C) = 4 + 2 = 6
    • 更新 open_set 為 [(6, 'C'), (7, 'B')]
  2. 處理節點 Cf(C) 最小):
    • g(C) = 4, h(C) = 2, f(C) = 6
    • 鄰居:B:g(B) = 6,不更新(已有更小值)。D:g(D) = 5, f(D) = 5 + 1 = 6
    • 更新 open_set 為 [(6, 'D'), (7, 'B')]
  3. 處理節點 D(已到目標):
    • 回溯路徑:D -> C -> B -> A

7. 最終輸出

最短路徑:

Shortest path using A* from A to D: ['A', 'B', 'C', 'D']

此結果是基於 g(n) 和 h(n) 綜合考慮後的最佳路徑。



avatar-img
128會員
209內容數
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
螃蟹_crab的沙龍 的其他內容
要使用 CUDA(Compute Unified Device Architecture)來加速計算,首先需要在你的系統上設置和安裝相關的工具。CUDA 是由 NVIDIA 開發的平行計算框架,用於加速大量數據的運算,尤其在圖像處理、機器學習、科學計算等領域很有應用。 可以參考官方的安裝方式 以
呈上篇介紹如何訓練模型,此篇就主要介紹如何利用訓練好的模型來生成圖片 [深度學習][Python]DCGAN訓練生成手寫阿拉伯數字_生成篇 生成的結果 生成的圖片大小會根據,當初設置的生成器輸出大小來決定,當你使用生成對抗網絡(GAN)生成圖像時,生成器模型的最後一層通常會決定生成圖
本文參考TensorFlow官網Deep Convolutional Generative Adversarial Network的程式碼來加以實作說明。 示範如何使用深度卷積生成對抗網路(DCGAN) 生成手寫數位影像。
本文將延續上一篇文章,經由訓練好的GAN模型中的生成器來生成圖片 [深度學習][Python]訓練MLP的GAN模型來生成圖片_訓練篇 [深度學習][Python]訓練CNN的GAN模型來生成圖片_訓練篇 相較之下CNN的GAN生成的效果比較好,但模型也相對比較複雜,訓練時間花的也比較
延續上一篇訓練GAM模型,這次我們讓神經網路更多層更複雜一點,來看訓練生成的圖片是否效果會更好。 [深度學習][Python]訓練MLP的GAN模型來生成圖片_訓練篇 資料集分割處理的部分在延續上篇文章,從第五點開始後修改即可,前面都一樣 訓練過程,比較圖 是不是CNN的效果比MLP還要好,
本文主要介紹,如何利用GAN生成對抗網路來訓練生成圖片。 利用tensorflow,中的keras來建立生成器及鑑別器互相競爭訓練,最後利用訓練好的生成器來生成圖片。 GAN生成對抗網路的介紹 它由生成網路(Generator Network)和鑑別網路(Discriminator Netwo
要使用 CUDA(Compute Unified Device Architecture)來加速計算,首先需要在你的系統上設置和安裝相關的工具。CUDA 是由 NVIDIA 開發的平行計算框架,用於加速大量數據的運算,尤其在圖像處理、機器學習、科學計算等領域很有應用。 可以參考官方的安裝方式 以
呈上篇介紹如何訓練模型,此篇就主要介紹如何利用訓練好的模型來生成圖片 [深度學習][Python]DCGAN訓練生成手寫阿拉伯數字_生成篇 生成的結果 生成的圖片大小會根據,當初設置的生成器輸出大小來決定,當你使用生成對抗網絡(GAN)生成圖像時,生成器模型的最後一層通常會決定生成圖
本文參考TensorFlow官網Deep Convolutional Generative Adversarial Network的程式碼來加以實作說明。 示範如何使用深度卷積生成對抗網路(DCGAN) 生成手寫數位影像。
本文將延續上一篇文章,經由訓練好的GAN模型中的生成器來生成圖片 [深度學習][Python]訓練MLP的GAN模型來生成圖片_訓練篇 [深度學習][Python]訓練CNN的GAN模型來生成圖片_訓練篇 相較之下CNN的GAN生成的效果比較好,但模型也相對比較複雜,訓練時間花的也比較
延續上一篇訓練GAM模型,這次我們讓神經網路更多層更複雜一點,來看訓練生成的圖片是否效果會更好。 [深度學習][Python]訓練MLP的GAN模型來生成圖片_訓練篇 資料集分割處理的部分在延續上篇文章,從第五點開始後修改即可,前面都一樣 訓練過程,比較圖 是不是CNN的效果比MLP還要好,
本文主要介紹,如何利用GAN生成對抗網路來訓練生成圖片。 利用tensorflow,中的keras來建立生成器及鑑別器互相競爭訓練,最後利用訓練好的生成器來生成圖片。 GAN生成對抗網路的介紹 它由生成網路(Generator Network)和鑑別網路(Discriminator Netwo
你可能也想看
Google News 追蹤
Thumbnail
本文探討了複利效應的重要性,並藉由巴菲特的投資理念,說明如何選擇穩定產生正報酬的資產及長期持有的核心理念。透過定期定額的投資方式,不僅能減少情緒影響,還能持續參與全球股市的發展。此外,文中介紹了使用國泰 Cube App 的便利性及低手續費,幫助投資者簡化投資流程,達成長期穩定增長的財務目標。
Thumbnail
題目敘述 Find K-th Smallest Pair Distance 給定一個輸入陣列nums和 參數k。 請找出第k小的pair distance是多少? pair distance定義為 abs( nums[i] - nums[j]), i 不等於j 也就是任意兩陣列元素差值的絕對值
Thumbnail
分享一個猜數字的遊戲題目,給予提示讓玩家找出正確的四位數密碼。
Thumbnail
題目敘述 All Ancestors of a Node in a Directed Acyclic Graph 給定一個有向無環圖,請找出每個點的祖先,以陣列的形式返回答案。
Thumbnail
題目敘述 Combination Sum IV 給定一個輸入陣列nums,和目標值target,從nums裡面挑數字去湊出總和 = target,數字可以重複挑選。 請問有多少排列數可以湊出target? 註: 排列數的意思就是位置不同代表兩種不同的方法數。
Thumbnail
題目敘述 Distinct Subsequences 給定一個字串s和目標t,請問有多少個s的子序列可以完美匹配目標t ? 也就是說,有多少個s的子序列和目標t相等? 測試範例 Input: s = "rabbbit", t = "rabbit" Output: 3
Thumbnail
Minimum Path Sum 給定一個矩陣,每個格子點代表經過的對應成本。 每回合可以往右移動一格或往下移動一格。 請問從起點左上角 走到 終點右下角的最小路徑成本總和是多少?
Thumbnail
給定一個字串陣列,請把它們所共有的字元伴隨著出現次數輸出。這篇文章介紹如何使用字典統計出現次數,和字典取交集的方法來解決此問題。並提供了複雜度分析和關鍵知識點。
Thumbnail
題目敘述 題目會給我們一棵二元搜索樹的根結點root,還有一個指定的目標值val。 要求我們找出在樹中對應到目標值val的節點,假如找不到,請回傳null( null在Python就是None)。 題目的原文敘述 測試範例 Example 1: Input: root = [4,2,
Thumbnail
題目敘述 題目會給定我們一顆二元搜索樹BST的根結點, 還有一個指定區間的上邊界R 和 下邊界L。 請問二元搜索樹中,所有落在指定區間內的節點元素值的總和是多少? 題目的原文敘述 測試範例 Example 1: Input: root = [10,5,15,3,7,null,18], l
Thumbnail
本文探討了複利效應的重要性,並藉由巴菲特的投資理念,說明如何選擇穩定產生正報酬的資產及長期持有的核心理念。透過定期定額的投資方式,不僅能減少情緒影響,還能持續參與全球股市的發展。此外,文中介紹了使用國泰 Cube App 的便利性及低手續費,幫助投資者簡化投資流程,達成長期穩定增長的財務目標。
Thumbnail
題目敘述 Find K-th Smallest Pair Distance 給定一個輸入陣列nums和 參數k。 請找出第k小的pair distance是多少? pair distance定義為 abs( nums[i] - nums[j]), i 不等於j 也就是任意兩陣列元素差值的絕對值
Thumbnail
分享一個猜數字的遊戲題目,給予提示讓玩家找出正確的四位數密碼。
Thumbnail
題目敘述 All Ancestors of a Node in a Directed Acyclic Graph 給定一個有向無環圖,請找出每個點的祖先,以陣列的形式返回答案。
Thumbnail
題目敘述 Combination Sum IV 給定一個輸入陣列nums,和目標值target,從nums裡面挑數字去湊出總和 = target,數字可以重複挑選。 請問有多少排列數可以湊出target? 註: 排列數的意思就是位置不同代表兩種不同的方法數。
Thumbnail
題目敘述 Distinct Subsequences 給定一個字串s和目標t,請問有多少個s的子序列可以完美匹配目標t ? 也就是說,有多少個s的子序列和目標t相等? 測試範例 Input: s = "rabbbit", t = "rabbit" Output: 3
Thumbnail
Minimum Path Sum 給定一個矩陣,每個格子點代表經過的對應成本。 每回合可以往右移動一格或往下移動一格。 請問從起點左上角 走到 終點右下角的最小路徑成本總和是多少?
Thumbnail
給定一個字串陣列,請把它們所共有的字元伴隨著出現次數輸出。這篇文章介紹如何使用字典統計出現次數,和字典取交集的方法來解決此問題。並提供了複雜度分析和關鍵知識點。
Thumbnail
題目敘述 題目會給我們一棵二元搜索樹的根結點root,還有一個指定的目標值val。 要求我們找出在樹中對應到目標值val的節點,假如找不到,請回傳null( null在Python就是None)。 題目的原文敘述 測試範例 Example 1: Input: root = [4,2,
Thumbnail
題目敘述 題目會給定我們一顆二元搜索樹BST的根結點, 還有一個指定區間的上邊界R 和 下邊界L。 請問二元搜索樹中,所有落在指定區間內的節點元素值的總和是多少? 題目的原文敘述 測試範例 Example 1: Input: root = [10,5,15,3,7,null,18], l