《交通规划》——最短路分配方法

《交通规划》——最短路分配方法

说明:下面内容,将用python、networkx实现刘博航、杜胜品主编的《交通规划》P198页的例题,主要是实现最短路径分配方法。

1. 题目描述如下:

2. networkx构建网络

import networkx as nx
import matplotlib.pyplot as plt

# 带权重的边列表
edges = [(1,2,10), (1,3,4), (2,3,3), (2,4,5),(3,4,12),
         (2,1,10), (3,1,4), (3,2,3), (4,2,5),(4,3,12)]
nodes = [1,2,3,4]

# 创建无向图
G = nx.DiGraph()

# 添加节点
G.add_nodes_from(nodes)
G.add_weighted_edges_from(edges)

# 绘制图形
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True, node_color='lightblue', node_size=500, font_size=16, font_weight='bold')
labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels=labels, font_size=12, font_color='red')
plt.show()

nx.write_gexf(G,'./net9_2.gexf')

构建的网络为有向图:

《交通规划》——最短路分配方法_第1张图片

3. 输入OD矩阵,表9-8

import pandas as pd
import numpy as np
od = pd.DataFrame(
    data=
    {'A':[0,100,300],
    'B':[100,0,200],
    'C':[300,200,0]}
)

od.index = ['A', 'B', 'C']
od
od.to_csv('./OD_9-8.csv')

《交通规划》——最短路分配方法_第2张图片

4. 流量分配

思路:

  • 处理OD矩阵,处理成OD对
  • 遍历每一对OD对,找出OD对对应的最短路径,并存储
  • 遍历最短路径所经过的边,将流量分配到对应的边上

4.1 OD矩阵 -->OD对

import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt

#输入网络
G=  nx.read_gexf('./net9_2.gexf')

# 输入OD
od = pd.read_csv('./OD_9-8.csv',index_col=0)
od

# 将OD点和网络节点进行对应
od_map_nodes_dict = {
    'A':1,
    'B':3,
    'C':4
}
# 将OD表处理成OD对
od_new = od.unstack()
od_new = od_new.reset_index()
od_new = od_new.rename(dict(zip(list(od_new.columns),['O','D','q'])),axis=1) #q 表示交通小区之间的出行分布量
od_new

《交通规划》——最短路分配方法_第3张图片

4.2 初始化网络中的流量

# 初始化G中的flow属性
for u,v,data in G.edges(data = True):
    data['flow'] =0

边视图如下:

image-20230614200634972

4.3 遍历每对OD,查找最短路径,并分配流量

#!分配OD量
# 将各OD点对的OD量分配到该OD点对应的最短路径上,并进行累加
df = od_new
# 遍历DataFrame的每一行
for _, row in df.iterrows():
    # 获取流量
    flow = row['q']
    O = str(od_map_nodes_dict[row['O']])
    D = str(od_map_nodes_dict[row['D']])
    # 获取路径
    path = nx.shortest_path(G,O,D,'weight')
    print(row['O'],'-',row['D'],'shortest_path:',path)
    
    # 分配流量到路径上的每一条边
    for i in range(len(path) - 1):
        # 如果边已经存在,增加流量
        if G.has_edge(path[i], path[i+1]):
            if 'flow' in G[path[i]][path[i+1]]:
                G[path[i]][path[i+1]]['flow'] += flow
            else:
                G[path[i]][path[i+1]]['flow'] = flow
        # else:
            # G.add_edge(path[i], path[i+1], flow=flow)

# 输出结果
G.edges(data= True)

for u, v, data in G.edges(data=True):
    print(f"Edge: {u}-{v}, Flow: {data['flow']}")

结果(和书中一致):

《交通规划》——最短路分配方法_第4张图片

《交通规划》——最短路分配方法_第5张图片

5. 完整代码:

import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
#************************************************************************************************
od = pd.DataFrame(
    data=
    {'A':[0,100,300],
    'B':[100,0,200],
    'C':[300,200,0]}
)

od.index = ['A', 'B', 'C']
od
od.to_csv('./OD_9-8.csv')

#************************************************************************************************
# 带权重的边列表
edges = [(1,2,10), (1,3,4), (2,3,3), (2,4,5),(3,4,12),
         (2,1,10), (3,1,4), (3,2,3), (4,2,5),(4,3,12)]
nodes = [1,2,3,4]

# 创建无向图
G = nx.DiGraph()

# 添加节点
G.add_nodes_from(nodes)
G.add_weighted_edges_from(edges)

# 绘制图形
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True, node_color='lightblue', node_size=500, font_size=16, font_weight='bold')
labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels=labels, font_size=12, font_color='red')
plt.show()

nx.write_gexf(G,'./net9_2.gexf')


#************************************************************************************************
#输入网络
G=  nx.read_gexf('./net9_2.gexf')

# 输入OD
od = pd.read_csv('./OD_9-8.csv',index_col=0)
od

# 将OD点和网络节点进行对应
od_map_nodes_dict = {
    'A':1,
    'B':3,
    'C':4
}
# 将OD表处理成OD对
od_new = od.unstack()
od_new = od_new.reset_index()
od_new = od_new.rename(dict(zip(list(od_new.columns),['O','D','q'])),axis=1) #q 表示交通小区之间的出行分布量
od_new

# # 确定最短OD对之间的最短路径
# od_new['shortest_path'] = od_new.apply(lambda x:nx.shortest_path(G,str(od_map_nodes_dict[x['O']]),str(od_map_nodes_dict[x['D']]),weight='weight'),axis=1)
# # 将路径中的节点从字符串转化为整数,因为图G中的节点是整数
# od_new['shortest_path'] = od_new['shortest_path'].apply(lambda x: [int(node) for node in x])


#!分配OD量
# 将各OD点对的OD量分配到该OD点对应的最短路径上,并进行累加
df = od_new
# 初始化G中的flow属性
for u,v,data in G.edges(data = True):
    data['flow'] =0



G.edges(data = True)

#!分配OD量
# 将各OD点对的OD量分配到该OD点对应的最短路径上,并进行累加
df = od_new
# 遍历DataFrame的每一行
for _, row in df.iterrows():
    # 获取流量
    flow = row['q']
    O = str(od_map_nodes_dict[row['O']])
    D = str(od_map_nodes_dict[row['D']])
    # 获取路径
    path = nx.shortest_path(G,O,D,'weight')
    print(row['O'],'-',row['D'],'shortest_path:',path)
    
    # 分配流量到路径上的每一条边
    for i in range(len(path) - 1):
        # 如果边已经存在,增加流量
        if G.has_edge(path[i], path[i+1]):
            if 'flow' in G[path[i]][path[i+1]]:
                G[path[i]][path[i+1]]['flow'] += flow
            else:
                G[path[i]][path[i+1]]['flow'] = flow
        # else:
            # G.add_edge(path[i], path[i+1], flow=flow)

# 输出结果
G.edges(data= True)

for u, v, data in G.edges(data=True):
    print(f"Edge: {u}-{v}, Flow: {data['flow']}")
    

你可能感兴趣的:(python,交通)