絡(luò)平衡分析:從UE原理到Frank-Wolfe配流實現(xiàn))
簡介黃海軍的《城市交通網(wǎng)絡(luò)平衡分析理論與實踐》是一本聚焦城市交通網(wǎng)絡(luò)建模與優(yōu)化的專業(yè)文獻面向交通工程、軌道交通及相關(guān)領(lǐng)域的研究者、規(guī)劃師和高校師生旨在幫助讀者理解交通網(wǎng)絡(luò)平衡原理并應(yīng)對擁堵、延誤等城市交通頑疾為城市交通治理提供系統(tǒng)方法論。資源為單個PDF文件大小約8.1MB內(nèi)容精煉完整已有608人學(xué)習(xí)關(guān)注。理論層面書中系統(tǒng)涵蓋網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)分析、交通流基本規(guī)律、出行時間與速度變化特征、通行能力約束等核心內(nèi)容實踐層面則介紹了交通監(jiān)控系統(tǒng)、模擬仿真、優(yōu)化算法、信息化平臺和交通規(guī)劃設(shè)計等落地手段。全書將理論推導(dǎo)與工程應(yīng)用緊密結(jié)合適合作為交通網(wǎng)絡(luò)平衡分析的參考書助力讀者構(gòu)建從基礎(chǔ)概念到實際評估的系統(tǒng)知識框架。1. 城市交通網(wǎng)絡(luò)平衡分析拿到 OD 矩陣后堵車是怎么算出來的如果你手里只有一張早高峰 OD 矩陣和一套路網(wǎng)想提前知道明天哪個路口會排長隊交通分配就是那個把需求壓到路網(wǎng)上、算出每條路流量的環(huán)節(jié)。這個環(huán)節(jié)在學(xué)術(shù)界有個更嚴(yán)格的名字城市交通網(wǎng)絡(luò)平衡分析。黃海軍的《城市交通網(wǎng)絡(luò)平衡分析理論與實踐》把這個環(huán)節(jié)的數(shù)學(xué)根子講透了用戶均衡UE假設(shè)每個人都只走當(dāng)前最快的路系統(tǒng)最優(yōu)SO假設(shè)有人統(tǒng)一調(diào)度兩者之間的差距就是交通治理的空間。這本書適合兩類人——一類是在 TransCAD、Emme 里點鼠標(biāo)點到心虛的模型師另一類是想把商業(yè)軟件當(dāng)黑匣子拆開、自己寫配流內(nèi)核的研究者。下面我按“先立住概念、再交出可復(fù)現(xiàn)代碼、最后補齊踩坑”的順序把這個方向講成一張能照著施工的圖紙。2. 從用戶均衡到系統(tǒng)最優(yōu)模型假設(shè)與適用邊界交通分配的外行版本是“哪條路短走哪條”聽起來簡單但一旦所有車都這么想最短的路會變堵然后有人改走次短路最后收斂到一個誰都不愿意再換路的狀態(tài)。這個狀態(tài)才是平衡。黃海軍這套理論的核心是給這種“所有人互相博弈”的集體行為找一個嚴(yán)格數(shù)學(xué)定義。UE 和 SO 是這個定義的兩端UE 描述自由選擇下的現(xiàn)實SO 描述管制調(diào)度下的理想模型師必須在兩端之間反復(fù)切換才能回答不同層面的問題。2.1 用戶均衡每個司機都以為自己在走最快路用戶均衡直接來自 Wardrop 第一原理同一 OD 對之間所有被使用的路徑其行程時間相等并且小于等于任何未被使用路徑的行程時間。翻譯成人話沒有一個人能靠單方面換路縮短行程時間大家誰都沒動力再動系統(tǒng)就停了。光背定義不好消化我給個能用手算驗證的例子。設(shè) OD 需求 3000 pcu/h有兩條平行路徑A 路自由流 10 分鐘、通行能力 1000 pcu/hB 路自由流 15 分鐘、通行能力 2000 pcu/h。路阻函數(shù)用工程里最常見的 BPR 形式t_a(x_a) t_a^0 * (1 alpha * (x_a / cap_a)^beta)alpha 取 0.15beta 取 4。假設(shè)流量 x 走 A剩余 3000 - x 走 B均衡條件是兩條路時間相等10 * (1 0.15 * (x / 1000)^4) 15 * (1 0.15 * ((3000 - x) / 2000)^4)這個方程沒有手算解析解但用二分法卡幾個值就能找到答案A 路約 1410 pcu/hB 路約 1590 pcu/h均衡行程時間約 15.9 分鐘。我列一張表方便你對照路徑自由流時間min通行能力pcu/h均衡流量pcu/h均衡時間minA101000141015.9B152000159015.9注意一個容易被質(zhì)疑的細(xì)節(jié)A 路自由流快但容量小最后只分到 47% 的流量B 路自由流慢但容量大反而承擔(dān)更多。這就是“個體理性導(dǎo)致整體次優(yōu)”的第一層體現(xiàn)。在項目匯報里這張表對應(yīng)的場景是平行通道分擔(dān)失衡領(lǐng)導(dǎo)會問為什么快路沒被塞滿你把均衡時間算出來他才明白快路一旦塞滿就不再快。2.2 系統(tǒng)最優(yōu)為什么個體都理性路網(wǎng)反而沒在最優(yōu)如果把目標(biāo)從“每個司機自主選擇”換成“全網(wǎng)總行程時間最小”模型就切換到系統(tǒng)最優(yōu)。SO 的數(shù)學(xué)表達是min Z_SO Σ_a x_a * t_a(x_a)這個目標(biāo)函數(shù)直接用當(dāng)前行程時間做最短路是解錯的因為每個司機換路時不會考慮自己加入后對后面所有車造成的額外延誤。正確的路阻應(yīng)該是邊際時間成本t_a(x_a) x_a * d t_a / d x_a也就是讓每個使用者承擔(dān)“我多走一個單位流量給全網(wǎng)帶來的額外延遲”。BPR 函數(shù)代入后邊際項比普通項多出一個大數(shù)所以 SO 分配出來的流量會往容量更寬的路段轉(zhuǎn)移犧牲部分個體的短時利益來換整體效率。UE 和 SO 的總行程時間差距就是過度擁堵的量化值。拿上面兩條路徑繼續(xù)算UE 全網(wǎng)總時間約 3000 * 15.9 47700 分鐘SO 會引導(dǎo)更多車走 B 路總時間比 UE 低幾個百分點。真實路網(wǎng)中這個差距通常在 2% 到 15% 之間取決于網(wǎng)絡(luò)冗余度。做方案評估時如果你拿 UE 結(jié)果直接算“采取管理措施后節(jié)省了多少時間”等于假設(shè)司機真的服從調(diào)度。大多數(shù)項目里這個前提不成立所以評估限行、收費、信號優(yōu)先這類政策時要么用 SO 做理想上界要么在 UE 基礎(chǔ)上疊加行為響應(yīng)模型。2.3 程序員的讀法把均衡翻譯成凸優(yōu)化和最短路徑迭代UE 不只是一個經(jīng)濟學(xué)假設(shè)它有一個漂亮的等價數(shù)學(xué)形式Beckmann 變換。找一個流量向量 x極小化Z(x) Σ_a ∫_0^{x_a} t_a(w) dw這個目標(biāo)函數(shù)沒有直觀物理含義但它的梯度恰好是路段行程時間 t_a(x_a)而 UE 條件正好是它的一階最優(yōu)性條件也就是 KKT 條件。這是整本書里最值得反復(fù)讀的一段。只要 t_a 是嚴(yán)格單調(diào)遞增函數(shù)這個凸問題有唯一解Frank-Wolfe 算法就是順著這個性質(zhì)設(shè)計的。把理論翻譯成程序我習(xí)慣走三步把 Wardrop 條件寫成 KKT對每個 OD 對被使用路徑的時間等于最短 OD 時間未使用路徑的時間不低于它。把 BPR 路阻函數(shù)當(dāng)作目標(biāo)函數(shù)的梯度來源流量更新就等價于沿梯度方向逼近最優(yōu)。用“反復(fù)求最短路徑 沿方向走一小步”替代直接解非線性方程組因為真實路網(wǎng)有幾千個節(jié)點純解析解法在工程上不可行。這三步做完你會明白為什么配流軟件的底層循環(huán)都長一個樣算路段時間、全有全無分配、更新流量、檢查收斂。下一章就按這個循環(huán)把最小代碼寫出來。3. 用 Frank-Wolfe 把理論跑成配流程序最小可復(fù)現(xiàn)實現(xiàn)很多模型師覺得 UE 配流是商業(yè)軟件的內(nèi)置黑盒其實它的迭代邏輯非常短。這一章給一個能直接在 Jupyter 里跑的最小實現(xiàn)NetworkX 負(fù)責(zé)最短路搜索SciPy 做一維線搜索剩下的路線邏輯全部手寫方便你觀察中間過程、改參數(shù)、調(diào)試奇怪結(jié)果。3.1 數(shù)據(jù)準(zhǔn)備路網(wǎng)表、OD 表和 BPR 路阻參數(shù)先約定輸入格式。路網(wǎng)表至少要有四列起始節(jié)點、終到節(jié)點、自由流時間、通行能力。BPR 參數(shù) alpha 和 beta 可以放在邊屬性里方便按道路等級分開設(shè)置。OD 表就是起始、終到、需求量單位我統(tǒng)一用 pcu/h否則后面所有對比都會亂。參數(shù)常見初值作用踩坑提示alpha0.15擁堵項系數(shù)不同道路類型應(yīng)分開標(biāo)定beta4.0擁堵項指數(shù)beta 固定 4 時更容易擬合其他參數(shù)capacity實際通行能力決定曲線陡升位置雙車道不是單車道簡單乘 2demand分時段 OD輸入規(guī)模全天揉成一張 OD 基本不能用gap 閾值1e-4收斂判據(jù)商業(yè)軟件常用 0.1% 到 1%讀 CSV 建立 NetworkX 有向圖的代碼import networkx as nx G nx.DiGraph() with open(network.csv, encodingutf-8) as f: for row in f: parts row.strip().split(,) if len(parts) 6: continue u, v parts[0], parts[1] t0, cap float(parts[2]), float(parts[3]) alpha, beta float(parts[4]), float(parts[5]) # flow 初始為 0后面每次迭代直接更新邊屬性 G.add_edge(u, v, t0t0, capcap, alphaalpha, betabeta, flow0.0)節(jié)點 ID 可以是字符串也可以是整數(shù)但 CSV 和 OD 表必須保持一致。如果 OD 表里出現(xiàn)路網(wǎng)不存在的節(jié)點NetworkX 會在最短路搜索時報 KeyError這個錯誤信息對新手不太友好后面避坑章會專門講。3.2 UE 配流主循環(huán)從 AON 到收斂只需 60 行Frank-Wolfe 每次迭代做兩件事按當(dāng)前流量更新路段時間再做一次全有全無分配得到輔助流量然后沿兩者的差方向走一步。先寫路阻函數(shù)、全有全無分配和目標(biāo)函數(shù)from scipy.optimize import minimize_scalar def edge_cost(e, flow): # BPR 路阻函數(shù)自由流時間 * (1 alpha * (流量/容量)^beta) return e[t0] * (1 e[alpha] * (flow / e[cap]) ** e[beta]) def set_times(G, flow): for u, v, e in G.edges(dataTrue): e[time] edge_cost(e, flow[(u, v)]) def all_or_nothing(G, flow, od): set_times(G, flow) aux {(u, v): 0.0 for u, v in G.edges()} shortest_total 0.0 for o, d, q in od: dist nx.dijkstra_path_length(G, o, d, weighttime) shortest_total q * dist path nx.dijkstra_path(G, o, d, weighttime) for a, b in zip(path[:-1], path[1:]): aux[(a, b)] q return aux, shortest_total def objective(G, flow): # Beckmann 目標(biāo)函數(shù)積分用解析式展開beta1 出現(xiàn)在分母 z 0.0 for u, v, e in G.edges(dataTrue): cap, beta e[cap], e[beta] z e[t0] * (flow[(u, v)] e[alpha] * cap / (beta 1) * (flow[(u, v)] / cap) ** (beta 1)) return zedge_cost是 BPR 路阻all_or_nothing把每個 OD 的需求全壓到當(dāng)前最短路徑上同時返回按最短路徑時間算出的理想總時間為后面計算 gap 做準(zhǔn)備objective是 Beckmann 目標(biāo)函數(shù)注意積分展開后的系數(shù)beta 等于 4 時分母是 5。主循環(huán)如下flow {(u, v): 0.0 for u, v in G.edges()} aux, _ all_or_nothing(G, flow, od) for e in flow: flow[e] aux[e] for k in range(1, 200): aux, shortest_total all_or_nothing(G, flow, od) d {e: aux[e] - flow[e] for e in flow} # Frank-Wolfe 方向 def phi(lam): # 在當(dāng)前流與輔助流之間試一個步長返回目標(biāo)函數(shù)值 trial {e: flow[e] lam * d[e] for e in flow} return objective(G, trial) res minimize_scalar(phi, bounds(0, 1), methodbounded) lam res.x flow {e: flow[e] lam * d[e] for e in flow} sys_total sum(edge_cost(e, flow[e]) * flow[e] for u, v, e in G.edges(dataTrue)) gap (sys_total - shortest_total) / sys_total print(k, round(lam, 4), round(gap, 6)) if gap 1e-4: breakd是 Frank-Wolfe 方向phi(lam)做一維線搜索找一個讓目標(biāo)函數(shù)最小的步長。這里用scipy.optimize.minimize_scalar的有界搜索模式比手寫黃金分割省事且更穩(wěn)。輸出里gap就是相對對偶間隙gap 降到 1e-4 以下認(rèn)為收斂。商業(yè)軟件默認(rèn)閾值經(jīng)常是 0.1% 到 1%自寫程序建議至少放到 1e-4否則斷面流量會差幾個百分點。3.3 步長與收斂判據(jù)MSA 和線搜索該選哪個Frank-Wolfe 最經(jīng)典的簡化是固定步長 1/k這個方案叫 MSA代碼只需替換一行l(wèi)am 1.0 / k不需要線搜索。它的優(yōu)點是穩(wěn)定不會在目標(biāo)函數(shù)不平滑時亂跳缺點是收斂慢。BPR 在容量附近很陡目標(biāo)函數(shù)接近但并不是嚴(yán)格的二次型1/k 的衰減速度在后期會讓 gap 卡在 1e-2 級別看起來很急。我的習(xí)慣是教學(xué)網(wǎng)絡(luò)和剛跑通的骨架用 MSA因為行為容易解釋真實路網(wǎng)第一版一定用線搜索等模型跑順后再評估要不要換投影類算法。線搜索還能順帶檢查目標(biāo)函數(shù)寫沒寫錯——如果minimize_scalar返回的步長長期在 0.01 以下往往不是算法問題而是某個邊容量小到離譜流量一上去路阻就爆了。相對對偶間隙的完整公式gap (Σ_a x_a * t_a(x_a) - Σ_rs q_rs * u_rs) / Σ_a x_a * t_a(x_a)其中 u_rs 是當(dāng)前路段時間下 OD 對 rs 的最短路徑時間。分子是“全網(wǎng)因為繞路多花的時間”分母是“當(dāng)前實際總行程時間”。gap 高說明還有大量車沒找到更短路徑gap 低說明再重新分配也榨不出多少收益。第五個避坑點里 gap 卡住不降的問題就是從這個公式發(fā)端的。4. 把配流結(jié)果當(dāng)工具用五個關(guān)鍵參數(shù)與校正順序跑通最小實現(xiàn)后真正的工程挑戰(zhàn)是讓結(jié)果可信。這一章集中講五個關(guān)鍵參數(shù)alpha、beta、capacity、OD 需求、收斂閾值。前四個決定模型的骨架最后一個決定你信不信這個骨架。校準(zhǔn)時有個鐵律先修路網(wǎng)再調(diào)容量最后才動 OD順序亂了基本等于給自己挖坑。4.1 BPR 標(biāo)定別把 0.15/4 當(dāng)萬能默認(rèn)值BPR 里的 0.15 和 4 是教材默認(rèn)值最初來自高速公路回歸經(jīng)驗換到城市快速路、信號交叉口、匝道就不一定對。最務(wù)實的做法是找?guī)锥斡芯€圈檢測的路段拿到分時段流量和實際行程時間用最小二乘擬合 alpha 和 betafrom scipy.optimize import curve_fit def bpr(v, t0, cap, alpha, beta): return t0 * (1 alpha * (v / cap) ** beta) # volume 是觀測流量序列travel_time 是同一時段的實際行程時間 popt, _ curve_fit(bpr, volume, travel_time, p0[10, 1000, 0.15, 4.0])volume和travel_time來自同一路段的歷史檢測數(shù)據(jù)。這里有個統(tǒng)計陷阱beta 對曲線尾部形狀影響極大但日常觀測數(shù)據(jù)往往集中在低飽和度區(qū)間beta 的辨識度很差。所以我一般固定 beta 4只標(biāo)定 alpha、t0、cap。t0 用平峰自由流車速反推cap 用斷面飽和流率實測alpha 只用擁堵時段的流量時間對擬合這樣每個參數(shù)都有物理錨點不會出現(xiàn)“擬合出來 alpha 是負(fù)數(shù)”這種玄學(xué)結(jié)果。4.2 OD 矩陣配流結(jié)果一半的誤差出在需求矩陣上很多第一次自建模型的人把注意力全放在算法上忽略配流對 OD 矩陣的敏感程度。OD 需求差 10%擁堵路段流量可能差 20% 以上因為 BPR 曲線在容量附近是非線性的流量一過 capacity 時間曲線直接抬頭。常見做法是先按早高峰 1 小時、平峰 1 小時、晚高峰 1 小時分別做時段 OD而不是把全天 24 小時揉成一張表。如果只有 24 小時總量就先按調(diào)查得到的時間分布系數(shù)拆成時段需求。OD 矩陣還需要平滑相鄰小區(qū)之間的需求往往會集中在少數(shù)幾條路徑原始 OD 直接分配會讓某些路段流量比實測高 30%另一些路段是 0。這時可以引入隨機項做 SUE 分配或者對 OD 做空間平滑。但千萬別為了擬合斷面流量而“拍腦袋調(diào) OD”那是在給自己埋雷后面第 4.3 節(jié)會解釋為什么。4.3 用 GEH 校驗斷面流量先修路網(wǎng)再修 OD配流完成后的第一件事是把模型斷面流量和線圈檢測值對一對。工程界常用 GEH 指標(biāo)GEH sqrt( 2 * (q_est - q_obs)^2 / (q_est q_obs) )GEH 范圍建議 5可接受5 ~ 10需檢查周邊路網(wǎng)編碼與容量 10必須查 OD 或路網(wǎng)不能跳過調(diào)模型有個順序也是血淚經(jīng)驗先查路網(wǎng)編碼錯沒錯再調(diào)通行能力和自由流時間最后才動 OD。很多人一上來就調(diào) OD結(jié)果斷面流量對上了但路徑結(jié)構(gòu)完全不合理回頭想改回真實需求難如登天。路網(wǎng)是底子OD 是需求事實兩者都不該為了擬合觀測隨意改動。遇到 GEH 大于 10 的斷面我一般先打開路網(wǎng)看上下游有沒有斷邊、方向反、節(jié)點拼錯這類低級錯誤在自建模型里能占到一半以上。另外收斂閾值不要一上來就要求 1e-6。真實路網(wǎng)的觀測誤差本身就大于 5%把 gap 壓到 1e-6 只會讓模型吞掉大量噪聲時間花在不必要的迭代上。我的做法是基礎(chǔ)方案用 1e-4方案對比時統(tǒng)一用 1e-4只有寫論文時才跑 1e-6。5. 配流避坑指南求解器不收斂到反常識結(jié)果五個高頻翻車現(xiàn)場理論講得再漂亮一跑真實路網(wǎng)就露餡。下面五個問題是我在項目里反復(fù)遇到的每個都按現(xiàn)象、原因、解決三段寫你復(fù)現(xiàn)時大概率會撞上至少一個。5.1 現(xiàn)象迭代 200 次gap 還在 1% 附近鋸齒狀看起來結(jié)果已經(jīng)“差不多”但閾值降到 1e-4 就是達不到gap 曲線像鋸齒一樣上下跳。原因通常是步長策略和路阻函數(shù)不匹配如果用 MSA1/k 衰減太慢后期每一步都在原地踏步如果用線搜索則可能是某個邊容量設(shè)得過大路阻函數(shù)太平滑方向向量 d 已經(jīng)接近零。解決方法是先改用線搜索再檢查有沒有容量小到離譜的邊如果問題依舊就把 gap 定義里的最短路目標(biāo)項加上轉(zhuǎn)向懲罰不要讓模型利用不現(xiàn)實的繞行路徑。5.2 現(xiàn)象路段行程時間比自由流還低BPR 函數(shù)的輸出永遠(yuǎn)大于等于自由流時間所以出現(xiàn)比自由流還低的結(jié)果一定是公式實現(xiàn)錯了。最常見原因是在代碼里寫成了t0 * alpha * (flow / cap) ** beta少了括號里的1 其次是流量和容量單位不一致流量是 pcu/h容量標(biāo)成了 veh/s數(shù)值上看起來像負(fù)數(shù)校正。解決寫一個單元測試構(gòu)造流量為 0 的邊斷言返回 t0構(gòu)造流量等于 capacity 的邊斷言返回 t0 * (1 alpha)。這兩行斷言能擋住一半以上的低級錯誤。5.3 現(xiàn)象零流量路段永遠(yuǎn)是 0手算時明明該有車UE 的性質(zhì)決定“未使用路徑”流量就是 0但為什么一條和最短路徑只差 0.1 分鐘的平行邊沒車第一初始化全 0 后第一次 AON 選擇了最短邊之后線搜索步長如果一直小于 1較慢邊始終分不到流量第二這其實是 UE 的角點解在真實世界很難出現(xiàn)因為沒人能掌握精確到 0.1 分鐘的路徑時間。解決如果關(guān)心這類接近并列的路徑就不要用純 UE改用 SUE 或者給路徑加一個感知誤差項。UE 適合看擁堵主骨架不適合回答“為什么這條次路一輛車都沒有”的微觀問題。5.4 現(xiàn)象MSA 步長讓流量像布朗運動收斂曲線拉不回來MSA 的 1/k 理論上能保證收斂但真實路網(wǎng)有大量非線性步長序列會帶來長時間震蕩?,F(xiàn)象是前幾十次迭代流量大幅擺動后面擺幅減小但 gap 紋絲不動。解決把固定步長換成線搜索后基本能恢復(fù)如果還想保留 MSA 的簡潔可以用幾何平均步長或?qū)ι洗蔚髁孔鲋笖?shù)平滑。注意震蕩本身是信息如果震蕩幅度大到 10%說明路網(wǎng)存在兩條幾乎一樣短的路模型在它們之間來回跳這時候該去看路徑集而不是繼續(xù)調(diào)參數(shù)。5.5 現(xiàn)象商業(yè)軟件和自己寫的程序結(jié)果差兩成懷疑書錯了自寫 UE 收斂到 1e-4和商業(yè)軟件默認(rèn)結(jié)果差 20%第一反應(yīng)通常是理論有問題。實際查下來大概率是三個差異疊加商業(yè)軟件默認(rèn)用 SUE 或帶路徑規(guī)模懲罰的模型BPR 參數(shù)和你設(shè)置的不一致收斂閾值不同。還有一個容易被忽略的因素是商業(yè)軟件對零點流量做了平滑處理。解決先把兩邊路網(wǎng)、OD、BPR 參數(shù)、收斂閾值統(tǒng)一成完全一樣的輸入再用一個只有兩條路徑的小網(wǎng)絡(luò)做對照實驗。如果小網(wǎng)絡(luò)一致、大網(wǎng)絡(luò)不一致再去排查轉(zhuǎn)向阻抗、收費、信號延誤等附加邏輯。6. 進階玩法把平衡配流接到交通仿真之前先做三件事當(dāng)你把 UE 跑穩(wěn)下一步不是馬上接仿真軟件而是先做三件常規(guī)驗證否則仿真階段翻車的代價會高出十倍。6.1 先做多模式均衡公交和小汽車的迭代反饋真實路網(wǎng)里公交和小汽車共享路權(quán)公交太慢會讓更多人開小汽車小汽車變多又反過來讓公交延誤增加。常見做法是雙層迭代先跑小汽車 UE得到各路段時間更新公交行程時間然后用 logit 模型調(diào)整模式分擔(dān)比例重新生成 OD再跑配流直到分擔(dān)比例變化小于 0.5%。注意 logit 的尺度參數(shù)需要單獨標(biāo)定否則分擔(dān)比例對時間差過于敏感一次小小的擁堵改善就可能讓公交分擔(dān)率暴漲 10 個百分點。6.2 用 KKT 條件給求解器做體檢路徑時間相等嗎UE 收斂后抽幾個需求大的 OD 對枚舉前若干條路徑檢查它們的時間是否真的相等。代碼很短for path in nx.shortest_simple_paths(G, o, d, weighttime, cutoff5): tt sum(G[a][b][time] for a, b in zip(path[:-1], path[1:])) print(round(tt, 4), path)只要被使用的路徑和枚舉出的最短路徑時間差超過 0.1%就說明收斂判據(jù)或路徑加載邏輯還有問題。大路網(wǎng)枚舉不了所有路徑就退回去看 gapgap 到 1e-4 之后路徑時間差通常在 0.05% 以內(nèi)。6.3 做一張敏感性參數(shù)表擾動 OD 和容量看流量變化范圍最后往 OD 需求上加 ±10% 擾動再把關(guān)鍵路段容量調(diào)高調(diào)低 10%各跑二十次配流把重點斷面的流量變化范圍記成一張表。這個表才是給決策者的交付物比單點結(jié)果更接近真實不確定性。我現(xiàn)在每個項目交付前都會跑一遍這個敏感性矩陣花二十分鐘能擋掉后面一個月的扯皮。希望幫到你。本文還有配套的精品資源點擊獲取