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

2021-01-09 阿里云云棲號

算法介紹

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 opencv 計算機視覺零基礎實戰」第一節
    前置條件說明:本系列opencv實戰教程將從基礎到實戰,若只是簡單學習完python也可以通過該教程完成一般的機器學習編程;文中將會對很多python的基礎內容進行講解,但由於文章定位的原因將不會贅述過多的基礎內容,基礎內容進行第一次講解後第二次將不會過多贅述,本文主要講解的是opencv相關知識。
  • Golang 會淘汰 Python 嗎?
    提供良好的代碼可讀性:Go語言所用的算法提供了一種極簡主義的方法,允許開發者輕鬆編寫可讀的代碼。Go語言的開發者可以輕鬆使用Go語言庫:大多Go語言的開發者不需要選擇其他程式語言所編寫的庫。Go擁有庫的核心優勢在於:使用Go語言的AI專業人士可以獲得開發者的舒適感。
  • 翼眸科技綜述面向無人機集群路徑規劃的智能優化算法
    智能優化算法因其對優化問題的性質要求低、魯棒性高,而被廣泛應用於求解路徑規劃問題.鑑於此, 本文綜述了近些年面向無人機集群路徑規劃的智能優化算法研究, 首先介紹了無人機集群路徑規劃的基本模型, 包括規劃空間表示、優化目標函數及約束條件等, 其次闡述了基於不同智能優化算法的無人機集群路徑規劃研究現狀、詳細對比分析了不同類型算法的優勢與不足, 最後對無人機集群路徑規劃研究進行了展望.
  • 圖的最短路徑算法-Floyd算法-弗洛伊德算法
    Floyd算法又稱為插點法,是一種利用動態規劃的思想尋找給定的加權圖中多源點之間最短路徑的算法 在計算機科學中,Floyd-Warshall算法是一種在具有正或負邊緣權重(但沒有負周期)的加權圖中找到最短路徑的算法。算法的單個執行將找到所有頂點對之間的最短路徑的長度(加權)。
  • 為什麼golang語言會變得越來越流行
    那麼為什麼這麼多公司選擇了go語言,為什麼這麼多開發者選擇了go語言,golang變得越來越流行的原因到底是什麼?簡潔性我們知道python如此流行的一方面是它有著豐富的擴展庫,幾乎我們平時常用的功能,都有非常強大的第三方擴展庫供我們使用,另一方面就是它的語法簡潔,對比於java的代碼,同樣的功能,python使用的代碼相比之要少得太多了。
  • 自動駕駛實時路徑規划算法簡介(Local search局部搜索)
    在上一節自動駕駛實時路徑規划算法簡介(RRT 和Lattice Planner)中介紹了找到車輛要遵循的最佳幾何路徑有兩個方法:a) 通過增量採樣或離散幾何結構(即增量搜索)找到最佳的動作序列。b) 從多個最終狀態中找到最佳操作(即局部搜索)。
  • 盤點職業生涯規劃教育實施路徑
    學校開展職業生涯規劃教育是非常有必要的,但是實施生涯教育要有計劃、有組織、有系統地落實。本文從學校層面簡要分析開展高中生職業生涯規劃實施路徑。 1 、開展職業生涯規劃課程教學。學校開設職業生涯規劃教育課程,必須將課程納入課程體系之中,通過傳授生涯規劃教育的理念、知識理論與策略方法等,從而喚醒學生生涯規劃的意識和培養學生自我生涯規劃的能力。2、開展生涯規劃專題講座與輔導。
  • 菜鳥路徑規划算法入圍全球最高工業獎項
    12月10日,美國運籌學與管理科學學會信息顯示,以菜鳥人工智慧團隊為核心研發的物流路徑規划算法,已經入圍2021年Franz Edelman傑出成就獎。這是全球運籌和管理科學界的最高工業應用獎,被稱為運籌學的「奧斯卡」。獎項設立50年來,首次有中國物流供應鏈領域企業入圍。
  • 短小精悍的多源最短路徑算法—Floyd算法
    在圖論中,在尋路最短路徑中除了Dijkstra算法以外,還有Floyd算法也是非常經典,然而兩種算法還是有區別的,Floyd主要計算多源最短路徑。在單源正權值最短路徑,我們會用Dijkstra算法來求最短路徑,並且算法的思想很簡單——貪心算法:每次確定最短路徑的一個點然後維護(更新)這個點周圍點的距離加入預選隊列,等待下一次的拋出確定。但是雖然思想很簡單,實現起來是非常複雜的,我們需要鄰接矩陣(表)儲存長度,需要優先隊列(或者每次都比較)維護一個預選點的集合。
  • 數據分析:R與Python怎麼選?
    R和Python 都是高級分析工具,各自都有眾多的簇擁者和強大的社區支持,在網絡爬蟲、數據加工、數據可視化、統計分析、機器學習、深度學習等領域都有豐富第三方包提供調用。以下羅列R和python在各數據工作領域的資料信息,看看它們都有啥?
  • 算法應用|機器學習python應用,初識機器學習是怎樣滴感受?
    每個算法模型都介紹其較為通用且實用的建模過程,力爭使基礎較差的讀者也能無障礙利用python來使用機器學習算法。1 初識機器學習1.1 什麼是機器學習?機器學習(Machine Leaming , ML)是一門多領域的交叉學科,涉及概率論、統計學、線性代數、算法等多門學科。 它專門研究計算機如何模擬和學習人的行為,以獲取新的知識或技能,重新組織已有的知識結構使之不斷完善自身的性能。
  • 《前端5分鐘》之使用解釋器模式實現獲取元素Xpath路徑的算法
    本文轉載自【微信公眾號:趣談前端,ID:beautifulFront】經微信公眾號授權轉載,如需轉載與原文作者聯繫前端領域裡基於javascript的設計模式和算法有很多,在很多複雜應用中也扮演著很重要的角色,接下來就介紹一下javascript設計模式中的解釋器模式,並用它來實現一個獲取元素Xpath路徑的算法
  • Python爬蟲實戰 | 只需 「4步」 入門網絡爬蟲(有福利哦)
    在python程序裡面,上述過程可以通過獲取網頁中的原始碼實現,進而獲得網頁中的數據。上面的網頁原始碼,在python語言中,我們只需要使用urllib、requests等庫實現即可,具體如下。這裡特別說明一些,requests比urllib更加方便、快捷。一旦學會requests庫,肯定會愛不釋手。
  • 十大編程算法
    算法步驟:創建一個堆H[0..n-1]把堆首(最大值)和堆尾互換3. 把堆的尺寸縮小1,並調用shift_down(0),目的是把新的數組頂端數據調整到相應位置4. 重複步驟2,直到堆的尺寸為1迪科斯徹算法使用了廣度優先搜索解決非負權有向圖的單源最短路徑問題,算法最終得到一個最短路徑樹。該算法常用於路由算法或者作為其他圖算法的一個子模塊。該算法的輸入包含了一個有權重的有向圖 G,以及G中的一個來源頂點 S。我們以 V 表示 G 中所有頂點的集合。每一個圖中的邊,都是兩個頂點 所形成的有序元素對。(u, v) 表示從頂點 u 到 v 有路徑相連。
  • 從0 到 1:全面理解 RPC 遠程調用!
    那 python 如何實現基於 json-rpc 協議呢?集群有可能根據實際需要擴充節點數量,如果使用直接調用,耦合度太高,不利於部署和生產。這是問題三。引入消息中間件,可以很好的解決這些問題。解決問題一:消息只有一份,接收者由AMQP的負載算法決定,默認為在所有Receiver中均勻發送(round robin)。
  • 從算法層解讀,自動駕駛的「軌跡規劃」是如何實現的?
    車輛路徑規劃問題中路網模型、路徑規划算法和交通信息的智能預測為關鍵點。路徑規劃是智能車輛導航和控制的基礎,是從軌跡決策的角度考慮的,可分為局部路徑規劃和全局路徑規劃。 全局路徑規劃的任務是根據全局地圖資料庫信息規劃出自起始點至目標點的一條無碰撞、可通過的路徑。目前正在研究的有準結構化道路環境多種約束條件下的路徑規劃技術,自然地形環境下的路徑規劃技術,以及重規劃技術等。
  • Python 30 個技巧
    列印引入模塊的文件路徑如果你想知道引用到代碼中模塊的絕對路徑,可以使用下面的技巧:import threadingimport socket print(threading)print(socket) #1- <module 'threading' from '/usr/lib/python2.7
  • Python實戰 | 只需 「4步」 入門網絡爬蟲
    JSON在python中分別由list和dict組成。Python官方json網址是  https://docs.python.org/3/library/json.html?1、python的數字類型分為整型、長整型、浮點型、布爾型、複數類型。2、python沒有字符類型3、python內部沒有普通類型,任何類型都是對象。4、如果需要查看變量的類型,可以使用type類,該類可以返回變量的類型或創建一個新的類型。5、python有3種表示字符串類型的方式,即單引號、雙引號、三引號。
  • ️國粹——中國象棋震撼來襲,python的趕緊上車️
    中國象棋想必大家都玩過,突發奇想,想著怎麼用python把中國國粹的中國象棋做出來呢??????教你如何用python輕輕鬆鬆操作Excel、Word、CSV,一文就夠了,趕緊碼住!!!程式設計師一般喜歡瀏覽的40個網站,屯了這麼多年,我就不藏私了,個人強烈推薦基於混沌Logistic加密算法的圖片加密與還原教你用python編寫二十幾行的代碼繪製動態煙花python錯誤:AttributeError: 『module『 object has no attribute 『xxxxx『,10種總結(成功解決)
  • Python生成一維碼,二維碼
    我們的生活已完全離不開一維碼和二維碼,本文會簡單的介紹如果通過python的方法來生成它們