首页 > 编程语言 >《交通规划》——python实现最短路分配方法

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

时间:2023-06-14 20:23:10浏览次数:41  
标签:OD python 短路 od flow nx new path 分配

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

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

1. 题目描述如下:

IMG_0624

IMG_0625

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')

构建的网络为有向图:

image-20230614195842282

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')

image-20230614200104793

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

image-20230614200503098

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']}")

结果(和书中一致):

image-20230614200809713

IMG_0626

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']}")
    

标签:OD,python,短路,od,flow,nx,new,path,分配
From: https://www.cnblogs.com/aleza/p/17481267.html

相关文章

  • python opencv rtsp
       #coding:utf-8#打开摄像头并灰度化显示importcv2ascvcamera_id="rtsp://admin:[email protected]:554/jingli/realmonitor?channel=1&subtype=0"#0表示摄像头的编号capture=cv.VideoCapture(camera_id)while(True):ret,frame=capture.re......
  • Python教程-多线程与多进程
    什么是线程,什么是进程?进程是程序(软件,应用)的一个执行实例,每个运行中的程序,可以同时创建多个进程,但至少要有一个。每个进程都提供执行程序所需的所有资源,都有一个虚拟的地址空间、可执行的代码、操作系统的接口、安全的上下文(记录启动该进程的用户和权限等等)、唯一的进程ID、环境变......
  • python装饰器函数学习笔记
    函数也是一个对象,并且这个对象可以被赋值给变量,所以,我们可以通过变量调用该函数defnow():...print('2015-3-25')...f=nowf()2015-3-25函数对象有一个__name__属性,可以拿到函数名字:now.name'now'f.name'now'现在如果我们要增强now()函数的功能,比如,在......
  • python返回函数学习笔记
    内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力deflazy_sum(*args):defsum():ax=0forninargs:ax=ax+nreturnaxreturn......
  • Python基础——网络编程
    在网络编程中主要是使用Socket(套接字)进行编程,套接字相当于应用程序访问下层网络的服务的接口,使用Socket可以是得不同主机之间进行通信,从而实现数据交换。1、Socket工作方式套接字在工作的时候连接的两端分别为客户端和服务器端,对于客户端和服务器端的工作方式是不一样的。对于服......
  • Python中时间与时间戳之间的转换
    对于时间数据,如2016-05-0520:28:54,有时需要与时间戳进行相互的运算,此时就需要对两种形式进行转换,在Python中,转换时需要用到time模块,具体的操作有如下的几种:将时间转换为时间戳重新格式化时间时间戳转换为时间获取当前时间及将其转换成时间戳1、将时间转换成时间戳将如上的时间2016......
  • 软件测试|教你用Python处理PDF文件(一)
    前言点击获取更多技术资料!我们在工作中,难免会遇到需要处理PDF文件的情况,PDF文件与Word文件不同,内容提取不是很容易,表格和图片都需要特别处理。不过PDF有一个优势,PDF可以跨平台使用,Windows系统,Mac系统都可以打开PDF文件,不像doc文件,需要在word或者类似的软件中才能打开。但是PDF......
  • python nohup 远程运行不宕机方法
    远程运行最怕断电,训练了几个小时的数据说没就没,或者停止运行。用nohup记录代码的输出,还可以不受断电的影响。方法1.用nohup运行一个python文件nohuppython-umain.py>nohup.out2>&1&除了main.py换成自己的文件名,nohup.out也可以改为其他名字,nohup1.out等。其余照搬。不......
  • python GUI+爬虫——12306抢票软件(2)
    这部分主要是项目环境的配置,下图是概览1.基于项目的虚拟环境--pipenv1.1简介1.2安装pipinstallpipenv, 检查安装状态:pipenv--version 我的系统是mac,该项目使用Windows10开发更好1.3创建项目的虚拟环境,使用pycharm1.4创建完后修改安装源,修改位置为pipfile文件修改:来源修......
  • python偏函数学习笔记
    Python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partialfunction)比如,int函数默认十进制转换,若提供其它base参数,就可以进行n进制转换int('12345',base=8)5349int('12345',16)74565定义一个int2()的函数,默认把base=2传进去defint2(x,base=2):retu......