golang 調用 python 實戰路徑規劃之 A* 算法

2021-01-08 阿里云云棲號

算法介紹

A*(念做:A Star)算法是一種很常用的路徑查找和圖形遍歷算法。它有較好的性能和準確度。本文在講解算法的同時也會提供Python語言的代碼實現,並會藉助matplotlib庫動態的展示算法的運算過程。

A*算法最初發表於1968年,由Stanford研究院的Peter Hart, Nils Nilsson以及Bertram Raphael發表。它可以被認為是Dijkstra算法的擴展。

由於藉助啟發函數的引導,A*算法通常擁有更好的性能。

廣度優先搜索

為了更好的理解A*算法,我們首先從廣度優先(Breadth First)算法講起。

正如其名稱所示,廣度優先搜索以廣度做為優先級進行搜索。

從起點開始,首先遍歷起點周圍鄰近的點,然後再遍歷已經遍歷過的點鄰近的點,逐步的向外擴散,直到找到終點。

這種算法就像洪水(Flood fill)一樣向外擴張,算法的過程如下圖所示:

在上面這幅動態圖中,算法遍歷了圖中所有的點,這通常沒有必要。對於有明確終點的問題來說,一旦到達終點便可以提前終止算法,下面這幅圖對比了這種情況:

在執行算法的過程中,每個點需要記錄達到該點的前一個點的位置 -- 可以稱之為父節點。這樣做之後,一旦到達終點,便可以從終點開始,反過來順著父節點的順序找到起點,由此就構成了一條路徑。

Dijkstra算法

Dijkstra算法是由計算機科學家Edsger W. Dijkstra在1956年提出的。

Dijkstra算法用來尋找圖形中節點之間的最短路徑。

考慮這樣一種場景,在一些情況下,圖形中相鄰節點之間的移動代價並不相等。例如,遊戲中的一幅圖,既有平地也有山脈,那麼遊戲中的角色在平地和山脈中移動的速度通常是不相等的。

在Dijkstra算法中,需要計算每一個節點距離起點的總移動代價。同時,還需要一個優先隊列結構。對於所有待遍歷的節點,放入優先隊列中會按照代價進行排序。

在算法運行的過程中,每次都從優先隊列中選出代價最小的作為下一個遍歷的節點。直到到達終點為止。

下面對比了不考慮節點移動代價差異的廣度優先搜索與考慮移動代價的Dijkstra算法的運算結果:

當圖形為網格圖,並且每個節點之間的移動代價是相等的,那麼Dijkstra算法將和廣度優先算法變得一樣。

最佳優先搜索

在一些情況下,如果我們可以預先計算出每個節點到終點的距離,則我們可以利用這個信息更快的到達終點。

其原理也很簡單。與Dijkstra算法類似,我們也使用一個優先隊列,但此時以每個節點到達終點的距離作為優先級,每次始終選取到終點移動代價最小(離終點最近)的節點作為下一個遍歷的節點。這種算法稱之為最佳優先(Best First)算法。

這樣做可以大大加快路徑的搜索速度,如下圖所示:

但這種算法會不會有什麼缺點呢?答案是肯定的。

因為,如果起點和終點之間存在障礙物,則最佳優先算法找到的很可能不是最短路徑,下圖描述了這種情況。

A*算法

對比了上面幾種算法,最後終於可以講解本文的重點:A*算法了。

下面的描述我們將看到,A*算法實際上是綜合上面這些算法的特點於一身的。

A*算法通過下面這個函數來計算每個節點的優先級。

f(n)=g(n)+h(n)

其中:

$f(n)$ 是節點n的綜合優先級。當我們選擇下一個要遍歷的節點時,我們總會選取綜合優先級最高(值最小)的節點。$g(n)$ 是節點n距離起點的代價。$h(n)$ 是節點n距離終點的預計代價,這也就是A*算法的啟發函數。關於啟發函數我們在下面詳細講解。A*算法在運算過程中,每次從優先隊列中選取$f(n)$值最小(優先級最高)的節點作為下一個待遍歷的節點。

另外,A*算法使用兩個集合來表示待遍歷的節點,與已經遍歷過的節點,這通常稱之為open_set和close_set。

完整的A*算法描述如下:

* 初始化open_set和close_set;* 將起點加入open_set中,並設置優先級為0(優先級最高);* 如果open_set不為空,則從open_set中選取優先級最高的節點n: * 如果節點n為終點,則: * 從終點開始逐步追蹤parent節點,一直達到起點; * 返回找到的結果路徑,算法結束; * 如果節點n不是終點,則: * 將節點n從open_set中刪除,並加入close_set中; * 遍歷節點n所有的鄰近節點: * 如果鄰近節點m在close_set中,則: * 跳過,選取下一個鄰近節點 * 如果鄰近節點m也不在open_set中,則: * 設置節點m的parent為節點n * 計算節點m的優先級 * 將節點m加入open_set中啟發函數

上面已經提到,啟發函數會影響A*算法的行為。

在極端情況下,當啟發函數$h(n)$始終為0,則將由$g(n)$決定節點的優先級,此時算法就退化成了Dijkstra算法。如果$h(n)$始終小於等於節點n到終點的代價,則A*算法保證一定能夠找到最短路徑。但是當$h(n)$的值越小,算法將遍歷越多的節點,也就導致算法越慢。如果$h(n)$完全等於節點n到終點的代價,則A*算法將找到最佳路徑,並且速度很快。可惜的是,並非所有場景下都能做到這一點。因為在沒有達到終點之前,我們很難確切算出距離終點還有多遠。如果$h(n)$的值比節點n到終點的代價要大,則A*算法不能保證找到最短路徑,不過此時會很快。在另外一個極端情況下,如果$h(n)$相較於$g(n)$大很多,則此時只有$h(n)$產生效果,這也就變成了最佳優先搜索。由上面這些信息我們可以知道,通過調節啟發函數我們可以控制算法的速度和精確度。因為在一些情況,我們可能未必需要最短路徑,而是希望能夠儘快找到一個路徑即可。這也是A*算法比較靈活的地方。

對於網格形式的圖,有以下這些啟發函數可以使用:

如果圖形中只允許朝上下左右四個方向移動,則可以使用曼哈頓距離(Manhattan distance)。如果圖形中允許朝八個方向移動,則可以使用對角距離。如果圖形中允許朝任何方向移動,則可以使用歐幾裡得距離(Euclidean distance)。關於距離

曼哈頓距離

如果圖形中只允許朝上下左右四個方向移動,則啟發函數可以使用曼哈頓距離,它的計算方法如下圖所示:

計算曼哈頓距離的函數如下,這裡的D是指兩個相鄰節點之間的移動代價,通常是一個固定的常數。

function heuristic(node) = dx = abs(node.x - goal.x) dy = abs(node.y - goal.y) return D * (dx + dy)對角距離

如果圖形中允許斜著朝鄰近的節點移動,則啟發函數可以使用對角距離。它的計算方法如下:

計算對角距離的函數如下,這裡的D2指的是兩個斜著相鄰節點之間的移動代價。如果所有節點都正方形,則其值就是$\sqrt{2} * D$。

function heuristic(node) = dx = abs(node.x - goal.x) dy = abs(node.y - goal.y) return D * (dx + dy) + (D2 - 2 * D) * min(dx, dy)歐幾裡得距離

如果圖形中允許朝任意方向移動,則可以使用歐幾裡得距離。

歐幾裡得距離是指兩個節點之間的直線距離,因此其計算方法也是我們比較熟悉的:$\sqrt{(p2.x-p1.x)^2 + (p2.y-p1.y)^2}$。其函數表示如下:

function heuristic(node) = dx = abs(node.x - goal.x) dy = abs(node.y - goal.y) return D * sqrt(dx * dx + dy * dy)算法實現

雖然前面介紹了很多內容,但實際上A*算法並不複雜,實現起來也比較簡單。

下面我們給出一個Python語言的代碼示例。

之所以使用Python語言是因為我們可以藉助matplotlib庫很方便的將結果展示出來。在理解了算法之後,通過其他語言實現也並非難事。

算法的源碼可以到我的github上下載:paulQuei/a-star-algorithm。

我們的算法演示的是在一個二維的網格圖形上從起點找尋終點的求解過程。

坐標點與地圖

首先,我們創建一個非常簡單的類來描述圖中的點,相關代碼如下:

# point.pyimport sysclass Point: def __init__(self, x, y): self.x = x self.y = y self.cost = sys.maxsize接著,我們實現一個描述地圖結構的類。為了簡化算法的描述:

我們選定左下角坐標[0, 0]的點是算法起點,右上角坐標[size - 1, size - 1]的點為要找的終點。

為了讓算法更有趣,我們在地圖的中間設置了一個障礙,並且地圖中還會包含一些隨機的障礙。該類的代碼如下:

# random_map.pyimport numpy as npimport pointclass RandomMap: def __init__(self, size=50): ① self.size = size self.obstacle = size//8 ② self.GenerateObstacle() ③ def GenerateObstacle(self): self.obstacle_point = [] self.obstacle_point.append(point.Point(self.size//2, self.size//2)) self.obstacle_point.append(point.Point(self.size//2, self.size//2-1)) # Generate an obstacle in the middle for i in range(self.size//2-4, self.size//2): ④ self.obstacle_point.append(point.Point(i, self.size-i)) self.obstacle_point.append(point.Point(i, self.size-i-1)) self.obstacle_point.append(point.Point(self.size-i, i)) self.obstacle_point.append(point.Point(self.size-i, i-1)) for i in range(self.obstacle-1): ⑤ x = np.random.randint(0, self.size) y = np.random.randint(0, self.size) self.obstacle_point.append(point.Point(x, y)) if (np.random.rand() > 0.5): # Random boolean ⑥ for l in range(self.size//4): self.obstacle_point.append(point.Point(x, y+l)) pass else: for l in range(self.size//4): self.obstacle_point.append(point.Point(x+l, y)) pass def IsObstacle(self, i ,j): ⑦ for p in self.obstacle_point: if i==p.x and j==p.y: return True return False這段代碼說明如下:

構造函數,地圖的默認大小是50x50;設置障礙物的數量為地圖大小除以8;調用GenerateObstacle生成隨機障礙物;在地圖的中間生成一個斜著的障礙物;隨機生成其他幾個障礙物;障礙物的方向也是隨機的;定義一個方法來判斷某個節點是否是障礙物;算法主體

有了基本的數據結構之後,我們就可以開始實現算法主體了。

這裡我們通過一個類來封裝我們的算法。

首先實現一些算法需要的基本函數,它們如下:

# a_star.pyimport sysimport timeimport numpy as npfrom matplotlib.patches import Rectangleimport pointimport random_mapclass AStar: def __init__(self, map): self.map=map self.open_set = [] self.close_set = [] def BaseCost(self, p): x_dis = p.x y_dis = p.y # Distance to start point return x_dis + y_dis + (np.sqrt(2) - 2) * min(x_dis, y_dis) def HeuristicCost(self, p): x_dis = self.map.size - 1 - p.x y_dis = self.map.size - 1 - p.y # Distance to end point return x_dis + y_dis + (np.sqrt(2) - 2) * min(x_dis, y_dis) def TotalCost(self, p): return self.BaseCost(p) + self.HeuristicCost(p) def IsValidPoint(self, x, y): if x < 0 or y < 0: return False if x >= self.map.size or y >= self.map.size: return False return not self.map.IsObstacle(x, y) def IsInPointList(self, p, point_list): for point in point_list: if point.x == p.x and point.y == p.y: return True return False def IsInOpenList(self, p): return self.IsInPointList(p, self.open_set) def IsInCloseList(self, p): return self.IsInPointList(p, self.close_set) def IsStartPoint(self, p): return p.x == 0 and p.y ==0 def IsEndPoint(self, p): return p.x == self.map.size-1 and p.y == self.map.size-1這裡的函數說明如下:

__init__:類的構造函數。BaseCost:節點到起點的移動代價,對應了上文的$g(n)$。HeuristicCost:節點到終點的啟發函數,對應上文的$h(n)$。由於我們是基於網格的圖形,所以這個函數和上一個函數用的是對角距離。TotalCost:代價總和,即對應上面提到的$f(n)$。IsValidPoint:判斷點是否有效,不在地圖內部或者障礙物所在點都是無效的。IsInPointList:判斷點是否在某個集合中。IsInOpenList:判斷點是否在open_set中。IsInCloseList:判斷點是否在close_set中。IsStartPoint:判斷點是否是起點。IsEndPoint:判斷點是否是終點。有了上面這些輔助函數,就可以開始實現算法主邏輯了,相關代碼如下:

# a_star.pydef RunAndSaveImage(self, ax, plt): start_time = time.time() start_point = point.Point(0, 0) start_point.cost = 0 self.open_set.append(start_point) while True: index = self.SelectPointInOpenList() if index < 0: print('No path found, algorithm failed!!!') return p = self.open_set[index] rec = Rectangle((p.x, p.y), 1, 1, color='c') ax.add_patch(rec) self.SaveImage(plt) if self.IsEndPoint(p): return self.BuildPath(p, ax, plt, start_time) del self.open_set[index] self.close_set.append(p) # Process all neighbors x = p.x y = p.y self.ProcessPoint(x-1, y+1, p) self.ProcessPoint(x-1, y, p) self.ProcessPoint(x-1, y-1, p) self.ProcessPoint(x, y-1, p) self.ProcessPoint(x+1, y-1, p) self.ProcessPoint(x+1, y, p) self.ProcessPoint(x+1, y+1, p) self.ProcessPoint(x, y+1, p)這段代碼應該不需要太多解釋了,它就是根據前面的算法邏輯進行實現。為了將結果展示出來,我們在算法進行的每一步,都會藉助於matplotlib庫將狀態保存成圖片。

上面這個函數調用了其他幾個函數代碼如下:

# a_star.pydef SaveImage(self, plt): millis = int(round(time.time() * 1000)) filename = './' + str(millis) + '.png' plt.savefig(filename)def ProcessPoint(self, x, y, parent): if not self.IsValidPoint(x, y): return # Do nothing for invalid point p = point.Point(x, y) if self.IsInCloseList(p): return # Do nothing for visited point print('Process Point [', p.x, ',', p.y, ']', ', cost: ', p.cost) if not self.IsInOpenList(p): p.parent = parent p.cost = self.TotalCost(p) self.open_set.append(p)def SelectPointInOpenList(self): index = 0 selected_index = -1 min_cost = sys.maxsize for p in self.open_set: cost = self.TotalCost(p) if cost < min_cost: min_cost = cost selected_index = index index += 1 return selected_indexdef BuildPath(self, p, ax, plt, start_time): path = [] while True: path.insert(0, p) # Insert first if self.IsStartPoint(p): break else: p = p.parent for p in path: rec = Rectangle((p.x, p.y), 1, 1, color='g') ax.add_patch(rec) plt.draw() self.SaveImage(plt) end_time = time.time() print('===== Algorithm finish in', int(end_time-start_time), ' seconds')這三個函數應該是比較容易理解的:

SaveImage:將當前狀態保存到圖片中,圖片以當前時間命名。ProcessPoint:針對每一個節點進行處理:如果是沒有處理過的節點,則計算優先級設置父節點,並且添加到open_set中。SelectPointInOpenList:從open_set中找到優先級最高的節點,返回其索引。BuildPath:從終點往回沿著parent構造結果路徑。然後從起點開始繪製結果,結果使用綠色方塊,每次繪製一步便保存一個圖片。測試入口

最後是程序的入口邏輯,使用上面寫的類來查找路徑:

# main.pyimport numpy as npimport matplotlib.pyplot as pltfrom matplotlib.patches import Rectangleimport random_mapimport a_starplt.figure(figsize=(5, 5))map = random_map.RandomMap() ①ax = plt.gca()ax.set_xlim([0, map.size]) ②ax.set_ylim([0, map.size])for i in range(map.size): ③ for j in range(map.size): if map.IsObstacle(i,j): rec = Rectangle((i, j), width=1, height=1, color='gray') ax.add_patch(rec) else: rec = Rectangle((i, j), width=1, height=1, edgecolor='gray', facecolor='w') ax.add_patch(rec)rec = Rectangle((0, 0), width = 1, height = 1, facecolor='b')ax.add_patch(rec) ④rec = Rectangle((map.size-1, map.size-1), width = 1, height = 1, facecolor='r')ax.add_patch(rec) ⑤plt.axis('equal') ⑥plt.axis('off')plt.tight_layout()#plt.show()a_star = a_star.AStar(map)a_star.RunAndSaveImage(ax, plt) ⑦這段代碼說明如下:

創建一個隨機地圖;設置圖像的內容與地圖大小一致;繪製地圖:對於障礙物繪製一個灰色的方塊,其他區域繪製一個白色的的方塊;繪製起點為藍色方塊;繪製終點為紅色方塊;設置圖像的坐標軸比例相等並且隱藏坐標軸;調用算法來查找路徑;由於我們的地圖是隨機的,所以每次運行的結果可能會不一樣,下面是我的電腦上某次運行的結果:

算法變種

A*算法有不少的變種,這裡我們介紹最主要的幾個。

ARA*

ARA 全稱是Anytime Repairing A*,也稱為Anytime A。

與其他Anytime算法一樣,它具有靈活的時間成本,即使在它結束之前被中斷,也可以返迴路徑查找或圖形遍歷問題的有效解決方案。方法是在逐步優化之前生成快速,非最優的結果。

在現實世界的規劃問題中,問題的解決時間往往是有限的。與時間相關的規劃者對這種情況都會比較熟悉:他們能夠快速找到可行的解決方案,然後不斷努力改進,直到時間用完為止。

啟發式搜索ARA*算法,它根據可用的搜索時間調整其性能邊界。它首先使用鬆散邊界快速找到次優解,然後在時間允許的情況下逐漸收緊邊界。如果有足夠的時間,它會找到可證明的最佳解決方方案。在改進其約束的同時,ARA*重複使用以前的搜索工作,因此,比其他隨時搜索方法更有效。

與A*算法不同,Anytime A*算法最重要的功能是,它們可以被停止,然後可以隨時重啟。該方法使用控制管理器類來處理時間限制以及停止和重新啟動A*算法以找到初始的,可能是次優的解決方案,然後繼續搜索改進的解決方案,直到達到可證明的最佳解決方案。

D*

D*是Dynamic A*的簡寫,其算法和A*類似,不同的是,其代價的計算在算法運行過程中可能會發生變化。

D*包含了下面三種增量搜索算法:

原始的D*由Anthony Stentz發表。Focussed D*由Anthony Stentz發表,是一個增量啟發式搜索算法,結合了A*和原始D*的思想。D Lite是由Sven Koenig和Maxim Likhachev基於LPA構建的算法。所有三種搜索算法都解決了相同的基於假設的路徑規劃問題,包括使用自由空間假設進行規劃。在這些環境中,機器人必須導航到未知地形中的給定目標坐標。它假設地形的未知部分(例如:它不包含障礙物),並在這些假設下找到從當前坐標到目標坐標的最短路徑。

然後機器人沿著路逕行進。當它觀察到新的地圖信息(例如以前未知的障礙物)時,它會將信息添加到其地圖中,並在必要時將新的最短路徑從其當前坐標重新添加到給定的目標坐標。它會重複該過程,直到達到目標坐標或確定無法達到目標坐標。在穿越未知地形時,可能經常發現新的障礙,因此重新計劃需要很快。增量(啟發式)搜索算法通過使用先前問題的經驗來加速搜索當前問題,從而加速搜索類似搜索問題的序列。假設目標坐標沒有改變,則所有三種搜索算法都比重複的A*搜索更有效。

D*及其變體已廣泛用於移動機器人和自動車輛導航。當前系統通常基於D* Lite而不是原始D*或Focussed D*。

Field D*

Field D*擴展了D*和D* Lite,是一種基於插值( interpolation-based )的規划算法,它使用線性插值來有效地生成低成本路徑,從而消除不必要的轉向。

在給定線性插值假設的情況下,路徑是最優的,並且在實踐中非常有效。該算法目前被各種現場機器人系統使用。

Block A*

Block A*擴展自A*,但它操作是一塊(block)單元而不是單個單元。

其open_set中的每個條目都是已到達但尚未擴展的塊,或者需要重新擴展的塊。

open_set中塊的優先級稱為其堆值(heap value)。與A*類似,Block A*中的基本循環是刪除具有最低堆值的條目並將其展開。在擴展期間使用LDDB來計算正在擴展的塊中的邊界單元的g值。

LDDB是一種新型資料庫,它包含了本地鄰域邊界點之間的距離。

本文為阿里雲原創內容,未經允許不得轉載。

相關焦點

  • Python編寫遺傳算法實戰,整數編碼,啟發式搜索解決旅行商問題
    上一篇寫了遺傳算法的原理,這一篇寫遺傳算法解決旅行商問題的實戰,而且使用python編寫。近幾年python越來越受歡迎,其中主要是簡單易學和上手快,並且編代碼的效率高,甚至有人喊出「人生苦短,我要用python」的口號,所以小編也來湊湊熱鬧。
  • 遺傳算法Python實戰 012.旅行商問題
    簡單來說,Travelling Salesman Problem (TSP) 是最基本的路線規劃問題。它尋求的是旅行者由起點出發,通過所有給定的需求點後,再次返回起點,求在這個過程中,所花費的最小路徑成本。
  • 好程式設計師Python培訓分享Python如何調用RPC接口
    Python如何調用RPC接口是很多Python開發工程師比較關心的問題,本篇文章好程式設計師Python培訓小編就給喜歡Python開發的小夥伴們分享一下Python調用RPC接口的詳解,文中有詳細的代碼列出有很好的參考價值,喜歡的小夥伴就隨小編一起來看一下吧,希望對大家有所幫助。
  • PySpark源碼解析,用Python調用高效Scala接口,搞定大規模數據分析
    機器之心專欄作者:匯量科技-陳緒相較於Scala語言而言,Python具有其獨有的優勢及廣泛應用性,因此Spark也推出了PySpark,在框架上提供了利用Python語言的接口,為數據科學家使用該框架提供了便利。
  • 為什麼golang語言會變得越來越流行
    那麼為什麼這麼多公司選擇了go語言,為什麼這麼多開發者選擇了go語言,golang變得越來越流行的原因到底是什麼?簡潔性我們知道python如此流行的一方面是它有著豐富的擴展庫,幾乎我們平時常用的功能,都有非常強大的第三方擴展庫供我們使用,另一方面就是它的語法簡潔,對比於java的代碼,同樣的功能,python使用的代碼相比之要少得太多了。
  • Python和人工智慧有什麼關係?Python 和人工智慧的區別是什麼?
    人工智慧人工智慧是一個大的概念,在人工智慧下有計算機視覺,語音識別,自然語言處理等不同的技術領域,這些技術領域中在Github上又有許多開源的代碼可以直接用來開發,而這些代碼往往需要或者只支持Python進行調用
  • 菜鳥路徑規划算法入圍全球最高工業獎項
    12月10日,美國運籌學與管理科學學會信息顯示,以菜鳥人工智慧團隊為核心研發的物流路徑規划算法,已經入圍2021年Franz Edelman傑出成就獎。這是全球運籌和管理科學界的最高工業應用獎,被稱為運籌學的「奧斯卡」。獎項設立50年來,首次有中國物流供應鏈領域企業入圍。
  • Python開發簡單爬蟲【學習資料總結】
    python語言高級:(python語言的高級庫,常用的企業級開發案例實戰) (1)Python常見第三方庫與網絡編程 (2)面向對象,Python正則表達式 (3)求職數據爬蟲,金融數據爬蟲,多線程爬蟲 (4)Python
  • 翼眸科技綜述面向無人機集群路徑規劃的智能優化算法
    智能優化算法因其對優化問題的性質要求低、魯棒性高,而被廣泛應用於求解路徑規劃問題.鑑於此, 本文綜述了近些年面向無人機集群路徑規劃的智能優化算法研究, 首先介紹了無人機集群路徑規劃的基本模型, 包括規劃空間表示、優化目標函數及約束條件等, 其次闡述了基於不同智能優化算法的無人機集群路徑規劃研究現狀、詳細對比分析了不同類型算法的優勢與不足, 最後對無人機集群路徑規劃研究進行了展望.
  • python爬蟲之selenium抓取淘寶商品信息
    簡介本節採用python爬蟲相關技術獲取淘寶商品信息。採用的技術有selenium、pyquery及urllib.parse等。下圖是電腦谷歌瀏覽器地址,然後我們下載對應版本的chromedriver.exe放到python安裝路徑的scripts目錄下。然後使用下述簡單代碼驗證環境是否準備完畢。
  • 慕課網Python課程帶你入門機器學習
    人工智慧系統0.2秒就能計算出680億條路徑、亞洲一號倉庫每天包裹量可達20萬個、無人化倉庫效率為傳統倉庫的10倍。這一個個數字不斷刷新的秘密武器,便是人工智慧領域的機器學習。根據《2018中國人工智慧發展報告》相關數據顯示,人工智慧行業的融資規模呈上升趨勢。在火熱的人工智慧領域裡,機器學習作為該領域的核心技術,對於人工智慧的現實應用具有重要意義。
  • 算法圖解(六)| 廣度優先搜索算法
    你希望從最短的路徑,花最少的時間到達金山大橋,按照這個圖,你需要走最少三步,這就是最短路徑,如下所示:6.3、廣度優先搜索解決最短路徑問題的算法被稱為廣度優先搜索,廣度優先搜索是一種用於圖的查找算法,可回答兩類問題
  • 自我代碼提升之啟發式算法(番外篇)
    類TSP問題的實踐這次對算法時間的場景是一種經典的優化問題——旅行商問題(TSP)。假設有一個旅行商人要拜訪n個城市,從一座指定的城市出發,而終點也被指定(通常回到起點)。他必須選擇所要走的路徑,路徑的限制是每個城市必須拜訪且只能拜訪一次。如何去選擇一條最短的路徑。
  • 自動駕駛實時路徑規划算法簡介(Local search局部搜索)
    在上一節自動駕駛實時路徑規划算法簡介(RRT 和Lattice Planner)中介紹了找到車輛要遵循的最佳幾何路徑有兩個方法:a) 通過增量採樣或離散幾何結構(即增量搜索)找到最佳的動作序列。b) 從多個最終狀態中找到最佳操作(即局部搜索)。
  • 介紹一下什麼是python(瘋狂Python)
    去python官網就能下載你所需要安裝的版本,安裝方法也可以百度一下(或者關注我私信我),讓你眼花繚亂的各種安裝介紹,保證你自己能安上。(我用的版本是Winodws版本)5.查看python版本以Windows為例,其他系統查看的python方法不做贅述,可自行百度一下打開cmd命令行(快捷鍵:Win + R鍵 同時按)輸入Python -V,就能返回電腦中安裝的python
  • Golang unsafe.Pointer使用原則以及 uintptr 隱藏的坑
    我們可以將一個值的指針傳遞給runtime.KeepAlive函數調用來確保此值在此調用之前仍然處於被使用中為了確保一個值部和它所引用著的值部仍然被認為在使用中,我們應該將引用著此值的另一個值傳給一個runtime.KeepAlive函數調用。在實踐中,我們常常將此值的指針傳遞給一個runtime.KeepAlive函數調用。
  • 基於規則的預測算法和基於機器學習的預測算法
    Apollo 障礙物行為預測系統採用 MLP 多層感知機制,通過深度神經網絡與規划算法,達到精準預測路徑的目的。 為了方便起見,我們把阿波羅作為本地阿波羅儲存庫的路徑,例如,/home/username/apollo 如果用來存儲離線預測數據的文件夾不存在的話,則使用命令 mkdir APOLLO/data/prediction 創建一個新文件夾 打開apollo/modules/prediction/conf/prediction.conf.通過改變--
  • python數據分析:如何用python做路徑分析,附資料庫實例操練
    最近在學習結構方程模型,因為是個新東西,自己做畢業論文也得用,所以最近更新很慢,大家見諒,最近會給大家寫一些自己理解的結構方程模型的東西,和python做法,今天主要是寫路徑分析。  路徑分析簡介  路徑分析其實是結構方程模型的一部分。
  • 算法|Python-BFS算法舉例分析
    問題描述BFS算法,也稱作廣度優先搜索算法。是一種圖形搜索演算法。簡單的說,BFS是從根節點開始,沿著樹的寬度遍歷樹的節點,如果發現目標,則演算終止。(百度百科)舉例分析:先用一個樹結構來說明bfs算法的搜索規律如果上圖要用bfs算法的話。
  • 2019 年 Python、Golang、Java、C++、Rust 該如何選擇?
    walle 讓用戶代碼發布終於可以不只能選擇 Jenkins,支持各種web代碼發布,php、java、python、go等代碼的發布、回滾可以通過web來一鍵完成。通過實戰項目練習解決一般爬蟲中遇到的問題。通過每個項目的readme,了解爬取過程分析。對於精通爬蟲的pyer,這將是一個很好的例子減少重複收集輪子的過程。項目經常更新維護,確保即下即用,減少爬取的時間。對於小白通過實戰項目,了解爬蟲的從無到有。爬蟲知識構建可以移步項目wiki。