公交換乘算法



三個表(最簡單化,不考慮模糊查詢,單行線等其他東西):
1,站點表stop(stop_id,stop_name)
2,路線表line(line_id,line_name)
3,路線站點表(點線路關係表)linestops( line_id, stop_id, seq )此處的seq指某站點在某線路中的順序。


現在分析算法:
1,直達線路
首先根據兩個站點名獲取兩個站點各自的id,這裏定義爲id1,id2
然後查詢
select line_id from
(select line_id from linestops where stop_id = id1) A,
(select line_id from linestops where stop_id = id2) B
where A.line_id = B.line_id
即得到可直達的線路列表

2,一次換乘
首先根據兩個站點名獲取兩個站點各自的id,這裏定義爲id1,id2
然後搜尋兩個站點通過直達方式各自能夠到達的站點集合,最後他們的交集就是我們所需要的換乘站點。
select stop_id from
(
select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id1)
)A,
(
select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id1)
)B
where A.stop_id= B.stop_id
得到換乘站(可能有多個或0個)後,剩下的就是顯示能夠到達換乘站的兩邊線路,這通過前面的直達查詢即可。

3,二次換乘
首先根據兩個站點名獲取兩個站點各自的id,這裏定義爲id1,id2
算法的中心思想是:站點1能夠通過直達到達的所有站點集合A,站點2能夠通過直達到達的所有站點集合B,A和B之間有直達的線路。
一步一步來:
站點1能夠通過直達到達的所有站點集合A:
select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id1)
站點2能夠通過直達到達的所有站點集合B:
select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id2)
而直達的查詢是
select line_id from
(select line_id from linestops where stop_id = id1) C,
(select line_id from linestops where stop_id = id2) D
where C.line_id = D.line_id

我們把=id1和=id2換成 in (select ....)A 和 in (select ...)B

這樣最後我們的查詢是
select line_id from
(select distinct line_id from linestops where stop_id in 【A】) C,
(select distinct line_id from linestops where stop_id in 【B】) D
where C.line_id = D.line_id
其中【A】是
(select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id1))
其中【B】是
(select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id2))
這樣子我們找到了作爲中間換乘的線路(可能有多條或者0條),對列舉的的每一條假設命名爲X線,下一步就是找出可以從站點1到達X任意一個站點的直達線路、和可以從站點2到達X任意一個站點的直達線路即可。
那麼與前面的算法相似,我們在站點1所有能夠到達的站點中去尋找和線路X相交的站點,然後再去找這兩個點的線路
select stop_id from
(select distinct stop_id from linestops where line_id in
(select line_id from linestops where stop_id = id1))A,
(select stop_id from linestops where line_id = X ) B
where A.stop_id = B.stop_id
找到站點了,下面就是根據已經解決的直達查詢找線路了。
站點2類似。


以上的算法有一個優點,全部是sql完成搜尋,所以asp代碼只需寥寥幾行循環而已。
但是缺點是:慢,畢竟可能涉及了數百次sql查詢。而且只是用最簡單的sql方法去算出所有可以換乘的方案,不涉及最優/最短的算法。如果是最短路徑,那得用特殊結構和算法。


另外:

根據出行者輸入的起點和終點,確定出行要選擇的起始公交站點A和目的公交站點B。搜索數據庫,查詢站點A和站點B之間是否有相同的車經過,如果有一條或幾條直達線路,通過比較選擇距離最短的公交線路推薦給出行者。如果沒有,則計算站點A和站點B之間有沒有一個公共站點C,從站點C可以換乘到達站點B。這就有兩種情況:(1)如果有,屬於一次換乘。計算站點A和公共站點C之間有沒有相同的公交車經過並存入集合X;同樣,計算站點B和公共站點C之間有沒有相同的公交車經過並存入集合Y。將這兩個集合比較後就可以得到從站點A經過公共站點C到達站點B的公交線路,在這些線路中進行比較,選擇距離最短的推薦給出行者。(2)如果沒有公共站點C,就出現了要換乘兩次的情況。將經過站點A的每條公交線路的所有站點存入集合O;同樣,經過站點B的每條線路的所有站點存入集合P。比較這兩個集合,先乘經過站點A的某一路車到達某一站點D,計算站點D與站點B之間有沒有公共站點E,如果有則站點D、E爲換乘站點。這種方案可能有多種,比較選擇距離最短的推薦給出行者。如果不存在公共站點E,說明經過兩次換乘無法從站點A到達站點B,停止搜索計算。

公交出行最優路線具體算法:

1) 輸入起始站點A和目的站點B;

2) 搜索系統數據庫,經過起始站點A的公交線路存爲X(i)(i=1,2,3…,m,m爲正整數),經過目的站點B的公交線路存爲Y(j)(j=1,2,3,…n,.n爲正整數);

3) 判斷是否有X(i)=Y(j),將滿足條件的存入Z。若Z=1,則該條公交線路X(i)即Y(j)爲從站點A到站點B的直達最優線路,輸出結果並結束運算。Z≥1,計算Z中各條線路的距離,選擇一條距離最短的線路,輸出結果並結束運算;

4) 搜索系統數據庫,公交線路X(i)所包含的站點存爲O(i,u)(u=1,2,3…,g,g爲正整數)公交線路Y(j)所包含的站點存爲P(j,v)(v=1,2,3…,h,h爲正整數);

5) 判斷是否有O(i,u)= P(j,v),將滿足條件的存入W。若W=1,則站點O(i,u)即P(j,v)爲從站點A到站點B的一次換乘站點,公交線路X(i),Y(j)爲換乘一次的最優路線,輸出結果並結束運算。若W≥1,分別計算每條換乘路線的距離,選擇一條距離最短的線路,輸出結果並結束運算;

6) 搜索系統數據庫,經過站點O(i,u)的公交線路存爲R(k)(k=1,2,3…,p,p爲正整數),公交線路R(k)所包含的站點存爲G(k,t)(t=1,2,3…,q,q爲正整數);

7)判斷是否有G(k,t)=P(j,v),將滿足條件的存入S。若S=1,則站點G(k,t)即P(j,v)爲從站點A到站點B的二次換乘站點,公交線路X (i),R(k),Y(j)爲換乘二次的最優路線,輸出結果並結束運算。若S≥1,分別計算每條換乘二次的路線距離,選擇一條距離最短的線路,輸出結果並結束運算;

8) 以上步驟沒有找到合適的公交線路,輸出“沒有找到換乘次數不超過兩次的最優公交線路”,結束運算。


一、公交換乘問題的算法分爲兩個步驟:

1、構造並求解換乘矩陣,獲得公交換乘方案(即從起點到終點最少換乘次數,及換乘站點)。
有三種實現形式:
①、求得所有節點T矩陣,兩個節點直達設爲1,兩個節點不通或需要換乘設爲0;參見《公共交通系統最佳路徑算法》
②求得所有線路的T矩陣,兩條線路相交設爲1,兩個線路不相交設爲0;參見《基於鄰接矩陣的公交換乘算法的研究》(注該算法屬於理想化算法)
③通過上述第2個步驟縮小範圍,然後用第一個步驟求得精確結果

2、根據最少換乘次數,縮小求解範圍,求解起始站點與目標站點間的最短路徑,進而得到最佳路徑。
最短路徑獲得有以下幾種形式:
①、最簡單的實現方法:如果上面1的最少換乘次數、換乘站點都能求解出來,只需要查詢換乘次數最少的情況下,所有可能的路徑中站點數最少的線路即爲所求(前提,假設所有站點之間的距離大致相等);
②、如果上面1只求出來最少換乘次數,這時需要用算法求最短路徑,常用的方法是改進Dijkstra算法,也就是在Diskstra算法中增加了一條判斷最少換乘算法的一項;
③、在遊戲設計程序中,經常要涉及到最短路徑的上述,最常採用的算法是A*算法,參見《遊戲地圖最短路徑搜索設計與實現》和《A算法》
④、K(<=3)條漸次短路徑搜索算法,這種算法國外用的比較多,由於該算法比較麻煩,國內研究不太多,參見《K(≤3)條漸次短路徑搜索算法的研究》、《一種新的Kth最短路徑搜索算法》和《城市軌道交通換乘票務清分模型的研究》(碩士論文)
⑤、螞蟻算法,參見《一種仿Dijkstra的螞蟻算法》
其中,②③④⑤步驟中都需要依靠最少換乘次數來達到降低複雜度的目的。

二、上述算法如能得到很好的實現,需要建立一個好的數據結構

1、數據存儲形式
我曾問過兩個實際搞過這方面的人,一個人採用數組來存儲,另外一個所採用鏈表與數組相結合的方式(即長鏈表採用數組,其它採用鏈表的方式),其實,之所以有上述兩個存儲形式,主要是因爲這兩個人算法中側重面不同,前一個側重實現最少換乘次數,後一個則側重最短路徑的實現。
2、數據結構存儲,可參考《城市公交網絡出行路徑選擇的計算機算法研究》、《基於GIS的標準公交基礎信息系統》《基於GIS的公交乘客出行路徑選擇模型》,考慮到公交換乘,所以通常情況下,把相近的站點(站點名一樣但地理位置不同的、站點名不一樣但地理位置很接近的)作爲公交網絡拓撲結構中一個節點。
3、兩個節點之間弧段權值的選取(計算最短路徑需要):通常情況下,用兩個節點之間的距離代替,但也有人用公交車在這兩個節點之間的速度或行車時間來作爲權值。下圖是瀋陽公交網給出來的環路車參數,根據該參數和兩個站點之間的距離可以求出站點之間的行車時間(正常)。當然因素考慮的越齊全,越人性化,但是程序上就增加了很多難度, 比如:考慮“等車時間、站點距離、線路的熱度(通往商業區)、時間(上班高峯期等)”等因素,這些因素都很難量化,所以,通常情況下,最簡單的方法用距離來作爲兩個節點之間弧段的權值。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章