布雷斯悖论

本文详细解释了Braess悖论的概念,通过一个具体的交通网实例,阐述了在引入近路后,尽管理论上通行效率应该提高,但实际上却导致整体通行时间增加的现象。分析了原因在于司机个体行为的理性选择导致的整体最优策略失效。
布雷斯悖论的例子

考虑右图中的交通网,有4000辆车打算在其中路上通行。通过的时间从起点到A是路上车的数量除以100,而从起点到B是固定的45分钟(另一条路相同)。如果近路不存在(即交通网上只有4条路),从起点到A到终点需要的时间是 \tfrac{A}{100} + 45,而从起点到B到终点需要的时间是 \tfrac{B}{100} + 45。如果其中某条路的通过时间更短,是不可以达到纳什均衡的,因为任何一个理性的司机都会选择更短的路。因为有4000辆车,易知 A + B = 4000 可以解得 A = B = 2000 这样每条路的通过时间都是 \tfrac{2000}{100} + 45 = 65 分钟。

现在假设有了一条近路(通过时间接近于0),在这种情况下所有的司机都会选择从起点到A到B这条线路,因为就算所有的车都走这条路,通过时间也不过40分钟,小于起点到B的45分钟。到达A之后,所有的司机都会选择从用接近0的时间行驶到到B再到终点,因为就算所有的车都走这条路,通过时间也不过40分钟,小于A到终点的45分钟。这样所有车的通过时间是\tfrac{4000}{100} + \tfrac{4000}{100} = 80 分钟,比不存在近道的时候还多了15分钟。因为没有司机愿意切换到别的路上去,所以走原先的路线(起点A终点,起点B终点)的时间都变成了85分钟。如果大家都约定好不走近路,那么都可以节约15分钟的时间。但是,由于单个的司机总是能从抄近道上获益,所以这种约定是不稳定的,于是Braess悖论便出现了。



import networkx as nx import matplotlib.pyplot as plt from collections import defaultdict import numpy as np from itertools import product # 设置中文显示 plt.rcParams['font.family'] = 'SimHei' plt.rcParams['font.size'] = 10 class TrafficNetwork: def __init__(self, total_flow=300, discrete_units=30): self.total_flow = total_flow self.discrete_units = discrete_units self.unit_flow = total_flow / discrete_units self.G = nx.DiGraph() self.all_paths = [] self.integral_functions = {} def add_edge(self, u, v, cost_func, cost_label, integral_func=None): """添加边到网络""" self.G.add_edge(u, v, cost={'func': cost_func, 'label': cost_label}) if integral_func: self.integral_functions[(u, v)] = integral_func def setup_scenario(self, scenario): """设置不同场景的网络结构""" self.G.clear() self.integral_functions.clear() if scenario == 'a': # 原始网络 self.add_edge('A', 'C', lambda x: x/100, 'x/100', lambda x: x**2/200) self.add_edge('C', 'B', lambda x: 3.1, '3.1', lambda x: 3.1*x) self.add_edge('A', 'D', lambda x: 3.1, '3.1', lambda x: 3.1*x) self.add_edge('D', 'B', lambda x: x/100, 'x/100', lambda x: x**2/200) elif scenario == 'b': # 新增A-B直接路径 self.add_edge('A', 'C', lambda x: x/100, 'x/100', lambda x: x**2/200) self.add_edge('C', 'B', lambda x: 3.1, '3.1', lambda x: 3.1*x) self.add_edge('A', 'D', lambda x: 3.1, '3.1', lambda x: 3.1*x) self.add_edge('D', 'B', lambda x: x/100, 'x/100', lambda x: x**2/200) self.add_edge('A', 'B', lambda x: 5, '5', lambda x: 5*x) elif scenario == 'c': # 新增C-D路径,关闭A-B路径 self.add_edge('A', 'C', lambda x: x/100, 'x/100', lambda x: x**2/200) self.add_edge('C', 'B', lambda x: 3.1, '3.1', lambda x: 3.1*x) self.add_edge('C', 'D', lambda x: 0, '0', lambda x: 0) self.add_edge('A', 'D', lambda x: 3.1, '3.1', lambda x: 3.1*x) self.add_edge('D', 'B', lambda x: x/100, 'x/100', lambda x: x**2/200) elif scenario == 'd': # 重新开放A-B路径,保留C-D路径 self.add_edge('A', 'C', lambda x: x/100, 'x/100', lambda x: x**2/200) self.add_edge('C', 'B', lambda x: 3.1, '3.1', lambda x: 3.1*x) self.add_edge('C', 'D', lambda x: 0, '0', lambda x: 0) self.add_edge('A', 'D', lambda x: 3.1, '3.1', lambda x: 3.1*x) self.add_edge('D', 'B', lambda x: x/100, 'x/100', lambda x: x**2/200) self.add_edge('A', 'B', lambda x: 5, '5', lambda x: 5*x) self.all_paths = list(nx.all_simple_paths(self.G, source='A', target='B')) def generate_flow_combinations(self): """生成所有可能的流量分配组合""" combinations = [] ranges = [range(self.discrete_units + 1) for _ in range(len(self.all_paths))] for flows in product(*ranges): if sum(flows) == self.discrete_units: combinations.append(flows) return combinations def simulate_step(self, path_flows): """模拟单步流量分配""" edge_flows = defaultdict(float) path_times = {} # 计算各边流量 for path_id, flow in enumerate(path_flows): path = self.all_paths[path_id] for i in range(len(path) - 1): u, v = path[i], path[i + 1] edge_flows[(u, v)] += flow * self.unit_flow # 计算各边行驶时间 edge_times = {} for (u, v), flow in edge_flows.items(): cost_attr = self.G[u][v]['cost'] edge_times[(u, v)] = cost_attr['func'](flow) # 计算各路径行驶时间 for path_id, flow in enumerate(path_flows): path = self.all_paths[path_id] total_time = sum(edge_times.get((path[i], path[i+1]), 0) for i in range(len(path)-1)) path_times[path_id] = total_time return edge_flows, edge_times, path_times def calculate_metrics(self, edge_flows, edge_times): """计算社会成本和潜能值""" social_cost = sum(flow * time for (edge, flow), time in zip(edge_flows.items(), edge_times.values())) potential = sum(self.integral_functions[edge](flow) for edge, flow in edge_flows.items() if edge in self.integral_functions) return social_cost, potential def is_nash_equilibrium(self, path_flows, path_times, tol=1e-5): """检查是否为纳什均衡""" min_time = min(path_times.values()) for path_id, time in path_times.items(): if path_flows[path_id] > 0 and abs(time - min_time) > tol: return False if path_flows[path_id] == 0 and time < min_time - tol: return False return True def analyze_scenario(self, scenario): """分析特定场景""" self.setup_scenario(scenario) flow_combinations = self.generate_flow_combinations() social_costs = [] potentials = [] nash_equilibria = [] for flow_comb in flow_combinations: edge_flows, edge_times, path_times = self.simulate_step(flow_comb) sc, pot = self.calculate_metrics(edge_flows, edge_times) social_costs.append(sc) potentials.append(pot) if self.is_nash_equilibrium(flow_comb, path_times): nash_equilibria.append({ 'flows': flow_comb, 'social_cost': sc, 'potential': pot, 'edge_flows': edge_flows, 'edge_times': edge_times }) # 绘制结果 self.plot_results(scenario, social_costs, potentials, nash_equilibria) return nash_equilibria def plot_results(self, scenario, social_costs, potentials, nash_equilibria): """绘制分析结果""" plt.figure(figsize=(15, 10)) # 社会成本与潜能变化 plt.subplot(2, 2, 1) plt.plot(social_costs, 'b-', label='社会总成本') plt.plot(potentials, 'r-', label='潜能函数') # 标注纳什均衡点 for i, nash in enumerate(nash_equilibria): idx = social_costs.index(nash['social_cost']) plt.plot(idx, nash['social_cost'], 'go', markersize=8) plt.annotate(f'纳什均衡 {i+1}', xy=(idx, nash['social_cost']), xytext=(idx+0.5, nash['social_cost']+max(social_costs)*0.1), arrowprops=dict(arrowstyle="->", color='green'), fontsize=8) plt.xlabel('流量分配方案索引') plt.ylabel('时间 (分钟)') plt.title(f'场景({scenario}) - 社会成本与潜能变化') plt.legend() plt.grid(True) # 路径流量分布 plt.subplot(2, 2, 2) flow_combinations = self.generate_flow_combinations() path_flows = np.array(flow_combinations).T * self.unit_flow for i in range(len(self.all_paths)): plt.plot(path_flows[i], label=f'路径 {i+1}') for i, nash in enumerate(nash_equilibria): idx = social_costs.index(nash['social_cost']) plt.axvline(x=idx, color='g', linestyle='--', alpha=0.5) plt.annotate(f'纳什均衡 {i+1}', (idx, max(path_flows.max(axis=0))), textcoords="offset points", xytext=(0, 15), ha='center', fontsize=9, color='green') plt.xlabel('流量分配方案索引') plt.ylabel('流量 (辆车)') plt.title('各路径流量分布') plt.legend() plt.grid(True) # 绘制网络图 plt.subplot(2, 2, 3) pos = {'A': (0, 1), 'C': (1, 1.5), 'D': (1, 0.5), 'B': (2, 1)} edge_labels = {(u, v): data['cost']['label'] for u, v, data in self.G.edges(data=True)} nx.draw(self.G, pos, with_labels=True, node_size=2000, node_color='lightblue', font_size=12, arrows=True) nx.draw_networkx_edge_labels(self.G, pos, edge_labels=edge_labels, font_size=10) plt.title(f'场景({scenario}) 网络结构') # 纳什均衡流量分布 if nash_equilibria: plt.subplot(2, 2, 4) nash = nash_equilibria[0] edge_flows = nash['edge_flows'] # 计算边的使用率和颜色 max_flow = max(edge_flows.values()) if edge_flows else 1 edge_colors = [] edge_widths = [] for u, v in self.G.edges(): flow = edge_flows.get((u, v), 0) edge_colors.append('red' if flow > 0.5*max_flow else 'black') edge_widths.append(1 + 3*(flow/max_flow)) # 创建详细的边标签 detailed_labels = {} for u, v in self.G.edges(): flow = edge_flows.get((u, v), 0) time = nash['edge_times'].get((u, v), 0) label = self.G[u][v]['cost']['label'] detailed_labels[(u, v)] = f"{label}\n流量: {flow:.1f}\n时间: {time:.1f}" nx.draw(self.G, pos, with_labels=True, node_size=2000, node_color='lightblue', font_size=12, arrows=True, edge_color=edge_colors, width=edge_widths) nx.draw_networkx_edge_labels(self.G, pos, edge_labels=detailed_labels, font_size=8) plt.title('纳什均衡流量分布 (红色: 高流量边)') plt.tight_layout() plt.savefig(f'scenario_{scenario}.png') plt.close() # 打印纳什均衡信息 print(f"\n场景({scenario})分析结果:") for i, nash in enumerate(nash_equilibria): print(f"纳什均衡点 {i+1}:") print(f"路径流量分配: {[f'{f*self.unit_flow:.1f}' for f in nash['flows']]}") print(f"社会总成本: {nash['social_cost']:.2f} 分钟") print(f"潜能函数值: {nash['potential']:.2f}") print("各边流量详情:") for edge, flow in nash['edge_flows'].items(): print(f"边 {edge[0]}->{edge[1]}: {flow:.1f} 辆车") # 比较所有场景 def compare_scenarios(): """比较所有场景的社会成本""" network = TrafficNetwork() scenarios = ['a', 'b', 'c', 'd'] scenario_names = ['(a) 原始', '(b) 新增A-B', '(c) 新增C-D', '(d) 开放所有'] social_costs = [] for scenario in scenarios: nash_equilibria = network.analyze_scenario(scenario) if nash_equilibria: social_costs.append(nash_equilibria[0]['social_cost']) else: social_costs.append(0) # 绘制社会成本比较图 plt.figure(figsize=(10, 6)) bars = plt.bar(scenario_names, social_costs, color=['blue', 'green', 'red', 'purple']) # 添加数值标签 for bar in bars: height = bar.get_height() plt.annotate(f'{height:.1f}', xy=(bar.get_x() + bar.get_width() / 2, height), xytext=(0, 3), textcoords="offset points", ha='center', va='bottom') # 标记布雷斯悖论 if social_costs[2] > social_costs[0]: plt.annotate('布雷斯悖论!', xy=(2, social_costs[2]), xytext=(2.5, social_costs[2] + 100), arrowprops=dict(facecolor='red', shrink=0.05), fontsize=12, color='red') plt.xlabel('网络场景') plt.ylabel('社会总成本 (分钟)') plt.title('不同网络场景下的社会总成本比较') plt.grid(axis='y', linestyle='--', alpha=0.7) plt.tight_layout() plt.savefig('social_cost_comparison.png') plt.close() print("\n社会总成本比较:") for name, cost in zip(scenario_names, social_costs): print(f"{name}: {cost:.2f} 分钟") # 检查布雷斯悖论 print("\n布雷斯悖论分析:") if social_costs[2] > social_costs[0]: increase = social_costs[2] - social_costs[0] print(f"场景(c)新增C-D路径后,社会总成本增加了{increase:.2f}分钟(布雷斯悖论)") else: print("未检测到布雷斯悖论") if __name__ == "__main__": compare_scenarios()最后代码生成的图像中删除下面俩个有向图
06-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值