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()最后代码生成的图像中删除下面俩个有向图