使用aequilibrae进行多类交通分配时的维度不匹配错误解决
多类交通均衡分配中不同Graph形状导致的ValueError解决
问题描述
使用Python的aequilibrae包执行多类交通均衡分配时,调用assig.execute()后抛出ValueError: operands could not be broadcast together with shapes (11202,) (9184,)。原因是不同交通类使用了不同结构的网络(对应g_usa、g_china、g_neutral三个Graph,节点/边数量不一致)。
脚本片段
%%time aem_usa = AequilibraeMatrix() aem_china = AequilibraeMatrix() aem_neutral= AequilibraeMatrix() os.chdir("D:/Professional/Mir/1_multi_class_analysis/7_matrix_bin/") #setting directory #load aem file aem_usa.load("Demand_usa.aem") aem_usa.computational_view(["matrix"]) aem_china.load("Demand_china.aem") aem_china.computational_view(["matrix"]) aem_neutral.load("Demand_neutral.aem") aem_neutral.computational_view(["matrix"]) #now assign classes tc_usa= TrafficClass("usa_flow", g_usa, aem_usa) tc_china=TrafficClass("china_flow", g_china, aem_china) #tc_china.set_pce(1) tc_neutral= TrafficClass("neutral_flow", g_neutral, aem_neutral) #set classes assig= TrafficAssignment() assig.set_classes([tc_china, tc_neutral]) assig.set_vdf("BPR") assig.set_vdf_parameters({"alpha":0, "beta":1}) assig.set_capacity_field("capacity") assig.set_algorithm("all-or-nothing") assig.max_iter = 100 assig.rgap_target = 1e-6 assig.execute()
错误信息
{ "name": "ValueError", "message": "operands could not be broadcast together with shapes (11202,) (9184,) ", "stack": "--------------------------------------------------------------------------- ValueError Traceback (most recent call last) File <timed exec>:36 File c:\Users\Raisul\anaconda3\envs\my_env\Lib\site-packages\aequilibrae\paths\traffic_assignment.py:432, in TrafficAssignment.execute(self, log_specification) 430 if log_specification: 431 self.log_specification() --> 432 self.assignment.execute() File c:\Users\Raisul\anaconda3\envs\my_env\Lib\site-packages\aequilibrae\paths\linear_approximation.py:388, in LinearApproximation.execute(self) 384 self.__maybe_create_path_file_directories() 386 for c in self.traffic_classes: # type: TrafficClass 387 # cost = c.fixed_cost / c.vot + self.congested_time # now only once --> 388 cost = c.fixed_cost + self.congested_time 389 aggregate_link_costs(cost, c.graph.compact_cost, c.results.crosswalk) 391 aon = allOrNothing(c.matrix, c.graph, c._aon_results) ValueError: operands could not be broadcast together with shapes (11202,) (9184,) " }
解决方案(保留不同Graph形状的前提下)
aequilibrae的多类交通分配默认要求所有交通类共享同一基础网络结构(即所有Graph的边数、节点映射必须一致),因为分配过程中需要统一计算拥堵时间等全局变量。要在保留不同Graph的前提下完成分配,可采用以下两种思路:
1. 拆分独立分配,手动合并结果
对每个交通类单独执行交通分配,再将各类型的流量结果合并到统一的网络中:
# 定义通用分配配置函数 def run_single_class_assignment(traffic_class): assig = TrafficAssignment() assig.set_classes([traffic_class]) assig.set_vdf("BPR") assig.set_vdf_parameters({"alpha":0, "beta":1}) assig.set_capacity_field("capacity") assig.set_algorithm("all-or-nothing") assig.max_iter = 100 assig.rgap_target = 1e-6 assig.execute() return assig # 分别执行三类分配 assig_usa = run_single_class_assignment(tc_usa) assig_china = run_single_class_assignment(tc_china) assig_neutral = run_single_class_assignment(tc_neutral) # 手动合并结果(需确保各网络的边有唯一标识可匹配) # 示例:假设所有网络的边都有相同的'link_id'字段 # 先获取各分配结果的边流量数据 usa_flows = assig_usa.results.get_link_flows() china_flows = assig_china.results.get_link_flows() neutral_flows = assig_neutral.results.get_link_flows() # 合并到统一DataFrame merged_flows = usa_flows.merge(china_flows, on='link_id', how='outer', suffixes=('_usa', '_china')) merged_flows = merged_flows.merge(neutral_flows, on='link_id', how='outer', suffixes=('', '_neutral')) merged_flows.fillna(0, inplace=True)
2. 构建统一超网络,适配所有交通类
将三个不同的网络合并为一个包含所有边的超网络,然后为每个交通类设置对应的边通行规则(比如对某类不可通行的边设置无穷大成本或0容量):
# 假设三个网络都是从同一基础GeoDataFrame衍生的,先合并所有边 import pandas as pd from aequilibrae.paths import Graph # 合并三个网络的边数据(需确保字段一致) combined_edges = pd.concat([g_usa.network, g_china.network, g_neutral.network]).drop_duplicates(subset='link_id') # 创建统一超网络的Graph g_combined = Graph() g_combined.load_from_geodataframe(combined_edges, directed=True) # 为每个交通类设置专属成本:对该类不可通行的边设置极高成本 # 示例:USA类只能走g_usa的边,其他边成本设为1e10 tc_usa = TrafficClass("usa_flow", g_combined, aem_usa) # 获取g_usa的link_id集合 usa_link_ids = set(g_usa.network['link_id']) # 筛选出超网络中不属于USA的边,设置成本为极大值 non_usa_indices = g_combined.network[~g_combined.network['link_id'].isin(usa_link_ids)].index tc_usa.graph.free_flow_time.iloc[non_usa_indices] = 1e10 # 同理处理China和Neutral类 tc_china = TrafficClass("china_flow", g_combined, aem_china) china_link_ids = set(g_china.network['link_id']) non_china_indices = g_combined.network[~g_combined.network['link_id'].isin(china_link_ids)].index tc_china.graph.free_flow_time.iloc[non_china_indices] = 1e10 tc_neutral = TrafficClass("neutral_flow", g_combined, aem_neutral) neutral_link_ids = set(g_neutral.network['link_id']) non_neutral_indices = g_combined.network[~g_combined.network['link_id'].isin(neutral_link_ids)].index tc_neutral.graph.free_flow_time.iloc[non_neutral_indices] = 1e10 # 现在执行多类分配 assig = TrafficAssignment() assig.set_classes([tc_china, tc_neutral, tc_usa]) assig.set_vdf("BPR") assig.set_vdf_parameters({"alpha":0, "beta":1}) assig.set_capacity_field("capacity") assig.set_algorithm("all-or-nothing") assig.max_iter = 100 assig.rgap_target = 1e-6 assig.execute() # 获取合并后的各类流量结果 combined_results = assig.results.get_link_flows()
关键说明
- 第一种方法更直接,适合各网络重叠度低的场景,但无法模拟不同类流量之间的拥堵相互影响(因为是独立分配)。
- 第二种方法能保留多类分配的拥堵交互效果,但需要确保超网络的边标识统一,且正确设置各类的通行限制。
内容的提问来源于stack exchange,提问作者MIr Raisul Islam
相关产品推荐
相关产品推荐

