2019-12-02 校內數模新手賽

調查地鐵站的路徑選擇問題

摘要

對於一二線城市,地鐵已成爲民衆不可或缺的出行方式,爲了減少在上班上學路上消耗的時間,人們也可謂絞盡腦汁。這次,我們要幫助p同學,在他解決地鐵"最佳門"問題時提供耗時最短的路線。

針對問題一,本文把龐大複雜的地鐵網絡化繁爲簡,最終簡化成只有中轉站和起始站互相以線段連接的平面圖,求解此問題等價於找到從起始點出發,經過所有中轉站,再回到出發點的耗時最短的路徑。本文將中轉站與起始站標號,採用 FloydFloyd 算法和蟻羣算法,在計算機上求解此變形後的 TSPTSP 問題。

針對問題二,類似解決問題一的思路,在對地鐵站編號重整後,仍舊套用 FloydFloyd 進行預處理,化爲傳統的 MTSPMTSP 問題。最後採用遺傳算法進行求解得到最佳方案。

針對問題三,根據第二問結果,第三問即簡單的概率模型,由於舅舅與舅媽兩人出現在中轉站的概率相互獨立,只需根據公式求解即可。

關鍵詞:最短路徑 FloydFloyd 算法 蟻羣算法 遺傳算法 旅行商問題(TSPTSP) 多旅行商問題(MTSPMTSP) 期望分析

1.問題的重述

中大南校的p同學想要進行一項非常有趣的研究------在廣州地鐵的各條線路間中轉,如何在上車時選擇合適的"最佳門",使得下車時能儘快搶佔先機,到達應轉線路(例:乘坐8號線地鐵時,若選擇在16號門上車,則在下車時距離進入4號線站臺的電梯最近)。p同學發現,搜索引擎並不能幫他找到地鐵屏蔽門編號和線路切換所在電梯和門的具體相對位置。也就是說,p同學只能進行實地考察。

p同學不考慮從宿舍到達地鐵站的時間,可以選擇從中大站或鷺江站出發,返回時也可以選擇回到中大站或鷺江站。對於 "自己怎麼都不會去"的9,14,21,13號線相關中轉站,p同學表示不感興趣。地鐵APM線與普通線路在地鐵站內的換乘和出站模式接近,p同學認爲不必調查。到達每個中轉站進行調查時,p同學都需要走出地鐵閘門,在站內進行觀察,之後重新進入閘門(見附錄1)。如果兩次路過同一中轉站,那麼第二次可以不下地鐵直接路過。

  1. p同學應如何選擇線路,使得進行該調查的耗時最低。

  2. p同學認爲集中時間調查完所有站點理論上太累。應如何選擇線路,使得分5天進行該調查時耗時最低。

  3. p同學的舅舅與舅媽在廣州地鐵8號線沿線各中轉站上班,若他們每人每天在每個中轉站上班的概率視爲相等,每天上班時間視爲全天,根據你在2.中給出的方案,計算與他們單人相遇總次數、與他們相遇次數和的期望與方差。

2.問題的分析

本題主要探究遍歷地鐵中轉站所用時間多少和相遇次數的問題。問題1、2要求從路線規劃出發,設計出使p同學調查耗時最短的路線,主要用到圖論的知識。問題3則要求根據第二問得出的方案來計算與舅舅舅媽相遇的期望與方差,屬於概率類問題。

2.1對問題1的分析

在處理問題1時,先分析地鐵線路圖,將不需要的線路刪去,然後把某些可以當作一個站的地鐵站合併,之後畫出簡化後的線路圖。分析後可以發現,這個問題可以等價成具有局部重複路徑的旅行商問題(TSPTSP),在4.1.2中我們證明了 FloydFloyd 算法對解決該問題的作用,將其轉化爲了傳統的 TSPTSP 問題,隨後我們利用蟻羣算法解決了這一問題,給出了最佳方案。

2.2對問題2的分析

在處理問題2時,類似對問題1的處理,對線路圖進行簡化。分析後發現該問題可轉化爲具有局部重複路徑的多旅行商問題(MTSPMTSP),在4.1.2中證明了 FloydFloyd 算法對解決該問題的作用,將其轉化爲了傳統的 MTSPMTSP 問題,隨後我們利用遺傳算法解決了這一問題,給出了最佳方案。

2.3對問題3的分析

第三問是一個典型的概率問題,直接根據第二問得到的方案進行解答即可。

3.模型的假設與符號說明

3.1模型的假設

  1. 假設p同學調查地鐵站的整個過程中所有地鐵正常運行。
  2. 假設p同學在所有的中轉站換乘時的等車時間不計。
  3. 假設若p同學在規劃的路徑中將多次經過某一中轉站的話,則其不一定在第一次到達該中轉站時就進行考察。
  4. 假設地鐵從上一個中轉站運行至下一個中轉站的時間爲廣州地鐵官網上提供的時間。
  5. 假設當p同學轉乘地鐵時,舅舅舅媽在同一個中轉站工作,則P同學與他們必定相遇。若經過中轉站不下車換乘或調查,則p同學與舅舅舅媽不能相遇。

3.2符號說明

符號 說明 單位
aia_i 中轉站編號 /
DisDis 總路程/(總時間) /(min)
disi,jdis_{i,j} 中轉站 i,ji,j 間距離(所需時間) /(min)
GG 連通圖 /
viv_i 頂點
DD 路徑 /
ρ\rho 信息素的揮發程度 /
τij(t)\tau_{ij}(t) tt 時刻中轉站 ii 與中轉站 jj 連接路徑上的信息素濃度 /
Δτijk\Delta\tau_{ij}^k kk 只螞蟻在中轉站 ii 與中轉站 jj 連接路徑上釋放的信息素濃度 /
Pi,jk(t)P_{i,j}^k(t) 表示 tt 時刻螞蟻 kk 從中轉站 ii 轉移到中轉站 jj 的概率 /
allowk\text{allow}_k 螞蟻 kk 待訪問中轉站的集合 /
NN 遺傳羣體中的個體總數
fif_i 個體 ii 的適應度 /
PiP_i 個體 ii 被選取的概率 /
QQ 修正模型的常係數 /
pp 舅舅/舅媽在四個中轉站其一上班的概率 /
nin_i 每條線路經過8號線中轉站的次數
E1E_1 單人相遇次數的期望
E2E_2 與他們相遇次數和的期望
D1D_1 單人相遇次數的方差 2次^2
D2D_2 與他們相遇次數和的方差 2次^2

4.模型的建立

4.1問題1的模型建立與求解

4.1.1對地鐵線路圖的簡化

通過查找數據,得到地鐵在不同中轉站之間運行所需時間。由於9,14,21,13號線相關的地鐵中轉站不在調查範圍,我們先刪去相關線路。之後,爲觀察方便,把兩個中轉站之間彎曲的線路變成連接兩個站的線段,得到圖1.1此時要遍歷28個站。

圖1.1

然後,爲了便於計算,我們嘗試再次簡化圖1.1:由於每個中轉站都要調查,滿足儘量減少時間的條件下,經過石壁與廣州南站兩個中轉站的路徑有且只有一條,將兩站合併成一個地鐵站不影響結果。此外,查詢數據知,廣州東站經1號線到體育西站的時間要多於經3號線到達的時間。在任何情況下,都可以選擇3號線。所以,1號線此段線路可以刪去而不影響結果。最終,我們得到的網絡如圖2.2所示。其中,編號1-27表示地鐵站(圖2.1),線段上的數字表示乘坐地鐵經過此路段需要的時間(單位:min)。 (合併後,在石壁停留的調查時間增加至20min,即增加了廣州南站的調查時間和往返時間)
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-YIs8UioF-1575883501493)(002.png)]

圖2.1編號與地鐵站的對應關係

在這裏插入圖片描述

圖2.2

4.1.2模型的建立

  1. 首先明確:在4.1.1的條件下,我們需要求在遍歷編號爲1-27的地鐵站的情況下,從1(或2)出發,回到2(或1)的最短時間。中間可以走"回頭路",因此到達每一個地鐵站的次數可能大於1次。

    爲方便建模,經過每一段路線所經過的時間可以看作相對距離 disdis。考慮一個符合題意的方案中依次途徑的中轉站編號序列爲 a1,a2,,ama_1,a_2,\cdots,a_m,總路程爲 Dis=disa1,a2+disa2,a3++disam1,amDis=dis_{a_1,a_2}+dis_{a_2,a_3}+\cdots+dis_{a_{m-1},a_m}
    目標是求 DisminDis_{min}

    經過分析後可以發現,由於1和2兩點事實上可以合併考慮,該問題本質上就是具有局部重複路徑的旅行商問題(TSPTSP),接下來分成兩部分對該問題進行求解。

  2. 預處理—— FloydFloyd 算法

    FloydFloyd 算法又稱爲插點法,是一種利用動態規劃的思想尋找給定的加權圖中多源點之間最短路徑的算法。在本題中,主要爲了在後續的蟻羣算法求解中能生成具有局部重複路徑的解決方案。爲詳細說明該預處理作用,下給出一個定理及其證明。

    定理:連通圖 GG 中,在允許走重複路徑的前提下,要使 TSPTSP 迴路的長度最短,則旅行商從頂點 v1v_1v2v_2 時,所經過的通路必是 v1v_1v2v_2 間的最短路徑。

    證明:假設頂點 v1v_1v2v_2 間存在多條道路(包括那些經過其他頂點的間接路徑),若旅行商在從 v1v_1v2v_2 時不經過 v1v_1v2v_2 間的最短路徑 DminD_{min},而是經過路徑 DD,顯然,使用 DminD_{min} 代替通路 DD 能夠獲得更優的方案,得到的新的旅行路徑必然就是圖中兩個頂點間最短路徑組成。

    接下來闡述 FloydFloyd 算法的內容。從編號爲 ii 的地鐵站出發,目的地爲編號 jj 的地鐵站時(1ij271\leq i\neq j\leq 27)若選擇直接到達,則距離爲 disi,jdis_{i,j}。考慮除 i,ji,j 之外的站點中轉,若存在站點 kk,使得 ikji\rightarrow k\rightarrow j 的距離 dis=disi,k+disk,j<disi,jdis'=dis_{i,k}+dis_{k,j}<dis_{i,j}

    則把 disdis' 的值賦給 disi,jdis_{i,j}。 繼續在 i,ji,j 以外的其他中轉站尋找這樣的 kk,直到確定 disi,jdis_{i,j} 的最小值。

    重複上述步驟,找到1-27號地鐵站任意兩站點之間的 dismindis_{min}。站點之間的最小相對距離如下表。(第一行和第一列爲中轉站編號)

    站點 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
    1 5 9 22 27 15 21 28 26 31 23 18 25 19 25 29 33 14 6 14 27 26 33 16 22 12 46
    2 5 4 17 22 10 16 23 31 36 28 23 20 14 20 24 28 19 11 17 30 21 28 11 27 17 42
    3 9 4 13 18 6 12 19 28 40 32 24 16 10 16 20 24 23 15 13 26 17 24 7 31 21 38
    4 22 17 13 5 19 25 32 41 53 45 37 29 23 29 33 37 36 28 26 35 26 11 20 44 34 51
    5 27 22 18 5 14 20 27 36 48 42 32 24 18 24 28 32 35 33 31 40 31 16 25 49 39 46
    6 15 10 6 19 14 6 13 22 34 28 18 10 4 10 14 18 21 21 19 32 23 30 13 37 27 32
    7 21 16 12 25 20 6 7 16 28 22 12 4 4 10 14 18 15 23 25 38 29 36 19 32 29 32
    8 28 23 19 32 27 13 7 9 21 23 13 5 11 16 12 18 16 24 32 45 36 43 26 33 30 29
    9 26 31 28 41 36 22 16 9 12 18 8 14 20 25 21 27 12 20 28 41 44 52 34 28 26 20
    10 31 36 40 53 48 34 28 21 12 8 18 26 32 37 33 39 17 25 33 46 49 64 39 18 28 32
    11 23 28 32 45 42 28 22 23 18 8 10 18 26 32 35 40 9 17 25 38 41 56 31 10 20 38
    12 18 23 24 37 32 18 12 13 8 18 10 8 16 22 25 30 4 12 20 33 36 48 26 20 18 28
    13 25 20 16 29 24 10 4 5 14 26 18 8 8 14 17 22 11 19 27 40 33 40 23 28 25 34
    14 19 14 10 23 18 4 4 11 20 32 26 16 8 6 10 14 19 25 23 36 27 34 17 36 31 28
    15 25 20 16 29 24 10 10 16 25 37 32 22 14 6 4 10 25 31 29 42 33 40 23 42 37 22
    16 29 24 20 33 28 14 14 12 21 33 35 25 17 10 4 6 28 35 33 46 37 44 27 45 41 18
    17 33 28 24 37 32 18 18 18 27 39 40 30 22 14 10 6 33 39 37 50 41 48 31 50 45 24
    18 14 19 23 36 35 21 15 16 12 17 9 4 11 19 25 28 33 8 16 29 32 47 22 19 14 32
    19 6 11 15 28 33 21 23 24 20 25 17 12 19 25 31 35 39 8 8 21 24 39 14 16 6 40
    20 14 17 13 26 31 19 25 32 28 33 25 20 27 23 29 33 37 16 8 13 16 31 6 21 11 48
    21 27 30 26 35 40 32 38 45 41 46 38 33 40 36 42 46 50 29 21 13 9 24 19 34 24 61
    22 26 21 17 26 31 23 29 36 44 49 41 36 33 27 33 37 41 32 24 16 9 15 10 37 27 55
    23 33 28 24 11 16 30 36 43 52 64 56 48 40 34 40 44 48 47 39 31 24 15 25 52 42 62
    24 16 11 7 20 25 13 19 26 34 39 31 26 23 17 23 27 31 22 14 6 19 10 25 27 17 45
    25 22 27 31 44 49 37 32 33 28 18 10 20 28 36 42 45 50 19 16 21 34 37 52 27 10 48
    26 12 17 21 34 39 27 29 30 26 28 20 18 25 31 37 41 45 14 6 11 24 27 42 17 10 46
    27 46 42 38 51 46 32 32 29 20 32 38 28 34 28 22 18 24 32 40 48 61 55 62 45 48 46
    表3.1站點之間的最小相對距離
  3. 正式求解——蟻羣算法

    ① 蟻羣算法介紹:
    螞蟻在尋找食物源時,會在其經過的路徑上釋放一種信息素,並能夠感知其他螞蟻釋放的信息素。信息素的濃度大小表徵路徑的遠近,信息素濃度越高,表示對應的路徑距離越短。

    通常,螞蟻會以較大的概率優先選擇信息素濃度較高的路徑,並釋放一定量的信息素,以增強該條路徑上的信息素濃度,這樣會形成一個正反饋。最終,螞蟻能夠找到一條最佳路徑,即最短距離。

    同時,路徑上的信息素濃度會隨着時間的推進而逐漸衰減。

    ② 蟻羣算法解決 TSPTSP 問題基本原理:

    不失一般性,設整個螞蟻羣體中螞蟻的數量爲 mm,中轉站的數量爲 nn,中轉站 ii 與中轉站 jj 之間的距離爲 disi,j(i,j=1,2,,n)dis_{i,j}(i,j=1,2,\cdots,n)tt 時刻中轉站 ii 與中轉站 jj 連接路徑上的信息素濃度爲 τij(t)\tau_{i j}(t)。初始時刻,各個中轉站間連接路徑上的信息素濃度相同,不妨設爲 τi,j(0)=τ0\tau_{i,j}(0)=\tau_0

    螞蟻 k(k=1,2,,m)k(k=1,2,\cdots,m) 根據各個中轉站間連接路徑上的信息素濃度決定其下一個訪問中轉站,設 Pi,jk(t)P_{i,j}^k(t) 表示 tt 時刻螞蟻 kk 從中轉站 ii 轉移到中轉站 jj 的概率,其計算公式爲
    Pijk={[τij(t)]α[ηij(t)]βs allow k[τis(t)]α[ηis(t)]β,s allow k0,s allow k P_{i j}^{k}=\left\{\begin{array}{ll}{\frac{\left[\tau_{i j}(t)\right]^{\alpha} \cdot\left[\eta_{i j}(t)\right]^{\beta}}{\sum_{s \in \text { allow }_{k}}\left[\tau_{i s}(t)\right]^{\alpha} \cdot\left[\eta_{i s}(t)\right]^{\beta}},} & {s \in \text { allow }_{k}} \\ {0,} & {s \notin \text { allow }_{k}}\end{array}\right.
    其中,ηij(t)\eta_{i j}(t) 爲啓發函數,ηij(t)=1di,j\eta_{i j}(t)=\frac{1}{d_{i,j}},表示螞蟻從中轉站 ii 轉移到中轉站 jj 的期望程度;allowk(k=1,2,,m)\text{allow}_k(k=1,2,\cdots,m) 爲螞蟻 kk 待訪問中轉站的集合,開始時,allowk\text{allow}_k 中有 (n1)(n-1) 個元素,即包括了除了螞蟻 kk 出發站點的其他所有站點,隨着時間的推進,allowk\text{allow}_k 中的元素不斷減少,直至爲空,即表示所有的中轉站均訪問完畢;α\alpha 爲信息素重要程度因子,其值越大,表示信息素的濃度在轉移中起的作用越大;β\beta 爲啓發函數重要程度因子,其值越大,表示啓發函數在轉移中的作用越大,即螞蟻會以較大的概率轉移到距離短的中轉站。

    如前文所述,在螞蟻釋放信息素的同時,各個中轉站間連接路徑上的信息素逐漸消失,設參數 ρ(0<ρ<1)\rho(0<\rho<1) 表示信息素的揮發程度。因此,當所有螞蟻完成一次循環後,各個城市間連接路徑上的信息素濃度需進行實時更新,即
    {τij(t+1)=(1ρ)τij(t)+ΔτijΔτij=k=1nΔτijk,0<ρ<1 \left\{\begin{array}{l}{\tau_{ij}(t+1)=(1-\rho) \tau_{i j}(t)+\Delta \tau_{i j}} \\ {\Delta \tau_{i j}=\sum_{k=1}^{n} \Delta \tau_{i j}^{k}}\end{array}, \quad 0<\rho<1\right.
    其中,Δτijk\Delta\tau_{ij}^k 表示第 kk 只螞蟻在中轉站 ii 與中轉站 jj 連接路徑上釋放的信息素濃度;Δτij\Delta\tau_{ij} 表示所有螞蟻在中轉站 ii 與中轉站 jj 連接路徑上釋放的信息素濃度之和。

    針對螞蟻釋放信息素問題,本題中我們採用了 ant cycle systemant\ cycle\ system 模型,在該模型中,Δτijk\Delta\tau_{ij}^k 的計算公式爲
    Δτijk={Q/Lk,k i  j 0, \Delta \tau_{i j}^{k}=\left\{\begin{array}{l}{Q / L_{k}},&第k只螞蟻從中轉站\ i\ 訪問中轉站\ j\ \\ {0},&其他\end{array}\right.
    ③ 蟻羣算法解決 TSPTSP 問題基本步驟

    基於上述原理,將蟻羣算法應用於解決 TSPTSP 問題一般需要以下幾個步驟,如圖3.2所示。
    在這裏插入圖片描述

    圖3.2蟻羣算法解決 TSP 問題基本步驟

4.1.3模型的結果

在本題中,由於可以重複經過路徑,所以先用 FloydFloyd 算法進行預處理,進而轉化成了一般性的 TSPTSP 問題。並且,由於在本問題中,每個地鐵中轉站只考察一次,因此在處理該問題時可以先不考慮考察時間,最後再加入答案中。將處理後的數據(表3.1)導入 MATLAB 中,應用蟻羣算法。即可解得最優方案如下:
在這裏插入圖片描述
在這裏插入圖片描述

直觀路線圖如下圖3.3:
在這裏插入圖片描述

圖3.3模型結果

4.2問題2的模型建立與求解

4.2.1對地鐵線路圖的簡化

類似4.1.1,在處理第二問的過程中,我們依舊是將每個中轉站抽象成一個點。主要的改變是,在第二問中將1和2兩個點進行合併。給各個地鐵中轉站的編號如下圖4.1。另外,修改後得地鐵中轉站網絡圖如下圖4.2,線段上的數字表示乘坐地鐵經過此路段需要的時間(單位:min)。
在這裏插入圖片描述

圖4.1編號與地鐵站的對應關係

在這裏插入圖片描述

圖4.2

4.2.2模型的建立

  1. 首先明確:在4.2.1的條件下,我們需要求在遍歷編號爲1-26的地鐵站的情況下,從1出發,回到1的最短時間。中間可以走“回頭路”因此到達每一個地鐵站的次數可能大於1次。

    爲方便建模,經過每一段路線所經過的時間可以看作相對距離 disdis。考慮一個符合題意的方案中,第 ii 天的出行中,依次途徑的中轉站編號序列爲 ai,1,ai,2,,ai,ma_{i,1},a_{i,2},\cdots,a_{i,m},則五天出行的總路程爲
    Dis=n=15(disai,1,ai,2+disai,2,ai,3++disai,m1,ai,m) Dis= \sum_{n=1}^5(dis_{a_{i,1},a_{i,2}}+dis_{a_{i,2},a_{i,3}}+\cdots+dis_{a_{i,m-1},a_{i,m}})
    目標是求 DisminDis_{min}

    經過分析後可以發現,與第一問類似,該問題本質上就是具有局部重複路徑的多旅行商問題(MTSPMTSP),接下來分成兩部分對該問題進行求解。

  2. 預處理——FloydFloyd 算法

    4.1.2中已經說明了該算法在生成具有局部重複路徑的解決方案的過程中的作用,並且給出了對應的定理和證明,同時也已闡明瞭 FloydFloyd 算法的內容及應用,此處不再贅述。

    預處理後得到1-26號地鐵站任意兩站點之間的 dismindis_{min}。站點之間的最小相對距離如下表。(第一行和第一列爲中轉站編號)

    站點 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
    1 4 17 22 10 16 23 26 31 23 18 20 14 20 24 28 14 6 14 27 21 28 11 22 12 42
    2 4 13 18 6 12 19 28 35 27 22 16 10 16 20 24 18 10 13 26 17 24 7 26 16 38
    3 17 13 5 19 25 32 41 48 40 35 29 23 29 33 37 31 23 26 35 26 11 20 39 29 51
    4 22 18 5 14 20 27 36 48 42 32 24 18 24 28 32 35 28 31 40 31 16 25 44 34 46
    5 10 6 19 14 6 13 22 34 28 18 10 4 10 14 18 21 16 19 32 23 30 13 32 22 32
    6 16 12 25 20 6 7 16 28 22 12 4 4 10 14 18 15 22 25 38 29 36 19 32 28 32
    7 23 19 32 27 13 7 9 21 23 13 5 11 16 12 18 16 24 32 45 36 43 26 33 30 29
    8 26 28 41 36 22 16 9 12 18 8 14 20 25 21 27 12 20 28 41 44 52 34 28 26 20
    9 31 35 48 48 34 28 21 12 8 18 26 32 37 33 39 17 25 33 46 49 59 39 18 28 32
    10 23 27 40 42 28 22 23 18 8 10 18 26 32 35 40 9 17 25 38 41 51 31 10 20 38
    11 18 22 35 32 18 12 13 8 18 10 8 16 22 25 30 4 12 20 33 36 46 26 20 18 28
    12 20 16 29 24 10 4 5 14 26 18 8 8 14 17 22 11 19 27 40 33 40 23 28 25 34
    13 14 10 23 18 4 4 11 20 32 26 16 8 6 10 14 19 20 23 36 27 34 17 36 26 28
    14 20 16 29 24 10 10 16 25 37 32 22 14 6 4 10 25 26 29 42 33 40 23 42 32 22
    15 24 20 33 28 14 14 12 21 33 35 25 17 10 4 6 28 30 33 46 37 44 27 45 36 18
    16 28 24 37 32 18 18 18 27 39 40 30 22 14 10 6 33 34 37 50 41 48 31 50 40 24
    17 14 18 31 35 21 15 16 12 17 9 4 11 19 25 28 33 8 16 29 32 42 22 19 14 32
    18 6 10 23 28 16 22 24 20 25 17 12 19 20 26 30 34 8 8 21 24 34 14 16 6 40
    19 14 13 26 31 19 25 32 28 33 25 20 27 23 29 33 37 16 8 13 16 31 6 21 11 48
    20 27 26 35 40 32 38 45 41 46 38 33 40 36 42 46 50 29 21 13 9 24 19 34 24 61
    21 21 17 26 31 23 29 36 44 49 41 36 33 27 33 37 41 32 24 16 9 15 10 37 27 55
    22 28 24 11 16 30 36 43 52 59 51 46 40 34 40 44 48 42 34 31 24 15 25 50 40 62
    23 11 7 20 25 13 19 26 34 39 31 26 23 17 23 27 31 22 14 6 19 10 25 27 17 45
    24 22 26 39 44 32 32 33 28 18 11 20 28 36 42 45 50 19 16 21 34 37 50 27 10 48
    25 12 16 29 34 22 28 30 26 28 20 18 25 26 32 36 40 14 6 11 24 27 40 17 10 46
    26 42 38 51 46 32 32 29 20 32 38 28 34 28 22 18 24 32 40 48 61 55 62 45 48 46
    表4.3站點之間的最小相對距離
  3. 正式求解——遺傳算法

    ① 遺傳算法介紹:

    遺傳算法是計算數學中用於解決最優化的搜索算法,是進化算法的一種。進化算法最初是借鑑了進化生物學中的一些現象而發展起來的,這些現象包括遺傳、突變、自然選擇以及雜交等。

    遺傳算法通常實現方式爲一種計算機模擬。對於一個最優化問題,一定數量的候選解(稱爲個體)可抽象表示爲染色體,使種羣向更好的解進化。傳統上,解用二進制表示(即0和1的串),但也可以用其他表示方法。進化從完全隨機個體的種羣開始,之後一代一代發生。在每一代中評價整個種羣的適應度,從當前種羣中隨機地選擇多個個體(基於它們的適應度),通過自然選擇和突變產生新的生命種羣,該種羣在算法的下一次迭代中成爲當前種羣。

    ② 遺傳算法解決 MTSPMTSP 問題基本步驟:

    首先進行二進制編碼,即每個個體的基因型都是一個二進制編碼符號串。接下來是進行交配,“交配運算”是使用單點或者多點進行交叉的算子。首先用隨機數產生一個或者多個交配點位置,然後兩個個體在交配點位置互換部分基因碼,形成兩個子個體。

    例如,兩條染色體 S1=01001011,S2=10010101S_1=01001011,S_2=10010101。交換其後4位基因,得S1=01000101,S2=10001011S_1'=01000101,S_2'=10001011 可以被看做原染色體 S1S_1S2S_2 的子代染色體。

    另外,這過程中還存在着變異現象,主要包括突變和倒位。對於突變,舉個例子,對於 S1=010110011S_1=010110011,第三位0突變成1,那麼我們得到 S1=011110011S_1'=011110011。倒位是指一個染色體某區段正常排列順序發生 180180^{\circ} 的顛倒,造成染色體內的 DNADNA 序列重新排列。例如對於 $S_1=$010100010110110101進行倒位時得到 $S_1’=$010101101000110101。

    然後還要進行適應度評估。遺傳算法依照與個體適應度成正比的機率決定當前種羣中各個個體遺傳到下一代羣體的機會。個體適應度大的個體更容易被遺傳到下一代。在本題中,利用該個體得到的五天路徑總長度作爲評估個體適應度大小的函數,長度越小適應度越高,長度越大適應度越低。

    最後還有選擇的步驟,選擇運算時根據個體適應度大小決定其下代遺傳的可能性。設種羣中個體總數爲 NN,個體 ii 的適應度爲 fif_i,則個體 ii 被選取的概率爲 Pi=fii=1NP_i=\frac{f_i}{\sum_{i=1}^N}

    遺傳算法的整個過程如下圖4.4:
    在這裏插入圖片描述

    圖4.4遺傳算法過程

4.2.3模型的結果

在本題中,由於可以重複經過路徑,所以先用 FloydFloyd 算法進行預處理。同時,結合實際生活經驗,爲了能夠不讓p同學太累,合理規劃出行調研路徑,我們假設p同學不一定第一次經過某中轉站就進行考察。於是,類似第一問,我們同樣先將考察時間分離出來,剩下的問題就是一個典型的 MTSPMTSP 問題。將處理後的數據(表4.3)導入 MATLAB 中,應用遺傳算法。

其中不斷修改參數min-tour(每天最少考察中轉站數),得到了下列圖4.5:
在這裏插入圖片描述

圖4.5修改參數得到的結果
由圖4.5可以看出,單次調查中轉站數量越少,總時間就越少。但是這樣會出現一次調查耗時巨大的情況。

由於題目中認爲“集中所有時間調查站點太累”,那麼我們給出一個單次調查時間上限180min,在滿足該條件並儘量使每天調查時間均勻的情況下,篩選出一個最優方案。即可解得最優方案如下(編號對應的地鐵站可參照圖4.1):
在這裏插入圖片描述
在這裏插入圖片描述

圖4.6模型的結果
最後基於這種方案得到最短總時間爲544。

4.3問題3的模型建立與求解

首先由如下假設:當p同學轉乘地鐵時,舅舅舅媽在同一個中轉站工作,則P同學與他們必定相遇。若經過中轉站不下車換乘或調查,則p同學與舅舅舅媽不能相遇。

8號線只有四個中轉站:25號沙園、18號昌崗、2號客村、3號萬勝圍。由於每天上班地點隨機,在這四個站中,與舅舅或者舅媽中一個人相遇概率爲 p=0.25p=0.25

方案中第一天——第五天的路線爲上圖4.6,設 ni(i=1,2,3,4,5)n_i(i=1,2,3,4,5) 爲經過中轉站次數(下列編號的地鐵站可參考圖4.1)
在這裏插入圖片描述
單人相遇次數(5天總共) E1=p×(n1+n2+n3+n4+n5)=2.75E_1=p\times(n_1+n_2+n_3+n_4+n_5)=2.75
單人相遇方差D1=15i=15(pniE15)=0.01D_1=\frac{1}{5}\sum_{i=1}^5(p\cdot n_i-\frac{E_1}{5})=0.01
與兩人相遇總次數 E2=2.75×2=5.5E_2=2.75\times 2=5.5
與兩人相遇方差 D2=4×0.01=0.04D_2=4\times 0.01=0.04

5.模型的推廣與評價

本文爲解決地鐵站問題採用的算法可以應用在其他尋求最短路徑以及類似的現實生活中的 TSPTSPMTSPMTSP 問題中。爲了使既定條件下計算機能夠求解該模型,對模型的優化方法在解決其他問題時也可以借鑑。

當然,模型也有一些缺點。如在等車時間的設置上,各個中轉站的等車時間與線路地鐵班數、線路人流量都相關,模型中全部取了一固定值。第二次經過中轉站時下車換乘的時間在構建模型時也予以忽略,只是在計算出最終路徑以後加到總時間上。

附錄

FloydFloyd 預處理代碼:

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<string>
using namespace std;

const int maxn=110;
const int waitTime=0;
const int INF=1000010;

int distances[maxn][maxn],n,times[maxn];
string paths[maxn][maxn];
string vertex[maxn]={"0","1","2","3","4","5","6","7","8","9","10","11","12",
"13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28"};

int main()
{
    freopen("in.txt","r",stdin);
    freopen("input.txt","w",stdout);

    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&times[i]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            scanf("%d",&distances[i][j]);
            
            if(distances[i][j]>0)
            	distances[i][j]=distances[i][j]+waitTime;
            else distances[i][j]=INF;
            paths[i][j]=vertex[i]+" --> "+vertex[j];
        }
    
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(distances[i][k]<INF&&distances[k][j]<INF&&i!=j)
                    if(distances[i][k]+distances[k][j]<distances[i][j]){
                        distances[i][j]=distances[j][i]=distances[i][k]+distances[k][j];
                        paths[i][j]=paths[i][k]+" --> "+vertex[j];
                    }
    
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)
        printf("%d ",distances[i][j]);

        printf("\n");
    }
    
    printf("\n");

    for(int i=1;i<=n;i++){
        cout<<"頂點"<<vertex[i]<<":"<<endl;

        for(int j=1;j<=n;j++)
        cout<<paths[i][j]<<"	"<<distances[i][j]<<endl;

        printf("\n");
    }

    return 0;
}

預處理後得到的第一問的 data.txtdata.txt

1000010 5 9 22 27 15 21 28 26 31 23 18 25 19 25 29 33 14 6 14 27 26 33 16 22 12 46 
5 1000010 4 17 22 10 16 23 31 36 28 23 20 14 20 24 28 19 11 17 30 21 28 11 27 17 42 
9 4 1000010 13 18 6 12 19 28 40 32 24 16 10 16 20 24 23 15 13 26 17 24 7 31 21 38 
22 17 13 1000010 5 19 25 32 41 53 45 37 29 23 29 33 37 36 28 26 35 26 11 20 44 34 51 
27 22 18 5 1000010 14 20 27 36 48 42 32 24 18 24 28 32 35 33 31 40 31 16 25 49 39 46 
15 10 6 19 14 1000010 6 13 22 34 28 18 10 4 10 14 18 21 21 19 32 23 30 13 37 27 32 
21 16 12 25 20 6 1000010 7 16 28 22 12 4 4 10 14 18 15 23 25 38 29 36 19 32 29 32 
28 23 19 32 27 13 7 1000010 9 21 23 13 5 11 16 12 18 16 24 32 45 36 43 26 33 30 29 
26 31 28 41 36 22 16 9 1000010 12 18 8 14 20 25 21 27 12 20 28 41 44 52 34 28 26 20 
31 36 40 53 48 34 28 21 12 1000010 8 18 26 32 37 33 39 17 25 33 46 49 64 39 18 28 32 
23 28 32 45 42 28 22 23 18 8 1000010 10 18 26 32 35 40 9 17 25 38 41 56 31 10 20 38 
18 23 24 37 32 18 12 13 8 18 10 1000010 8 16 22 25 30 4 12 20 33 36 48 26 20 18 28 
25 20 16 29 24 10 4 5 14 26 18 8 1000010 8 14 17 22 11 19 27 40 33 40 23 28 25 34 
19 14 10 23 18 4 4 11 20 32 26 16 8 1000010 6 10 14 19 25 23 36 27 34 17 36 31 28 
25 20 16 29 24 10 10 16 25 37 32 22 14 6 1000010 4 10 25 31 29 42 33 40 23 42 37 22 
29 24 20 33 28 14 14 12 21 33 35 25 17 10 4 1000010 6 28 35 33 46 37 44 27 45 41 18 
33 28 24 37 32 18 18 18 27 39 40 30 22 14 10 6 1000010 33 39 37 50 41 48 31 50 45 24 
14 19 23 36 35 21 15 16 12 17 9 4 11 19 25 28 33 1000010 8 16 29 32 47 22 19 14 32 
6 11 15 28 33 21 23 24 20 25 17 12 19 25 31 35 39 8 1000010 8 21 24 39 14 16 6 40 
14 17 13 26 31 19 25 32 28 33 25 20 27 23 29 33 37 16 8 1000010 13 16 31 6 21 11 48 
27 30 26 35 40 32 38 45 41 46 38 33 40 36 42 46 50 29 21 13 1000010 9 24 19 34 24 61 
26 21 17 26 31 23 29 36 44 49 41 36 33 27 33 37 41 32 24 16 9 1000010 15 10 37 27 55 
33 28 24 11 16 30 36 43 52 64 56 48 40 34 40 44 48 47 39 31 24 15 1000010 25 52 42 62 
16 11 7 20 25 13 19 26 34 39 31 26 23 17 23 27 31 22 14 6 19 10 25 1000010 27 17 45 
22 27 31 44 49 37 32 33 28 18 10 20 28 36 42 45 50 19 16 21 34 37 52 27 1000010 10 48 
12 17 21 34 39 27 29 30 26 28 20 18 25 31 37 41 45 14 6 11 24 27 42 17 10 1000010 46 
46 42 38 51 46 32 32 29 20 32 38 28 34 28 22 18 24 32 40 48 61 55 62 45 48 46 1000010 

預處理後得到的第二問的 input.txtinput.txt

1000010 4 17 22 10 16 23 26 31 23 18 20 14 20 24 28 14 6 14 27 21 28 11 22 12 42 
4 1000010 13 18 6 12 19 28 35 27 22 16 10 16 20 24 18 10 13 26 17 24 7 26 16 38 
17 13 1000010 5 19 25 32 41 48 40 35 29 23 29 33 37 31 23 26 35 26 11 20 39 29 51 
22 18 5 1000010 14 20 27 36 48 42 32 24 18 24 28 32 35 28 31 40 31 16 25 44 34 46 
10 6 19 14 1000010 6 13 22 34 28 18 10 4 10 14 18 21 16 19 32 23 30 13 32 22 32 
16 12 25 20 6 1000010 7 16 28 22 12 4 4 10 14 18 15 22 25 38 29 36 19 32 28 32 
23 19 32 27 13 7 1000010 9 21 23 13 5 11 16 12 18 16 24 32 45 36 43 26 33 30 29 
26 28 41 36 22 16 9 1000010 12 18 8 14 20 25 21 27 12 20 28 41 44 52 34 28 26 20 
31 35 48 48 34 28 21 12 1000010 8 18 26 32 37 33 39 17 25 33 46 49 59 39 18 28 32 
23 27 40 42 28 22 23 18 8 1000010 10 18 26 32 35 40 9 17 25 38 41 51 31 10 20 38 
18 22 35 32 18 12 13 8 18 10 1000010 8 16 22 25 30 4 12 20 33 36 46 26 20 18 28 
20 16 29 24 10 4 5 14 26 18 8 1000010 8 14 17 22 11 19 27 40 33 40 23 28 25 34 
14 10 23 18 4 4 11 20 32 26 16 8 1000010 6 10 14 19 20 23 36 27 34 17 36 26 28 
20 16 29 24 10 10 16 25 37 32 22 14 6 1000010 4 10 25 26 29 42 33 40 23 42 32 22 
24 20 33 28 14 14 12 21 33 35 25 17 10 4 1000010 6 28 30 33 46 37 44 27 45 36 18 
28 24 37 32 18 18 18 27 39 40 30 22 14 10 6 1000010 33 34 37 50 41 48 31 50 40 24 
14 18 31 35 21 15 16 12 17 9 4 11 19 25 28 33 1000010 8 16 29 32 42 22 19 14 32 
6 10 23 28 16 22 24 20 25 17 12 19 20 26 30 34 8 1000010 8 21 24 34 14 16 6 40 
14 13 26 31 19 25 32 28 33 25 20 27 23 29 33 37 16 8 1000010 13 16 31 6 21 11 48 
27 26 35 40 32 38 45 41 46 38 33 40 36 42 46 50 29 21 13 1000010 9 24 19 34 24 61 
21 17 26 31 23 29 36 44 49 41 36 33 27 33 37 41 32 24 16 9 1000010 15 10 37 27 55 
28 24 11 16 30 36 43 52 59 51 46 40 34 40 44 48 42 34 31 24 15 1000010 25 50 40 62 
11 7 20 25 13 19 26 34 39 31 26 23 17 23 27 31 22 14 6 19 10 25 1000010 27 17 45 
22 26 39 44 32 32 33 28 18 11 20 28 36 42 45 50 19 16 21 34 37 50 27 1000010 10 48 
12 16 29 34 22 28 30 26 28 20 18 25 26 32 36 40 14 6 11 24 27 40 17 10 1000010 46 
42 38 51 46 32 32 29 20 32 38 28 34 28 22 18 24 32 40 48 61 55 62 45 48 46 1000010 

MATLABMATLAB 蟻羣算法代碼:

%% 清空環境變量
clear all
clc

%% 導入數據
load data.txt

%% 計算城市間相互距離
n = size(data,1);
D = data;

%% 初始化參數
m = 35;                              % 螞蟻數量
alpha = 3;                           % 信息素重要程度因子
beta = 4;                            % 啓發函數重要程度因子
rho = 0.2;                           % 信息素揮發因子
Q = 0.8;                               % 常係數
Eta = 1./D;                          % 啓發函數
Tau = ones(n,n);                     % 信息素矩陣
Table = zeros(m,n);                  % 路徑記錄表
iter = 1;                            % 迭代次數初值
iter_max = 3500;                      % 最大迭代次數 
Route_best = zeros(iter_max,n);      % 各代最佳路徑       
Length_best = zeros(iter_max,1);     % 各代最佳路徑的長度  
Length_ave = zeros(iter_max,1);      % 各代路徑的平均長度  

%% 迭代尋找最佳路徑
while iter <= iter_max
    % 隨機產生各個螞蟻的起點城市
      start = zeros(m,1);
      for i = 1:m
          % temp = 1;
          start(i) = 1;
      end
      Table(:,1) = start; 
      % 構建解空間
      citys_index = 1:n;
      % 逐個螞蟻路徑選擇
      for i = 1:m
          % 逐個城市路徑選擇
         for j = 2:n
             tabu = Table(i,1:(j - 1));           % 已訪問的城市集合(禁忌表)
             allow_index = ~ismember(citys_index,tabu);
             allow = citys_index(allow_index);  % 待訪問的城市集合
             P = allow;
             % 計算城市間轉移概率
             for k = 1:length(allow)
                 P(k) = Tau(tabu(end),allow(k))^alpha * Eta(tabu(end),allow(k))^beta;
             end
             P = P/sum(P);
             % 輪盤賭法選擇下一個訪問城市
             Pc = cumsum(P);     
            target_index = find(Pc >= rand); 
            target = allow(target_index(1));
            Table(i,j) = target;
         end
      end
      % 計算各個螞蟻的路徑距離
      Length = zeros(m,1);
      for i = 1:m
          Route = Table(i,:);
          for j = 1:(n - 1)
              Length(i) = Length(i) + D(Route(j),Route(j + 1));
          end
          Length(i) = Length(i) + D(Route(n),Route(1));
      end
      % 計算最短路徑距離及平均距離
      if iter == 1
          [min_Length,min_index] = min(Length);
          Length_best(iter) = min_Length;  
          Length_ave(iter) = mean(Length);
          Route_best(iter,:) = Table(min_index,:);
      else
          [min_Length,min_index] = min(Length);
          Length_best(iter) = min(Length_best(iter - 1),min_Length);
          Length_ave(iter) = mean(Length);
          if Length_best(iter) == min_Length
              Route_best(iter,:) = Table(min_index,:);
          else
              Route_best(iter,:) = Route_best((iter-1),:);
          end
      end
      % 更新信息素
      Delta_Tau = zeros(n,n);
      % 逐個螞蟻計算
      for i = 1:m
          % 逐個城市計算
          for j = 1:(n - 1)
              Delta_Tau(Table(i,j),Table(i,j+1)) = Delta_Tau(Table(i,j),Table(i,j+1)) + Q/Length(i);
          end
          Delta_Tau(Table(i,n),Table(i,1)) = Delta_Tau(Table(i,n),Table(i,1)) + Q/Length(i);
      end
      Tau = (1-rho) * Tau + Delta_Tau;
    % 迭代次數加1,清空路徑記錄表
    iter = iter + 1;
    Table = zeros(m,n);
end

%% 結果顯示
[Shortest_Length,index] = min(Length_best);
Shortest_Route = Route_best(index,:);
disp(['最短距離:' num2str(Shortest_Length)]);
disp(['最短路徑:' num2str([Shortest_Route Shortest_Route(1)])]);

MATLABMATLAB 遺傳算法代碼:

%% 
load input.txt

n = 26;
xy = 10*rand(n,2);
salesmen = 5;
min_tour = 4;
pop_size = 160;
num_iter = 5e3;
a = meshgrid(1:n);
dmat = input;
[opt_rte,opt_brk,min_dist] = mtspf_ga(xy,dmat,salesmen,min_tour, ...
pop_size,num_iter,1,1);

%% 
function varargout = mtspf_ga(xy,dmat,salesmen,min_tour,pop_size,num_iter,show_prog,show_res)

% Process Inputs and Initialize Defaults
% Verify Inputs
[N,dims] = size(xy);
[nr,nc] = size(dmat);
if N ~= nr || N ~= nc
    error('Invalid XY or DMAT inputs!')
end
n = N - 1; % Separate Start/End City
 
% Sanity Checks
salesmen = max(1,min(n,round(real(salesmen(1)))));
min_tour = max(1,min(floor(n/salesmen),round(real(min_tour(1)))));
pop_size = max(8,8*ceil(pop_size(1)/8));
num_iter = max(1,round(real(num_iter(1))));
show_prog = logical(show_prog(1));
show_res = logical(show_res(1));
 
% Initializations for Route Break Point Selection
num_brks = salesmen-1;
dof = n - min_tour*salesmen;          % degrees of freedom
addto = ones(1,dof+1);
for k = 2:num_brks
    addto = cumsum(addto);
end
cum_prob = cumsum(addto)/sum(addto);
 
% Initialize the Populations
pop_rte = zeros(pop_size,n);          % population of routes
pop_brk = zeros(pop_size,num_brks);   % population of breaks
for k = 1:pop_size
    pop_rte(k,:) = randperm(n)+1;
    pop_brk(k,:) = randbreaks();
end
 
% Select the Colors for the Plotted Routes
clr = [1 0 0; 0 0 1; 0.67 0 1; 0 1 0; 1 0.5 0];
if salesmen > 5
    clr = hsv(salesmen);
end
 
% Run the GA
global_min = Inf;
total_dist = zeros(1,pop_size);
dist_history = zeros(1,num_iter);
tmp_pop_rte = zeros(8,n);
tmp_pop_brk = zeros(8,num_brks);
new_pop_rte = zeros(pop_size,n);
new_pop_brk = zeros(pop_size,num_brks);
if show_prog
    pfig = figure('Name','MTSPF_GA | Current Best Solution','Numbertitle','off');
end
for iter = 1:num_iter
    % Evaluate Members of the Population
    for p = 1:pop_size
        d = 0;
        p_rte = pop_rte(p,:);
        p_brk = pop_brk(p,:);
        rng = [[1 p_brk+1];[p_brk n]]';
        for s = 1:salesmen
            d = d + dmat(1,p_rte(rng(s,1))); % Add Start Distance
            for k = rng(s,1):rng(s,2)-1
                d = d + dmat(p_rte(k),p_rte(k+1));
            end
            d = d + dmat(p_rte(rng(s,2)),1); % Add End Distance
        end
        total_dist(p) = d;
    end
 
    % Find the Best Route in the Population
    [min_dist,index] = min(total_dist);
    dist_history(iter) = min_dist;
    if min_dist < global_min
        global_min = min_dist;
        opt_rte = pop_rte(index,:);
        opt_brk = pop_brk(index,:);
        rng = [[1 opt_brk+1];[opt_brk n]]';
        if show_prog
            % Plot the Best Route
            figure(pfig);
            for s = 1:salesmen
                rte = [1 opt_rte(rng(s,1):rng(s,2)) 1];
                if dims == 3, plot3(xy(rte,1),xy(rte,2),xy(rte,3),'.-','Color',clr(s,:));
                else plot(xy(rte,1),xy(rte,2),'.-','Color',clr(s,:)); end
                title(sprintf('Total Distance = %1.4f, Iteration = %d',min_dist,iter));
                hold on
            end
            if dims == 3, plot3(xy(1,1),xy(1,2),xy(1,3),'ko');
            else plot(xy(1,1),xy(1,2),'ko'); end
            hold off
        end
    end
 
    % Genetic Algorithm Operators
    rand_grouping = randperm(pop_size);
    for p = 8:8:pop_size
        rtes = pop_rte(rand_grouping(p-7:p),:);
        brks = pop_brk(rand_grouping(p-7:p),:);
        dists = total_dist(rand_grouping(p-7:p));
        [ignore,idx] = min(dists);
        best_of_8_rte = rtes(idx,:);
        best_of_8_brk = brks(idx,:);
        rte_ins_pts = sort(ceil(n*rand(1,2)));
        I = rte_ins_pts(1);
        J = rte_ins_pts(2);
        for k = 1:8 % Generate New Solutions
            tmp_pop_rte(k,:) = best_of_8_rte;
            tmp_pop_brk(k,:) = best_of_8_brk;
            switch k
                case 2 % Flip
                    tmp_pop_rte(k,I:J) = fliplr(tmp_pop_rte(k,I:J));
                case 3 % Swap
                    tmp_pop_rte(k,[I J]) = tmp_pop_rte(k,[J I]);
                case 4 % Slide
                    tmp_pop_rte(k,I:J) = tmp_pop_rte(k,[I+1:J I]);
                case 5 % Modify Breaks
                    tmp_pop_brk(k,:) = randbreaks();
                case 6 % Flip, Modify Breaks
                    tmp_pop_rte(k,I:J) = fliplr(tmp_pop_rte(k,I:J));
                    tmp_pop_brk(k,:) = randbreaks();
                case 7 % Swap, Modify Breaks
                    tmp_pop_rte(k,[I J]) = tmp_pop_rte(k,[J I]);
                    tmp_pop_brk(k,:) = randbreaks();
                case 8 % Slide, Modify Breaks
                    tmp_pop_rte(k,I:J) = tmp_pop_rte(k,[I+1:J I]);
                    tmp_pop_brk(k,:) = randbreaks();
                otherwise % Do Nothing
            end
        end
        new_pop_rte(p-7:p,:) = tmp_pop_rte;
        new_pop_brk(p-7:p,:) = tmp_pop_brk;
    end
    pop_rte = new_pop_rte;
    pop_brk = new_pop_brk;
end
 
if show_res
    % Plots
    figure('Name','MTSPF_GA | Results','Numbertitle','off');
    subplot(2,2,1);
    if dims == 3, plot3(xy(:,1),xy(:,2),xy(:,3),'k.');
    else plot(xy(:,1),xy(:,2),'k.'); end
    title(' Locations');
    subplot(2,2,2);
    imagesc(dmat([1 opt_rte],[1 opt_rte]));
    title('Distance Matrix');
    subplot(2,2,3);
    rng = [[1 opt_brk+1];[opt_brk n]]';
    for s = 1:salesmen
        rte = [1 opt_rte(rng(s,1):rng(s,2)) 1]
        if dims == 3, plot3(xy(rte,1),xy(rte,2),xy(rte,3),'.-','Color',clr(s,:));
        else plot(xy(rte,1),xy(rte,2),'.-','Color',clr(s,:)); end
        title(sprintf('Total time = %1.4f',min_dist));
        hold on;
    end
    if dims == 3, plot3(xy(1,1),xy(1,2),xy(1,3),'ko');
    else plot(xy(1,1),xy(1,2),'ko'); end
    subplot(2,2,4);
plot(dist_history,'b','LineWidth',2);
    title('Best Solution History');
    set(gca,'XLim',[0 num_iter+1],'YLim',[0 1.1*max([1 dist_history])]);
end
 
% Return Outputs
if nargout
    varargout{1} = opt_rte;
    varargout{2} = opt_brk;
    varargout{3} = min_dist;
end
 
    % Generate Random Set of Break Points
    function breaks = randbreaks()
        if min_tour == 1 % No Constraints on Breaks
            tmp_brks = randperm(n-1);
            breaks = sort(tmp_brks(1:num_brks));
        else % Force Breaks to be at Least the Minimum Tour Length
            num_adjust = find(rand < cum_prob,1)-1;
            spaces = ceil(num_brks*rand(1,num_adjust));
            adjust = zeros(1,num_brks);
            for kk = 1:num_brks
                adjust(kk) = sum(spaces == kk);
            end
            breaks = min_tour*(1:num_brks) + cumsum(adjust);
        end
    end
end
+1],'YLim',[0 1.1*max([1 dist_history])]);
end
 
% Return Outputs
if nargout
    varargout{1} = opt_rte;
    varargout{2} = opt_brk;
    varargout{3} = min_dist;
end
 
    % Generate Random Set of Break Points
    function breaks = randbreaks()
        if min_tour == 1 % No Constraints on Breaks
            tmp_brks = randperm(n-1);
            breaks = sort(tmp_brks(1:num_brks));
        else % Force Breaks to be at Least the Minimum Tour Length
            num_adjust = find(rand < cum_prob,1)-1;
            spaces = ceil(num_brks*rand(1,num_adjust));
            adjust = zeros(1,num_brks);
            for kk = 1:num_brks
                adjust(kk) = sum(spaces == kk);
            end
            breaks = min_tour*(1:num_brks) + cumsum(adjust);
        end
    end
end
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章