import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from matplotlib.widgets import Slider
import matplotlib.patches as mpatches
from matplotlib.colors import LinearSegmentedColormap
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['figure.figsize'] = (15, 10)
# ====================== 全局参数设置 ======================
BASE_PARAMS = {
'MU': 50, # 服务率 (车/小时)
'R': 60, # 单位时间收益 (元/小时)
'F': 36.7, # 固定成本 (元)
'D': 40, # 距离 (公里)
'S': 60, # 车速 (公里/小时)
'C': 1 # 平均载客数 (人/车)
}
# ====================== 决策模型 (基于成本比较) ======================
def taxi_decision(lambda_val, params):
"""出租车司机决策模型 - 基于成本比较"""
mu = params['MU']
R = params['R']
F = params['F']
D = params['D']
S = params['S']
# 处理边界情况
if lambda_val <= 0:
# 无需求时默认放空
return "放空", 0, F + (D/S)*R, 0
if lambda_val >= mu:
# 高负荷下的等待时间
rho = 0.999
Wq = 1 / (mu * (1 - rho))
else:
rho = lambda_val / mu
Wq = 1 / (mu * (1 - rho)) # 平均等待时间 (小时)
waiting_cost = Wq * R
relocation_cost = F + (D / S) * R
# 决策完全基于成本比较
decision = "等待" if waiting_cost <= relocation_cost else "放空"
return decision, waiting_cost, relocation_cost, Wq
# ====================== 成本对比可视化 ======================
def visualize_cost_comparison(params, lambda_range=(0, 100), num_points=100):
"""可视化不同需求下的成本对比和决策边界"""
lambda_values = np.linspace(lambda_range[0], lambda_range[1], num_points)
wait_costs = []
reloc_costs = []
decisions = []
for lambda_val in lambda_values:
decision, w_cost, r_cost, _ = taxi_decision(lambda_val, params)
wait_costs.append(w_cost)
reloc_costs.append(r_cost)
decisions.append(decision)
# 找到决策切换点
switch_idx = None
for i in range(1, len(lambda_values)):
if decisions[i] != decisions[i-1]:
switch_idx = i
break
# 创建图表
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10), sharex=True)
# 成本对比图
ax1.plot(lambda_values, wait_costs, 'b-', label='等待成本', linewidth=2)
ax1.plot(lambda_values, reloc_costs, 'r-', label='放空成本', linewidth=2)
if switch_idx is not None:
switch_lambda = lambda_values[switch_idx]
ax1.axvline(x=switch_lambda, color='g', linestyle='--',
label=f'决策阈值: λ={switch_lambda:.1f}车/小时')
ax1.text(switch_lambda, min(wait_costs[0], reloc_costs[0])*0.8,
f'临界点', rotation=90, fontsize=12, ha='center', va='bottom')
ax1.set_title('出租车决策成本对比分析', fontsize=16)
ax1.set_ylabel('成本 (元)', fontsize=12)
ax1.legend(fontsize=10)
ax1.grid(True, linestyle='--', alpha=0.7)
# 决策区域图
# 创建决策区域
ax2.fill_between(lambda_values, 0, 1,
where=np.array(decisions) == "等待",
color='lightblue', alpha=0.3)
ax2.fill_between(lambda_values, 0, 1,
where=np.array(decisions) == "放空",
color='lightcoral', alpha=0.3)
# 修复错误:将决策标签转换为颜色值
colors = ['blue' if d == "等待" else 'red' for d in decisions]
ax2.scatter(lambda_values, [0.5]*len(lambda_values), c=colors,
s=30, alpha=0.7)
# 添加图例
wait_patch = mpatches.Patch(color='lightblue', label='等待决策区')
reloc_patch = mpatches.Patch(color='lightcoral', label='放空决策区')
ax2.legend(handles=[wait_patch, reloc_patch], fontsize=10)
ax2.set_xlabel('出租车需求率 (λ, 车/小时)', fontsize=12)
ax2.set_yticks([])
ax2.set_title('决策区域分布', fontsize=14)
ax2.grid(True, linestyle='--', alpha=0.7)
# 标记当前需求
current_lambda = 60
current_decision, _, _, _ = taxi_decision(current_lambda, params)
ax1.axvline(x=current_lambda, color='m', linestyle='-')
ax1.plot(current_lambda,
wait_costs[np.abs(lambda_values - current_lambda).argmin()],
'mo', markersize=8)
ax1.text(current_lambda, ax1.get_ylim()[1]*0.9,
f'当前需求: {current_lambda}车/小时\n决策: {current_decision}',
fontsize=10, color='m')
plt.tight_layout()
plt.show()
def visualize_parameter_cost_impact(params, param_name, value_range, lambda_val=60):
"""可视化参数变化对成本的影响"""
param_values = np.linspace(value_range[0], value_range[1], 50)
wait_costs = []
reloc_costs = []
decisions = []
for value in param_values:
mod_params = params.copy()
mod_params[param_name] = value
decision, w_cost, r_cost, _ = taxi_decision(lambda_val, mod_params)
wait_costs.append(w_cost)
reloc_costs.append(r_cost)
decisions.append(decision)
# 找到决策切换点
switch_points = []
for i in range(1, len(param_values)):
if decisions[i] != decisions[i-1]:
switch_value = param_values[i]
switch_points.append(switch_value)
# 创建图表
fig, ax = plt.subplots(figsize=(12, 8))
# 绘制成本曲线
ax.plot(param_values, wait_costs, 'b-', label='等待成本', linewidth=2)
ax.plot(param_values, reloc_costs, 'r-', label='放空成本', linewidth=2)
# 标记决策切换点
for sp in switch_points:
ax.axvline(x=sp, color='g', linestyle='--')
ax.text(sp, min(min(wait_costs), min(reloc_costs)) * 0.8,
f'决策切换点: {sp:.2f}', rotation=90, fontsize=10)
# 标记当前参数值
current_value = params[param_name]
current_wait = wait_costs[np.abs(param_values - current_value).argmin()]
current_reloc = reloc_costs[np.abs(param_values - current_value).argmin()]
ax.plot(current_value, current_wait, 'bo', markersize=8)
ax.plot(current_value, current_reloc, 'ro', markersize=8)
ax.text(current_value, max(current_wait, current_reloc)*1.05,
f'当前值: {current_value}', fontsize=12, color='m')
# 添加当前决策信息
current_decision = decisions[np.abs(param_values - current_value).argmin()]
cost_diff = abs(current_wait - current_reloc)
ax.text(0.05, 0.95,
f'当前决策: {current_decision}\n成本差: {cost_diff:.2f}元',
transform=ax.transAxes, fontsize=12,
bbox=dict(facecolor='white', alpha=0.8))
ax.set_title(f'{param_name}变化对决策成本的影响 (λ={lambda_val}车/小时)', fontsize=16)
ax.set_xlabel(f'{param_name}值', fontsize=12)
ax.set_ylabel('成本 (元)', fontsize=12)
ax.legend(fontsize=10)
ax.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
return switch_points
def create_cost_comparison_dashboard(params):
"""创建成本比较仪表盘"""
fig = plt.figure(figsize=(16, 12))
gs = gridspec.GridSpec(3, 2, height_ratios=[1, 1, 0.2])
# 需求-成本主图
ax_main = plt.subplot(gs[0, :])
# 参数滑块位置
ax_mu = plt.axes([0.25, 0.05, 0.65, 0.03])
ax_r = plt.axes([0.25, 0.01, 0.65, 0.03])
# 创建滑块
slider_mu = Slider(ax_mu, '服务率(MU)', 30, 70, valinit=params['MU'])
slider_r = Slider(ax_r, '单位收益(R)', 40, 100, valinit=params['R'])
# 初始化数据
lambda_values = np.linspace(0, 100, 100)
wait_line, = ax_main.plot([], [], 'b-', label='等待成本', linewidth=2)
reloc_line, = ax_main.plot([], [], 'r-', label='放空成本', linewidth=2)
switch_line = ax_main.axvline(0, color='g', linestyle='--', label='决策阈值')
current_line = ax_main.axvline(60, color='m', linestyle='-')
current_point_wait, = ax_main.plot([], [], 'bo', markersize=8)
current_point_reloc, = ax_main.plot([], [], 'ro', markersize=8)
decision_text = ax_main.text(0.05, 0.95, '', transform=ax_main.transAxes,
fontsize=12, bbox=dict(facecolor='white', alpha=0.8))
# 决策区域图
ax_decision = plt.subplot(gs[1, :])
decision_fill_wait = ax_decision.fill_between([], [], [], color='lightblue', alpha=0.3)
decision_fill_reloc = ax_decision.fill_between([], [], [], color='lightcoral', alpha=0.3)
# 图例区域
ax_legend = plt.subplot(gs[2, :])
ax_legend.axis('off')
# 设置图表属性
ax_main.set_title('出租车决策成本比较仪表盘', fontsize=16)
ax_main.set_xlabel('出租车需求率 (λ, 车/小时)', fontsize=12)
ax_main.set_ylabel('成本 (元)', fontsize=12)
ax_main.grid(True, linestyle='--', alpha=0.7)
ax_main.legend(loc='upper right', fontsize=10)
ax_decision.set_title('决策区域分布', fontsize=14)
ax_decision.set_xlabel('出租车需求率 (λ, 车/小时)', fontsize=12)
ax_decision.set_yticks([])
ax_decision.grid(True, linestyle='--', alpha=0.7)
# 更新函数
def update(val):
# 更新参数
mod_params = params.copy()
mod_params['MU'] = slider_mu.val
mod_params['R'] = slider_r.val
# 计算新成本曲线
wait_costs = []
reloc_costs = []
decisions = []
for lambda_val in lambda_values:
decision, w_cost, r_cost, _ = taxi_decision(lambda_val, mod_params)
wait_costs.append(w_cost)
reloc_costs.append(r_cost)
decisions.append(decision)
# 更新主图
wait_line.set_data(lambda_values, wait_costs)
reloc_line.set_data(lambda_values, reloc_costs)
# 找到决策切换点
switch_idx = None
for i in range(1, len(lambda_values)):
if decisions[i] != decisions[i-1]:
switch_idx = i
break
if switch_idx is not None:
switch_lambda = lambda_values[switch_idx]
switch_line.set_xdata([switch_lambda, switch_lambda])
switch_line.set_label(f'决策阈值: λ={switch_lambda:.1f}')
else:
switch_line.set_xdata([])
# 更新当前需求点
current_lambda = 60
current_idx = np.abs(lambda_values - current_lambda).argmin()
current_decision = decisions[current_idx]
current_wait = wait_costs[current_idx]
current_reloc = reloc_costs[current_idx]
current_point_wait.set_data([current_lambda], [current_wait])
current_point_reloc.set_data([current_lambda], [current_reloc])
current_line.set_xdata([current_lambda, current_lambda])
cost_diff = abs(current_wait - current_reloc)
decision_text.set_text(f'当前需求: {current_lambda}车/小时\n当前决策: {current_decision}\n成本差: {cost_diff:.2f}元')
# 重新绘制决策区域
ax_decision.fill_between(lambda_values, 0, 1,
where=np.array(decisions) == "等待",
color='lightblue', alpha=0.3)
ax_decision.fill_between(lambda_values, 0, 1,
where=np.array(decisions) == "放空",
color='lightcoral', alpha=0.3)
# 更新图例
ax_legend.clear()
ax_legend.axis('off')
wait_patch = mpatches.Patch(color='lightblue', label='等待决策区')
reloc_patch = mpatches.Patch(color='lightcoral', label='放空决策区')
ax_legend.legend(handles=[wait_patch, reloc_patch],
loc='center', ncol=2, fontsize=12)
# 设置Y轴范围
max_cost = max(max(wait_costs), max(reloc_costs)) * 1.1
ax_main.set_ylim(0, max_cost)
fig.canvas.draw_idle()
# 初始更新
update(None)
# 注册更新函数
slider_mu.on_changed(update)
slider_r.on_changed(update)
plt.tight_layout()
plt.show()
def visualize_cost_difference(params, lambda_val=60):
"""可视化参数变化对成本差异的影响"""
fig = plt.figure(figsize=(15, 10))
# 定义参数和范围
parameters = {
'MU': (30, 70), # 服务率范围
'R': (40, 100), # 单位收益范围
'F': (20, 60), # 固定成本范围
'D': (20, 60), # 距离范围
'S': (40, 80) # 车速范围
}
# 创建2行3列的子图
axes = [plt.subplot(2, 3, i+1) for i in range(5)]
for ax, (param, (min_val, max_val)) in zip(axes, parameters.items()):
param_values = np.linspace(min_val, max_val, 50)
cost_diffs = []
decisions = []
for value in param_values:
mod_params = params.copy()
mod_params[param] = value
decision, w_cost, r_cost, _ = taxi_decision(lambda_val, mod_params)
cost_diff = w_cost - r_cost # 正数表示等待成本更高,负数表示放空成本更高
cost_diffs.append(cost_diff)
decisions.append(decision)
# 绘制成本差异曲线
ax.plot(param_values, cost_diffs, 'b-', linewidth=2)
ax.axhline(y=0, color='k', linestyle='--', alpha=0.5)
# 标记决策区域
ax.fill_between(param_values, cost_diffs, 0,
where=np.array(cost_diffs) > 0,
color='lightcoral', alpha=0.3)
ax.fill_between(param_values, cost_diffs, 0,
where=np.array(cost_diffs) < 0,
color='lightblue', alpha=0.3)
# 标记当前值
current_value = params[param]
current_idx = np.abs(param_values - current_value).argmin()
ax.plot(current_value, cost_diffs[current_idx], 'ro', markersize=8)
ax.text(current_value, cost_diffs[current_idx],
f'当前: {decisions[current_idx]}', fontsize=10, ha='center')
# 设置标题和标签
ax.set_title(f'{param}对成本差异的影响', fontsize=12)
ax.set_xlabel(f'{param}值', fontsize=10)
ax.set_ylabel('成本差异 (等待-放空)', fontsize=10)
ax.grid(True, linestyle='--', alpha=0.7)
# 添加总结图
ax_summary = plt.subplot(2, 3, 6)
# 计算每个参数的决策影响指数
impact_scores = []
for param, (min_val, max_val) in parameters.items():
min_params = params.copy()
min_params[param] = min_val
_, w_min, r_min, _ = taxi_decision(lambda_val, min_params)
max_params = params.copy()
max_params[param] = max_val
_, w_max, r_max, _ = taxi_decision(lambda_val, max_params)
# 计算成本差异变化幅度
impact = abs((w_min - r_min) - (w_max - r_max))
impact_scores.append(impact)
# 绘制决策影响图
colors = plt.cm.viridis(np.linspace(0, 1, len(parameters)))
bars = ax_summary.bar(parameters.keys(), impact_scores, color=colors)
# 添加数值标签
for bar in bars:
height = bar.get_height()
ax_summary.text(bar.get_x() + bar.get_width()/2., height,
f'{height:.2f}', ha='center', va='bottom', fontsize=10)
ax_summary.set_title('参数对决策的影响强度', fontsize=12)
ax_summary.set_ylabel('成本差异变化幅度', fontsize=10)
ax_summary.grid(True, axis='y', linestyle='--', alpha=0.7)
plt.suptitle(f'参数变化对成本差异的影响 (λ={lambda_val}车/小时)', fontsize=16)
plt.tight_layout(rect=[0, 0, 1, 0.95])
plt.show()
# ====================== 主函数 ======================
def main():
"""主函数:显示成本比较可视化"""
# 1. 显示成本对比分析
print("显示需求率与成本对比关系...")
visualize_cost_comparison(BASE_PARAMS)
# 2. 显示服务率(MU)对成本的影响
print("显示服务率(MU)对决策成本的影响...")
visualize_parameter_cost_impact(BASE_PARAMS, 'MU', (30, 70))
# 3. 显示单位收益(R)对成本的影响
print("显示单位收益(R)对决策成本的影响...")
visualize_parameter_cost_impact(BASE_PARAMS, 'R', (40, 100))
# 4. 显示成本差异分析
print("显示参数变化对成本差异的影响...")
visualize_cost_difference(BASE_PARAMS)
# 5. 显示成本比较仪表盘
print("显示成本比较交互式仪表盘...")
create_cost_comparison_dashboard(BASE_PARAMS)
print("所有成本比较可视化图表已显示完成!")
if __name__ == "__main__":
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 运行主函数
main()
基于以上代码再得出决策方案并得到其随时间变化的可视化图,以下是excel表中具体数据
时间 客流量
0:30 5909
1:30 640
2:30 0
3:30 0
4:30 0
5:30 0
6:30 0
7:30 0
8:30 2394
9:30 5713
10:30 6343
11:30 2839
12:30 4293
13:30 1996
14:30 3772
15:30 3696
16:30 3363
17:30 6411
18:30 3739
19:30 8931
20:30 5496
21:30 8735
22:30 4157
23:30 4832
最新发布