图论解决复杂路口红绿灯安排,python语言实现
文章目錄
- 問題描述
- 說明性描述
- 操作性描述
- 圖著色問題
- 圖著色算法
- 算法精化和python描述
- 算法細節處理:
- python實現
- 討論
問題描述
說明性描述
說明性描述說明了需要解決的問題是什么,針對什么樣的問題,期望什么樣的解
這是一個5條路的交叉口,其中兩條是單行線。這個圖本身已經是實際問題的抽象,與行駛方向無關的因素如道路方位、寬度、車流量等都已被抽象去除。要求設計紅綠燈,按不同方向行駛的車輛不能相互沖突,依次通過;在此基礎上,要求紅綠燈輪轉次數最少。
現在基本想法是對行駛方向分組:
- 同屬一組的各個方向行駛的車輛,均可以同時行駛,不出現相互交錯的行駛路線
- 所做的分組應該盡可能大
操作性描述
操作性描述說明通過怎樣的操作過程可以得到所要的解
采用圖來進一步抽象問題,其中頂點集VVV中的頂點元素表示所有可能可行方向,不難列出本例一共13個:AB, AC, AD, BA, BC, BD, DA, DB, DC, EA, EB, EC, ED。邊集EEE中的元素表示兩個頂點所代表的可行方向有沖突。
有了沖突圖,尋找安全分組的問題就可以換一種說法:為沖突圖中的頂點確定一種分組,保證屬于同一組的頂點互不鄰接。
要解決的問題進一步抽象為圖數據結構上的頂點分組。
圖著色問題
以非相鄰為條件的最佳頂點分組問題,其實對應于有名的圖最佳著色問題:把頂點看成區域,把相鄰看成兩個頂點有邊界,把不同分組看做給相鄰頂點以不同顏色著色。著名的四色問題表明,對于任一方式分割為區域的平面圖,只需要4種顏色著色,就能保證相鄰區域都具有不同顏色。
但是,從交叉路口構造出的沖突圖可能不是平面圖,因此完全可能需要更多的顏色。
圖著色算法
現有的最佳著色算法基本相當于枚舉所有可能的著色方案,從中選出使用顏色最少的方案。
下面考慮使用貪婪算法,或稱貪心法。其基本思想是根據當時掌握的信息,盡可能地向得到解的方向前進,直到不能繼續再換一個方向。這樣做通常不能得到最優解,但能找到“可接受的”解,即給出一種較好的算法。
算法梗概(偽代碼)如下:
上面算法還有重要的細節要考慮:一種新顏色的著色處理。具體:
- 圖G保存需著色圖中頂點的鄰接信息;
- 集合verts是圖中所有尚未著色的頂點集合;
- 用另一個變量new_group記錄正在構造的用當前新顏色著色的頂點(一個頂點),在上面算法的每次迭代中重新構造,每次重新分組時將這個集合重新設置為空集。
檢查上面的算法,可以看到算法涉及一些集合操作和圖操作。
算法精化和python描述
算法細節處理:
python的集合操作:
10. 判斷集合vs是否空集:not vs
11. 設置一個集合為空:vs = set()
12. 從集合中去掉一個元素:vs.remove(v)
13. 向集合中增加一個元素:vs.add(v)
python的集合數據類型不支持遍歷,需要從當時的集合verts生成一個表,然后對表做遍歷。
算法中需要的圖操作依賴于,如何在python中實現圖數據結構,這里假定兩個與圖有關的操作:
有了以上假設,就可以寫程序:
python實現
def coloring(G): #做圖G的著色color = 0groups = set()verts = vertices(G) #取得G圖的所有頂點,依賴于圖的表示while verts:new_group = set()for v in list(verts):if not_adjacent_with_set(v, newgroup, G):new_group.add(v)verts.remove(v)group.add((color, new_group))color += 1return groups這個python函數能對任何一個圖算出頂點分組。其中欠缺的細節就是圖的表示,以及函數里設計的兩個圖操作
討論
對于給定的交叉路口實例,可行的分組可能不唯一。算法給出的解是確定的,依賴于算法中選擇頂點的具體策略,以及對圖中頂點的遍歷順序,即**list(verts)**給出的頂點序列中的順序。
回顧前面從問題出發做出一個python程序的工作過程:
問題是,這樣的結果滿足原交叉路口實例的需要嗎?
仔細分析,上面算法中采取的定義不統一:
算法給出的結果是各分組互不相交,每個頂點只屬于一個分組;而工作實際是只要求同屬一組的頂點是互不沖突的,即允許頂點屬于不同分組的情況。
需要將之前得到的分組盡可能擴充,加入與已有分組不沖突的方向,如何修改前面算法,使之能給出這樣分組?
總結
以上是生活随笔為你收集整理的图论解决复杂路口红绿灯安排,python语言实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图像滤波器
- 下一篇: 从技术分工的角度来看996.ICU