前面介紹了關於雙向及啟發式的搜尋,它們均可以實現了效率的倍增。但是應用到長距離(例如武漢——杭州大於500公里)的搜尋時,平均效率存在100ms級甚至s級的耗時,顯然這樣乙個面對廣大使用者群的網際網路服務引擎效率是不可接受的,那麼有沒有優化的方向可以實現數量級的提公升?
但人類對效率與正確的極致追求也是不止境的。關於雙向及啟發式搜尋,它們的優化初衷均是一致的:縮短搜尋範圍。有人想到另乙個路網搜尋優化的方向:稀疏搜尋路網密度——分層演算法。
路網由一堆節點和邊組成。路網最優路徑的搜尋耗時,是與節點和邊規模的平方成正比的。其演算法設計初衷計算任意節點對最優路徑時,在盡量稀疏的路網上進行搜尋,來降低路網搜尋規模,而又能同時保證結果的最優正確性。
a 預處理階段:採取分層的方法不斷迭代,當前層的路網是由低一層的路網不斷進行乾掉拓撲點和邊,生成新的邏輯路網的結果。
並且每一層邏輯路網滿足下面兩個性質:
條件1:每一層的邏輯路網是其低一層邏輯路網的子集
條件2:每一層的邏輯路網中,任意拓撲點對的最優路徑,一定屬於當前層。
b 實時查詢階段:在邏輯路網上進行最優路徑的查詢(比原始路網搜尋快近1000倍)
預處理的過程:基於當前路網不斷迭代,進行乾掉拓撲點和邊生成更高層邏輯路網的過程。
3.3.1乾掉節點(contract_node)
a 背景
試圖思考下,我們乾掉乙個節點時,其入邊和出邊也相應的也會乾掉了,但為了保證拓撲的完整性,會增加相應的邏輯邊。
如果乙個節點node,其入邊個數和出邊個數分別是ndegin和ndegout,contract其node時,去掉了其入邊和出邊的個數是(ndegin+ndegout),而最壞情況下,會引入的邏輯邊的個數是indeg*outdeg。顯然,如果ndegin與ndegout均大於1時,值ndegin*ndegout大於值(indeg+outdeg)的,並且ndegin和ndegout越大,其差值越大。
b 條件
現在的矛盾:我們想去掉一些不是那麼重要的節點,而又不想引入更多的邏輯邊,所以引入contract因子contract_factor,通常取值1-2之間。當且僅當節點滿足條件時:(ndegin*ndegout)<(ndegin + ndegout)*contract_factor,才會contract掉這個節點。
3.3.2 乾掉邊(build partial_tree 和 select_highway)
a 對於每個節點,基於給定的neighbour_size,計算其鄰域半徑neighborhood_radius
b 對於每個節點,計算每個節點的最優路徑樹partial_tree
c 對於每個partial_tree,對其每個葉子節點進行邊的回溯,按照既定的規則,選取符合條件的邊為更高層的邊
最後對路網演算法優化的方向做個簡單總結:
a bi-directional
b heuristic (策略:縮減搜尋範圍,dijkstra搜尋空間是近似圓,a*搜尋空間近似橢圓)
c hierarchy(shortcut/contration,策略:縮減搜尋密度,通常搜尋密度為原始路網的近似百分之一,並且能保證結果正確性。典型演算法如:hh、hnr、ch)
d timetable(預儲存和實時取)
並且上面4個優化方向互不衝突,通常可以任何組合同時使用。
參考
1
白話機器學習演算法(一)分層聚類
分層聚類 1 對於若干輸入物件,開始時候每個物件都是一類 2 你可以想象一類就是一塊磁鐵,每次只允許一對磁鐵吸在一起,要求是這對磁鐵的距離所有距離裡最近的,兩個磁鐵就變成一塊大磁鐵,他們歸為一類 然後更新下這個大磁鐵的中心,以便以後算距離 這樣總類數就會減少一類 3 直到聚到某個數目,比如最終我要聚...
五大常用演算法之一 分治演算法
一 基本概念 在電腦科學中,分治法是一種很重要的演算法。字面上的解釋是 分而治之 就是把乙個複雜的問題分成兩個或更多的相同或相似的子問題,再把子問題分成更小的子問題 直到最後子問題可以簡單的直接求解,原問題的解即子問題的解的合併。這個技巧是很多高效演算法的基礎,如排序演算法 快速排序,歸併排序 傅利...
五大常用演算法之一 分治演算法
一 基本概念 在電腦科學中,分治法是一種很重要的演算法。字面上的解釋是 分而治之 就是把乙個複雜的問題分成兩個或更多的相同或相似的子問題,再把子問題分成更小的子問題 直到最後子問題可以簡單的直接求解,原問題的解即子問題的解的合併。這個技巧是很多高效演算法的基礎,如排序演算法 快速排序,歸併排序 傅利...