import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import simpy
from pulp import LpMinimize, LpProblem, LpVariable
import seaborn as sns
from scipy.stats import gamma
# 设置中文显示
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
class SharedVehicleEvaluationSystem:
"""共享车辆评估系统,用于分析不同类型共享车辆的引入对系统性能的影响"""
def __init__(self, config=None):
"""初始化评估系统"""
self.config = config or {
'total_vehicles': 1000, # 车辆总数
'simulation_days': 30, # 仿真天数
'scenarios': ['base', 'cost_sensitive', 'distance_sensitive', 'mixed_cost_performance'] # 仿真场景
}
self.user_profiles = None
self.vehicle_costs = None
self.road_capacity = None
self.results = {}
def prepare_data(self):
"""准备评估所需的数据"""
# 用户群体参数
self.user_profiles = pd.DataFrame({
'age_group': ['18-25', '26-35', '36-45', '46+'],
'bike_preference': [0.6, 0.4, 0.3, 0.5],
'ebike_preference': [0.3, 0.5, 0.4, 0.3],
'moped_preference': [0.1, 0.1, 0.3, 0.2],
'trip_frequency': [14, 10, 8, 6], # 每周出行次数
'avg_trip_distance': [3.2, 5.7, 4.1, 2.8], # 平均出行距离(km)
'income_level': [2, 3, 3, 2], # 收入水平(1-5)
'cost_sensitivity': [0.8, 0.6, 0.5, 0.7], # 成本敏感度(1-10)
'time_sensitivity': [0.7, 0.9, 0.8, 0.6] # 时间敏感度(1-10)
})
# 车辆成本参数
self.vehicle_costs = {
'bike': {
'purchase': 300, # 购置成本(元)
'maintenance': 0.5, # 每日维护成本(元)
'lifespan': 3, # 使用寿命(年)
'max_speed': 15, # 最高速度(km/h)
'energy_cost': 0, # 能源成本(元/公里)
'fixed_ride_fee': 1, # 固定骑行费用(元)
'variable_fee_rate': 0.5 # 可变费用率(元/公里)
},
'ebike': {
'purchase': 1200,
'maintenance': 1.5,
'battery_replacement': 300, # 电池更换成本(元/次)
'battery_life': 300, # 电池寿命(公里)
'battery_capacity': 10, # 电池容量(km/次充电)
'charging_time': 2, # 充电时间(小时)
'charging_cost': 0.8, # 充电成本(元/次)
'lifespan': 2,
'max_speed': 25,
'energy_cost': 0.02, # 充电成本(元/公里)
'fixed_ride_fee': 2,
'variable_fee_rate': 0.8
# 'purchase': 2000,
# 'maintenance': 1.5,
# 'battery_replacement': 300, # 电池更换成本(元/次)
# 'battery_life': 300, # 电池寿命(公里)
# 'battery_capacity': 40, # 电池容量(km/次充电)
# 'charging_time': 4, # 充电时间(小时)
# 'charging_cost': 0.8, # 充电成本(元/次)
# 'lifespan': 2,
# 'max_speed': 25,
# 'energy_cost': 0.0375, # 充电成本(元/公里)
# 'fixed_ride_fee': 2,
# 'variable_fee_rate': 0.8
},
'moped': {
# 'purchase': 4000,
# 'maintenance': 2.5,
# 'battery_replacement': 800, # 电池更换成本(元/次)
# 'battery_life': 20000, # 电池寿命(公里)
# 'battery_capacity': 90, # 电池容量(km/次充电)
# 'charging_time': 2, # 充电时间(小时)
# 'charging_cost': 2, # 充电成本(元/次)
# 'lifespan': 3,
# 'max_speed': 25,
# 'energy_cost': 0.018, # 充电成本(元/公里)
# 'fixed_ride_fee': 2,
# 'variable_fee_rate': 0.12
'purchase': 2000,
'maintenance': 2.0,
'fuel_cost': 0.3, # 燃料成本(元/公里)
'lifespan': 4,
'max_speed': 40,
'energy_cost': 0.03, # 能源成本(元/公里)
'fixed_ride_fee': 3,
'variable_fee_rate': 1.2
}
}
# 道路承载能力参数
self.road_capacity = {
'bike_lane': {
'bike': 1.0, # 相对占用空间
'ebike': 1.2,
'moped': 1.5
},
'mixed_traffic': {
'bike': 0.5,
'ebike': 0.7,
'moped': 1.0
},
'max_flow': {
'bike_lane': 1500, # 自行车道最大流量(辆/小时)
'mixed_traffic': 3000 # 混合车道最大流量(辆/小时)
}
}
return self.user_profiles, self.vehicle_costs, self.road_capacity
def calculate_trip_cost(self, user, vehicle_type, distance):
"""计算特定用户使用特定车辆类型的出行成本"""
# 获取车辆的费用结构
vehicle = self.vehicle_costs[vehicle_type]
# 基础费用
base_cost = vehicle['fixed_ride_fee']
# 距离相关费用
distance_cost = vehicle['variable_fee_rate'] * distance
# 能源/燃料费用
energy_cost = vehicle['energy_cost'] * distance
# 如果是电动车,考虑电池更换成本
if vehicle_type == 'ebike':
battery_replacement_cost = (distance / vehicle['battery_life']) * vehicle['battery_replacement']
else:
battery_replacement_cost = 0
# 总成本
total_cost = base_cost + distance_cost + energy_cost + battery_replacement_cost
# 考虑用户收入水平对感知成本的影响
perceived_cost = total_cost * (1 + (5 - user['income_level']) * 0.1)
return perceived_cost
def calculate_trip_time(self, origin, destination, vehicle_type, road_network, congestion_factor=1.0):
"""计算出行时间,考虑距离、车辆速度和道路拥堵情况"""
# 计算欧氏距离(简化)
distance = np.sqrt((destination[0] - origin[0]) ** 2 + (destination[1] - origin[1]) ** 2)
# 获取车辆速度
speed = self.vehicle_costs[vehicle_type]['max_speed']
# 考虑道路类型对速度的影响(简化)
road_type = 'bike_lane' if distance < 5 else 'mixed_traffic'
road_efficiency = 0.9 if road_type == 'bike_lane' else 0.7
# 考虑拥堵因素
effective_speed = speed * road_efficiency / congestion_factor
# 计算出行时间(分钟)
travel_time = (distance / effective_speed) * 60
# 添加随机波动
travel_time *= np.random.uniform(0.9, 1.1)
# 如果是电动车,考虑电池耗尽需要充电的情况
if vehicle_type == 'ebike':
battery_capacity = self.vehicle_costs['ebike']['battery_capacity']
if distance > battery_capacity:
# 需要充电
charging_times = int(distance / battery_capacity)
travel_time += charging_times * self.vehicle_costs['ebike']['charging_time'] * 60
return travel_time
def calculate_congestion(self, vehicle_counts, road_network):
"""计算道路拥堵因子,基于当前车辆数量和道路容量"""
# 假设城市中有不同类型的道路,每种道路占比不同
road_types = {
'bike_lane': 0.6, # 自行车道占60%
'mixed_traffic': 0.4 # 混合车道占40%
}
# 计算每种道路类型的车辆密度
congestion_factors = {}
for road_type, proportion in road_types.items():
# 计算该类型道路上的车辆数量
road_vehicles = 0
for vehicle_type, count in vehicle_counts.items():
road_vehicles += count * road_network[road_type][vehicle_type]
# 计算车辆密度(辆/公里)
road_length = 100 * proportion # 假设城市总道路长度为100公里
density = road_vehicles / road_length
# 计算拥堵因子(基于最大流量)
max_density = road_network['max_flow'][road_type] / 30 # 假设平均车速30km/h
congestion_factor = max(1.0, density / max_density)
congestion_factors[road_type] = congestion_factor
# 计算综合拥堵因子(加权平均)
overall_congestion = sum(congestion_factors[rt] * p for rt, p in road_types.items())
return overall_congestion
def user_choice_model(self, user, vehicles, scenario='base'):
"""用户选择模型,基于效用最大化理论预测用户对不同车辆的选择概率"""
# 计算每种车辆的效用值
utilities = {}
# 检查是否有出行距离信息
has_distance = 'trip_distance' in user and not np.isnan(user['trip_distance'])
for vehicle_type, params in vehicles.items():
# 基础效用 = 偏好系数 * 场景调整
utility = user[f'{vehicle_type}_preference']
# 根据场景调整基础偏好
if scenario == 'cost_sensitive':
utility *= 1.2 if vehicle_type == 'bike' else 0.8
elif scenario == 'distance_sensitive':
utility *= 1.2 if vehicle_type in ['ebike', 'moped'] else 0.8
elif scenario == 'mixed_cost_performance':
if vehicle_type == 'bike':
utility *= 0.9 # 中等偏好
elif vehicle_type == 'ebike':
utility *= 1.1 # 较高偏好
else: # moped
utility *= 1.0 # 中等偏好
# 考虑成本因素
if has_distance:
# 计算出行成本
trip_cost = self.calculate_trip_cost(user, vehicle_type, user['trip_distance'])
# 成本带来的负效用(考虑用户成本敏感度)
utility -= user['cost_sensitivity'] * 0.05 * trip_cost
# 考虑距离因素
if has_distance:
distance = user['trip_distance']
# 不同车辆类型在不同距离上的适用性
if vehicle_type == 'bike':
# 自行车在短距离上更有优势
utility += max(0, 0.3 - 0.05 * distance)
elif vehicle_type == 'ebike':
# 电动车在中距离上更有优势
utility += max(0, -0.2 + 0.05 * distance, 0.4 - 0.03 * distance)
else: # moped
# 助力车在长距离上更有优势
utility += max(0, -0.3 + 0.06 * distance)
# 考虑时间因素(影响出行时间)
if has_distance:
# 估计出行时间(分钟)
travel_time = self.calculate_trip_time(
user['origin'], user['destination'], vehicle_type,
self.road_capacity
)
# 时间带来的负效用(考虑用户时间敏感度)
utility -= user['time_sensitivity'] * 0.01 * travel_time
# 考虑车辆可用性(供应影响)
if params > 0:
availability_factor = 1.0 - (1.0 / (1 + np.exp(-params / 100)))
utility *= availability_factor
utilities[vehicle_type] = utility
# 基于效用计算选择概率(softmax函数)
exp_utilities = np.exp(list(utilities.values()))
probabilities = exp_utilities / np.sum(exp_utilities)
return dict(zip(utilities.keys(), probabilities))
def run_simulation(self, scenario='base'):
"""运行系统仿真"""
# 创建仿真环境
env = simpy.Environment()
# 初始化车辆数量(基于成本分析的最优配置)
vehicle_fleet = self.config['total_vehicles']
# 记录系统性能指标
performance = {
'wait_time': [],
'utilization': {'bike': [], 'ebike': [], 'moped': []},
'congestion': [],
'mode_share': {'bike': [], 'ebike': [], 'moped': []},
'total_trips': 0,
'unsatisfied_demand': 0,
'daily_utilization': {'bike': [], 'ebike': [], 'moped': []},
'vehicle_km': {'bike': 0, 'ebike': 0, 'moped': 0}, # 记录每种车辆的总行驶公里数
'trip_cost': {'bike': [], 'ebike': [], 'moped': []}, # 记录每种车辆的出行成本
'choice_probabilities': [] # 记录用户选择概率的每日变化
}
# 初始车辆配置(使用成本分析的结果)
usage_data = {
'ebike': 5.0, # 假设电动车平均每次出行5公里
'moped': 8.0, # 假设助力车平均每次出行8公里
'total_trips': 1000 # 假设总出行次数
}
cost_results = self.cost_analysis(vehicle_fleet, usage_data, scenario)
# 基于成本分析结果初始化车辆配置
vehicles = {
'bike': int(cost_results['bike_count']),
'ebike': int(cost_results['ebike_count']),
'moped': int(cost_results['moped_count'])
}
print(f"场景 '{scenario}' 初始车辆配置: {vehicles}")
# 创建仿真进程
sim_process = env.process(self.system_simulation(env, vehicles, scenario, performance))
# 运行仿真直到结束
env.run(until=self.config['simulation_days'])
# 从仿真进程中获取返回值
if sim_process.triggered :
results = sim_process.value
if results:
performance.update(results)
else:
print(f"警告: 仿真进程未正常完成 (状态: {sim_process})")
return performance
# def system_simulation(self, env, vehicles, scenario, performance):
# """系统仿真模型,模拟用户使用共享车辆的过程"""
# # 模拟城市区域
# city_area = (10, 10)
#
# # 记录每日数据
# daily_utilized = {'bike': 0, 'ebike': 0, 'moped': 0}
# daily_total = 0
# daily_choice_probs = {'bike': [], 'ebike': [], 'moped': []}
#
# # 创建一个结束事件
# end_event = env.event()
#
# # 安排一个进程在仿真结束时触发事件
# def trigger_end_event():
# yield env.timeout(self.config['simulation_days'])
# end_event.succeed()
#
# env.process(trigger_end_event())
#
# # 主仿真循环
# while not end_event.triggered:
# current_day = int(env.now)
# # print('current_day',current_day)
# # exit()
# # 重置每日计数器
# if env.now == 0 or (env.now > 0 and env.now % 1 == 0):
# if env.now > 0:
# # 计算并记录每日模式分担率
# total_utilized = sum(daily_utilized.values())
# for vt in ['bike', 'ebike', 'moped']:
# if total_utilized > 0:
# share = daily_utilized[vt] / total_utilized
# else:
# share = 0
# performance['mode_share'][vt].append(share)
# performance['daily_utilization'][vt].append(daily_utilized[vt])
#
# # 记录每日选择概率
# avg_choice_probs = {vt: np.mean(daily_choice_probs[vt]) if daily_choice_probs[vt] else 0 for vt in
# ['bike', 'ebike', 'moped']}
# performance['choice_probabilities'].append(avg_choice_probs)
#
# daily_utilized = {vt: 0 for vt in daily_utilized}
# daily_total = 0
# daily_choice_probs = {'bike': [], 'ebike': [], 'moped': []}
#
# # 生成用户请求
# daily_trips = 0
# daily_unsatisfied = 0
#
# for _, user in self.user_profiles.iterrows():
# # 根据用户类型调整每日出行频率
# adjusted_frequency = max(0.1, user['trip_frequency'] / 7)
#
# # 使用泊松分布生成每日实际出行次数
# actual_trips = np.random.poisson(adjusted_frequency)
# actual_trips = max(actual_trips, 0)
#
# for _ in range(actual_trips):
# # 随机生成起点和终点
# origin = (np.random.uniform(0, city_area[0]), np.random.uniform(0, city_area[1]))
# destination = (np.random.uniform(0, city_area[0]), np.random.uniform(0, city_area[1]))
#
# # 计算出行距离
# trip_distance = np.sqrt((destination[0] - origin[0]) ** 2 + (destination[1] - origin[1]) ** 2)
#
# # 创建包含距离信息的用户数据
# user_with_trip = user.copy()
# user_with_trip['trip_distance'] = trip_distance
# user_with_trip['origin'] = origin
# user_with_trip['destination'] = destination
#
# # 用户选择车辆
# choice_probs = self.user_choice_model(user_with_trip, vehicles, scenario)
#
# # 记录选择概率
# for vt in ['bike', 'ebike', 'moped']:
# daily_choice_probs[vt].append(choice_probs[vt])
#
# vehicle_type = np.random.choice(
# list(choice_probs.keys()),
# p=list(choice_probs.values())
# )
#
# daily_trips += 1
# daily_total += 1
#
# # 计算本次出行成本
# trip_cost = self.calculate_trip_cost(user_with_trip, vehicle_type, trip_distance)
# performance['trip_cost'][vehicle_type].append(trip_cost)
#
# # 模拟车辆使用过程
# if vehicles[vehicle_type] > 0:
# # 有可用车辆
# vehicles[vehicle_type] -= 1
# daily_utilized[vehicle_type] += 1
#
# # 计算拥堵因子
# congestion = self.calculate_congestion(vehicles, self.road_capacity)
# performance['congestion'].append(congestion)
#
# # 计算出行时间
# trip_time = self.calculate_trip_time(
# origin, destination, vehicle_type, self.road_capacity, congestion
# )
#
# # 更新系统性能指标
# performance['wait_time'].append(0) # 有车可用,等待时间为0
# performance['utilization'][vehicle_type].append(1)
#
# # 记录行驶公里数
# performance['vehicle_km'][vehicle_type] += trip_distance
#
# # 车辆返回
# yield env.timeout(trip_time / 60) # 转换为小时
# vehicles[vehicle_type] += 1
# else:
# # 无车可用
# daily_unsatisfied += 1
#
# # 记录等待时间(假设用户等待一段时间后取消)
# wait_time = np.random.gamma(2, 2) # 平均4分钟
# performance['wait_time'].append(wait_time)
# performance['utilization'][vehicle_type].append(0)
#
# yield env.timeout(wait_time / 60) # 转换为小时
#
# # 记录每日统计数据
# if daily_trips > 0:
# performance['total_trips'] += daily_trips
# performance['unsatisfied_demand'] += daily_unsatisfied
#
# # 等待下一天或仿真结束
# if not end_event.triggered:
# yield env.timeout(1)
#
# # 计算最终的模式分担率
# total_utilized = sum(sum(performance['utilization'][vt]) for vt in ['bike', 'ebike', 'moped'])
# if total_utilized == 0:
# total_utilized = 1
#
# for vt in ['bike', 'ebike', 'moped']:
# share = sum(performance['utilization'][vt]) / total_utilized
# performance['mode_share'][vt].append(share)
#
# return performance
# def system_simulation(self, env, vehicles, scenario, performance):
# """系统仿真模型,模拟用户使用共享车辆的过程"""
# # 模拟城市区域
# city_area = (10, 10)
#
# # 新增:定义一天中的时间段及其权重(可根据实际情况调整)
# time_periods = {
# 'morning_peak': (6, 10, 1.2), # 早高峰:6-10点,权重1.2
# 'midday': (10, 16, 0.9), # 中午:10-16点,权重0.9
# 'evening_peak': (16, 19, 1.3), # 晚高峰:16-19点,权重1.3
# 'night': (19, 24, 1.0), # 夜间:19-24点,权重1.0
# 'early_morning': (0, 6, 0.7) # 凌晨:0-6点,权重0.7
# }
#
# # 记录每日数据
# daily_utilized = {'bike': 0, 'ebike': 0, 'moped': 0}
# daily_total = 0
# daily_choice_probs = {'bike': [], 'ebike': [], 'moped': []}
#
# # 新增:记录按时间段和用户类型的选择概率
# period_choice_probs = {period: {'bike': [], 'ebike': [], 'moped': []} for period in time_periods}
# user_type_choice_probs = {age_group: {'bike': [], 'ebike': [], 'moped': []}
# for age_group in self.user_profiles['age_group'].unique()}
#
# # 新增:记录实际选择结果与预测概率的对比
# actual_choices = {'bike': 0, 'ebike': 0, 'moped': 0}
# predicted_choices = {'bike': 0, 'ebike': 0, 'moped': 0}
#
# # 创建一个结束事件
# end_event = env.event()
#
# # 安排一个进程在仿真结束时触发事件
# def trigger_end_event():
# yield env.timeout(self.config['simulation_days'])
# end_event.succeed()
#
# env.process(trigger_end_event())
#
# # 主仿真循环
# while not end_event.triggered:
# current_day = int(env.now)
# current_time = env.now % 24 # 当前时间(0-24小时)
#
# # 确定当前时间段
# current_period = None
# for period, (start, end, _) in time_periods.items():
# if start <= current_time < end:
# current_period = period
# break
#
# # 重置每日计数器
# if env.now == 0 or (env.now > 0 and env.now % 1 == 0):
# print('env.now',env.now)
# if env.now > 0:
# # 计算并记录每日模式分担率
# total_utilized = sum(daily_utilized.values())
# for vt in ['bike', 'ebike', 'moped']:
# if total_utilized > 0:
# share = daily_utilized[vt] / total_utilized
# else:
# share = 0
# performance['mode_share'][vt].append(share)
# performance['daily_utilization'][vt].append(daily_utilized[vt])
#
# # 记录每日选择概率
# avg_choice_probs = {vt: np.mean(daily_choice_probs[vt]) if daily_choice_probs[vt] else 0 for vt in
# ['bike', 'ebike', 'moped']}
# performance['choice_probabilities'].append(avg_choice_probs)
#
# # 新增:记录按时间段的平均选择概率
# for period in time_periods:
# for vt in ['bike', 'ebike', 'moped']:
# if period_choice_probs[period][vt]:
# avg_prob = np.mean(period_choice_probs[period][vt])
# performance[f'period_{period}_choice_prob'][vt].append(avg_prob)
#
# # 新增:计算预测与实际选择的差异
# total_predicted = sum(predicted_choices.values())
# total_actual = sum(actual_choices.values())
#
# if total_predicted > 0 and total_actual > 0:
# for vt in ['bike', 'ebike', 'moped']:
# pred_share = predicted_choices[vt] / total_predicted
# actual_share = actual_choices[vt] / total_actual
# performance['pred_actual_diff'][vt].append(actual_share - pred_share)
#
# # 重置计数器
# daily_utilized = {vt: 0 for vt in daily_utilized}
# daily_total = 0
# daily_choice_probs = {'bike': [], 'ebike': [], 'moped': []}
#
# # 重置时间段选择概率记录
# for period in time_periods:
# period_choice_probs[period] = {'bike': [], 'ebike': [], 'moped': []}
#
# # 重置预测与实际选择计数器
# actual_choices = {'bike': 0, 'ebike': 0, 'moped': 0}
# predicted_choices = {'bike': 0, 'ebike': 0, 'moped': 0}
#
# # 生成用户请求
# daily_trips = 0
# daily_unsatisfied = 0
#
# for _, user in self.user_profiles.iterrows():
# age_group = user['age_group']
#
# # 根据用户类型和时间段调整每日出行频率
# period_weight = time_periods[current_period][2] if current_period else 1.0
# adjusted_frequency = max(0.1, user['trip_frequency'] / 7 * period_weight)
#
# # 使用泊松分布生成每日实际出行次数
# actual_trips = np.random.poisson(adjusted_frequency)
# actual_trips = max(actual_trips, 0)
#
# for _ in range(actual_trips):
# # 随机生成起点和终点
# origin = (np.random.uniform(0, city_area[0]), np.random.uniform(0, city_area[1]))
# destination = (np.random.uniform(0, city_area[0]), np.random.uniform(0, city_area[1]))
#
# # 计算出行距离
# trip_distance = np.sqrt((destination[0] - origin[0]) ** 2 + (destination[1] - origin[1]) ** 2)
#
# # 创建包含距离信息的用户数据
# user_with_trip = user.copy()
# user_with_trip['trip_distance'] = trip_distance
# user_with_trip['origin'] = origin
# user_with_trip['destination'] = destination
# user_with_trip['time_period'] = current_period # 新增:添加时间段信息
#
# # 用户选择车辆(使用实时车辆数量)
# choice_probs = self.user_choice_model(user_with_trip, vehicles, scenario)
#
# # 记录预测的选择次数
# for vt in ['bike', 'ebike', 'moped']:
# predicted_choices[vt] += choice_probs[vt]
#
# # 记录选择概率
# for vt in ['bike', 'ebike', 'moped']:
# daily_choice_probs[vt].append(choice_probs[vt])
#
# # 按时间段记录
# if current_period:
# period_choice_probs[current_period][vt].append(choice_probs[vt])
#
# # 按用户类型记录
# user_type_choice_probs[age_group][vt].append(choice_probs[vt])
#
# # 实际选择车辆
# vehicle_type = np.random.choice(
# list(choice_probs.keys()),
# p=list(choice_probs.values())
# )
#
# # 记录实际选择
# actual_choices[vehicle_type] += 1
#
# daily_trips += 1
# daily_total += 1
#
# # 计算本次出行成本
# trip_cost = self.calculate_trip_cost(user_with_trip, vehicle_type, trip_distance)
# performance['trip_cost'][vehicle_type].append(trip_cost)
#
# # 模拟车辆使用过程
# if vehicles[vehicle_type] > 0:
# # 有可用车辆
# vehicles[vehicle_type] -= 1
# daily_utilized[vehicle_type] += 1
#
# # 计算拥堵因子(使用实时车辆数量)
# congestion = self.calculate_congestion(vehicles, self.road_capacity)
# performance['congestion'].append(congestion)
#
# # 计算出行时间
# trip_time = self.calculate_trip_time(
# origin, destination, vehicle_type, self.road_capacity, congestion
# )
#
# # 更新系统性能指标
# performance['wait_time'].append(0) # 有车可用,等待时间为0
# performance['utilization'][vehicle_type].append(1)
#
# # 记录行驶公里数
# performance['vehicle_km'][vehicle_type] += trip_distance
#
# # 车辆返回
# yield env.timeout(trip_time / 60) # 转换为小时
# vehicles[vehicle_type] += 1
# else:
# # 无车可用
# daily_unsatisfied += 1
#
# # 记录等待时间(假设用户等待一段时间后取消)
# wait_time = np.random.gamma(2, 2) # 平均4分钟
# performance['wait_time'].append(wait_time)
# performance['utilization'][vehicle_type].append(0)
#
# yield env.timeout(wait_time / 60) # 转换为小时
#
# # 记录每日统计数据
# if daily_trips > 0:
# performance['total_trips'] += daily_trips
# performance['unsatisfied_demand'] += daily_unsatisfied
#
# # 等待下一天或仿真结束
# if not end_event.triggered:
# yield env.timeout(1)
#
# # 计算最终的模式分担率
# total_utilized = sum(sum(performance['utilization'][vt]) for vt in ['bike', 'ebike', 'moped'])
# if total_utilized == 0:
# total_utilized = 1
#
# for vt in ['bike', 'ebike', 'moped']:
# share = sum(performance['utilization'][vt]) / total_utilized
# performance['mode_share'][vt].append(share)
#
# return performance
def system_simulation(self, env, vehicles, scenario, performance):
"""系统仿真模型,模拟用户使用共享车辆的过程"""
# 模拟城市区域
city_area = (10, 10)
# 定义一天中的时间段及其权重
time_periods = {
'morning_peak': (6, 10, 1.2), # 早高峰:6-10点,权重1.2
'midday': (10, 16, 0.9), # 中午:10-16点,权重0.9
'evening_peak': (16, 19, 1.3), # 晚高峰:16-19点,权重1.3
'night': (19, 24, 1.0), # 夜间:19-24点,权重1.0
'early_morning': (0, 6, 0.7) # 凌晨:0-6点,权重0.7
}
# 初始化性能数据结构中的时间段选择概率键
for period in time_periods:
if f'period_{period}_choice_prob' not in performance:
performance[f'period_{period}_choice_prob'] = {
'bike': [], 'ebike': [], 'moped': []
}
# 初始化预测与实际选择差异键
if 'pred_actual_diff' not in performance:
performance['pred_actual_diff'] = {
'bike': [], 'ebike': [], 'moped': []
}
# 记录每日数据
daily_utilized = {'bike': 0, 'ebike': 0, 'moped': 0}
daily_total = 0
daily_choice_probs = {'bike': [], 'ebike': [], 'moped': []}
# 按时间段和用户类型的选择概率
period_choice_probs = {period: {'bike': [], 'ebike': [], 'moped': []} for period in time_periods}
user_type_choice_probs = {age_group: {'bike': [], 'ebike': [], 'moped': []}
for age_group in self.user_profiles['age_group'].unique()}
# 记录实际选择结果与预测概率的对比
actual_choices = {'bike': 0, 'ebike': 0, 'moped': 0}
predicted_choices = {'bike': 0, 'ebike': 0, 'moped': 0}
# 创建一个结束事件
end_event = env.event()
# 安排一个进程在仿真结束时触发事件
env.process(self._trigger_end_event(env, end_event, self.config['simulation_days']))
# 存储所有用户请求进程的引用
user_processes = []
# 主仿真循环 - 每天生成新的用户请求
current_day = 0
while not end_event.triggered:
# 重置每日计数器
if env.now >= current_day:
if current_day > 0:
# 计算并记录每日模式分担率
self._record_daily_statistics(env, daily_utilized, daily_choice_probs, performance,
period_choice_probs, actual_choices, predicted_choices, time_periods)
daily_utilized = {vt: 0 for vt in daily_utilized}
daily_total = 0
daily_choice_probs = {'bike': [], 'ebike': [], 'moped': []}
for period in time_periods:
period_choice_probs[period] = {'bike': [], 'ebike': [], 'moped': []}
actual_choices = {'bike': 0, 'ebike': 0, 'moped': 0}
predicted_choices = {'bike': 0, 'ebike': 0, 'moped': 0}
current_day += 1
# 生成当日用户请求
daily_trips, daily_unsatisfied = self._generate_daily_user_requests(
env, vehicles, scenario, performance, current_day, time_periods,
daily_utilized, daily_choice_probs, period_choice_probs,
user_type_choice_probs, actual_choices, predicted_choices, city_area
)
# 记录每日统计数据
if daily_trips > 0:
performance['total_trips'] += daily_trips
performance['unsatisfied_demand'] += daily_unsatisfied
# 等待下一天
if not end_event.triggered:
yield env.timeout(1)
# 等待所有用户进程完成
for process in user_processes:
if not process.triggered:
yield process
# 计算最终的模式分担率
self._calculate_final_mode_share(performance)
return performance
def _trigger_end_event(self, env, end_event, simulation_days):
"""触发仿真结束事件"""
yield env.timeout(simulation_days)
end_event.succeed()
def _record_daily_statistics(self, env, daily_utilized, daily_choice_probs, performance,
period_choice_probs, actual_choices, predicted_choices, time_periods):
"""记录每日统计数据"""
total_utilized = sum(daily_utilized.values())
for vt in ['bike', 'ebike', 'moped']:
if total_utilized > 0:
share = daily_utilized[vt] / total_utilized
else:
share = 0
performance['mode_share'][vt].append(share)
performance['daily_utilization'][vt].append(daily_utilized[vt])
# 记录每日选择概率
avg_choice_probs = {vt: np.mean(daily_choice_probs[vt]) if daily_choice_probs[vt] else 0 for vt in
['bike', 'ebike', 'moped']}
performance['choice_probabilities'].append(avg_choice_probs)
# 记录按时间段的平均选择概率
for period in time_periods:
for vt in ['bike', 'ebike', 'moped']:
if period_choice_probs[period][vt]:
avg_prob = np.mean(period_choice_probs[period][vt])
performance[f'period_{period}_choice_prob'][vt].append(avg_prob)
# 计算预测与实际选择的差异
total_predicted = sum(predicted_choices.values())
total_actual = sum(actual_choices.values())
if total_predicted > 0 and total_actual > 0:
for vt in ['bike', 'ebike', 'moped']:
pred_share = predicted_choices[vt] / total_predicted
actual_share = actual_choices[vt] / total_actual
performance['pred_actual_diff'][vt].append(actual_share - pred_share)
def _generate_daily_user_requests(self, env, vehicles, scenario, performance, current_day, time_periods,
daily_utilized, daily_choice_probs, period_choice_probs,
user_type_choice_probs, actual_choices, predicted_choices, city_area):
"""生成每日用户请求并创建处理进程"""
daily_trips = 0
daily_unsatisfied = 0
for _, user in self.user_profiles.iterrows():
age_group = user['age_group']
# 生成用户请求时间点(在一天内均匀分布)
for _ in range(self._calculate_daily_trips(user, time_periods)):
# 随机选择一天中的时间点
trip_time = np.random.uniform(0, 1) # 0-1天之间
# 确定时间段
current_time = (current_day + trip_time) % 24
current_period = self._determine_time_period(current_time, time_periods)
# 安排用户请求处理进程
env.process(self._process_user_request(
env, user, age_group, current_period, vehicles, scenario, performance,
city_area, daily_utilized, daily_choice_probs, period_choice_probs,
user_type_choice_probs, actual_choices, predicted_choices,
trip_time, time_periods
))
return daily_trips, daily_unsatisfied
def _calculate_daily_trips(self, user, time_periods):
"""计算用户每日出行次数"""
# 随机选择一个时间段作为主要出行时段
period_weights = [weight for _, _, weight in time_periods.values()]
total_weight = sum(period_weights)
normalized_weights = [w / total_weight for w in period_weights]
# 随机选择一个时间段
selected_period_idx = np.random.choice(len(time_periods), p=normalized_weights)
selected_period = list(time_periods.keys())[selected_period_idx]
period_weight = time_periods[selected_period][2]
# 根据用户类型和时间段调整每日出行频率
adjusted_frequency = max(0.1, user['trip_frequency'] / 7 * period_weight)
# 使用泊松分布生成每日实际出行次数
actual_trips = np.random.poisson(adjusted_frequency)
return max(actual_trips, 0)
def _determine_time_period(self, current_time, time_periods):
"""确定当前时间所属的时间段"""
for period, (start, end, _) in time_periods.items():
if start <= current_time < end:
return period
return 'night' # 默认夜间
def _process_user_request(self, env, user, age_group, current_period, vehicles, scenario, performance,
city_area, daily_utilized, daily_choice_probs, period_choice_probs,
user_type_choice_probs, actual_choices, predicted_choices, trip_time, time_periods):
"""处理单个用户请求"""
# 等待到请求时间
yield env.timeout(trip_time)
# 随机生成起点和终点
origin = (np.random.uniform(0, city_area[0]), np.random.uniform(0, city_area[1]))
destination = (np.random.uniform(0, city_area[0]), np.random.uniform(0, city_area[1]))
# 计算出行距离
trip_distance = np.sqrt((destination[0] - origin[0]) ** 2 + (destination[1] - origin[1]) ** 2)
# 创建包含距离信息的用户数据
user_with_trip = user.copy()
user_with_trip['trip_distance'] = trip_distance
user_with_trip['origin'] = origin
user_with_trip['destination'] = destination
user_with_trip['time_period'] = current_period
# 用户选择车辆(使用实时车辆数量)
choice_probs = self.user_choice_model(user_with_trip, vehicles, scenario)
# 记录预测的选择次数
for vt in ['bike', 'ebike', 'moped']:
predicted_choices[vt] += choice_probs[vt]
# 记录选择概率
for vt in ['bike', 'ebike', 'moped']:
daily_choice_probs[vt].append(choice_probs[vt])
if current_period:
period_choice_probs[current_period][vt].append(choice_probs[vt])
user_type_choice_probs[age_group][vt].append(choice_probs[vt])
# 实际选择车辆
vehicle_type = np.random.choice(
list(choice_probs.keys()),
p=list(choice_probs.values())
)
# 记录实际选择
actual_choices[vehicle_type] += 1
# 模拟车辆使用过程
if vehicles[vehicle_type] > 0:
# 有可用车辆
vehicles[vehicle_type] -= 1
daily_utilized[vehicle_type] += 1
# 计算拥堵因子(使用实时车辆数量)
congestion = self.calculate_congestion(vehicles, self.road_capacity)
performance['congestion'].append(congestion)
# 计算出行时间
trip_time = self.calculate_trip_time(
origin, destination, vehicle_type, self.road_capacity, congestion
)
# 更新系统性能指标
performance['wait_time'].append(0) # 有车可用,等待时间为0
performance['utilization'][vehicle_type].append(1)
# 记录行驶公里数
performance['vehicle_km'][vehicle_type] += trip_distance
# 车辆返回
yield env.timeout(trip_time / 60) # 转换为小时
vehicles[vehicle_type] += 1
else:
# 无车可用
# 记录等待时间(假设用户等待一段时间后取消)
wait_time = np.random.gamma(2, 2) # 平均4分钟
performance['wait_time'].append(wait_time)
performance['utilization'][vehicle_type].append(0)
yield env.timeout(wait_time / 60) # 转换为小时
def _calculate_final_mode_share(self, performance):
"""计算最终的模式分担率"""
total_utilized = sum(sum(performance['utilization'][vt]) for vt in ['bike', 'ebike', 'moped'])
if total_utilized == 0:
total_utilized = 1
for vt in ['bike', 'ebike', 'moped']:
share = sum(performance['utilization'][vt]) / total_utilized
performance['mode_share'][vt].append(share)
def cost_analysis(self, total_vehicles, usage_data, scenario='base'):
"""成本分析模型,计算不同车辆配置的总成本"""
# 初始化问题
prob = LpProblem("Fleet_Cost_Optimization", LpMinimize)
# 定义决策变量:每种车辆的数量
bike_count = LpVariable("bike_count", lowBound=0, cat='Integer')
ebike_count = LpVariable("ebike_count", lowBound=0, cat='Integer')
moped_count = LpVariable("moped_count", lowBound=0, cat='Integer')
# 根据不同场景调整目标函数和约束条件
if scenario == 'cost_sensitive':
# 在成本敏感场景下,更注重降低运营成本
weight_purchase = 0.7
weight_operation = 1.3
# 运营成本权重
# 约束条件:自行车比例至少为30%
prob += bike_count >= total_vehicles * 1
# prob += ebike_count >= total_vehicles * 0.4
# prob += moped_count >= total_vehicles * 0.2
elif scenario == 'distance_sensitive':
# 在距离敏感场景下,更注重车辆性能和覆盖范围
weight_purchase = 0.9
weight_operation = 1.1
# 约束条件:电动车比例至少为40%,助力车比例至少为20%
prob += bike_count >= total_vehicles * 0.4
prob += ebike_count >= total_vehicles * 0.4
prob += moped_count >= total_vehicles * 0.2
elif scenario == 'mixed_cost_performance':
# 综合考虑成本和性能的场景
weight_purchase = 0.8
weight_operation = 1.2
# 约束条件:电动车比例至少为30%
prob += bike_count >= total_vehicles * 0.6
prob += ebike_count >= total_vehicles * 0.3
prob += moped_count >= total_vehicles * 0.1
else: # base scenario
# 基础场景
weight_purchase = 1.0
weight_operation = 1.0
# 基础场景下的默认配置
prob += bike_count >= total_vehicles * 0.7
prob += ebike_count >= total_vehicles * 0.2
prob += moped_count >= total_vehicles * 0.1
# 目标函数:最小化总成本(考虑购置成本和运营成本)
total_cost = (
# 购置成本(年化)
bike_count * self.vehicle_costs['bike']['purchase'] / (self.vehicle_costs['bike']['lifespan'] * 365) * weight_purchase +
ebike_count * self.vehicle_costs['ebike']['purchase'] / (self.vehicle_costs['ebike']['lifespan'] * 365) * weight_purchase +
moped_count * self.vehicle_costs['moped']['purchase'] / (self.vehicle_costs['moped']['lifespan'] * 365) * weight_purchase +
# 日常维护成本
bike_count * self.vehicle_costs['bike']['maintenance'] * weight_operation +
ebike_count * self.vehicle_costs['ebike']['maintenance'] * weight_operation +
moped_count * self.vehicle_costs['moped']['maintenance'] * weight_operation +
# 能源/燃料成本
ebike_count * usage_data['ebike'] * self.vehicle_costs['ebike']['energy_cost'] * weight_operation +
moped_count * usage_data['moped'] * self.vehicle_costs['moped']['energy_cost'] * weight_operation +
# 电动车电池更换成本
ebike_count * (usage_data['ebike'] / self.vehicle_costs['ebike']['battery_life']) * self.vehicle_costs['ebike']['battery_replacement'] * weight_operation
)
prob += total_cost
# 总车辆数约束
prob += bike_count + ebike_count + moped_count <= total_vehicles
# 求解问题
prob.solve()
return {
'bike_count': bike_count.value(),
'ebike_count': ebike_count.value(),
'moped_count': moped_count.value(),
'total_cost': prob.objective.value(),
'cost_per_trip': prob.objective.value() / max(usage_data['total_trips'], 1) # 确保不为零
}
def visualize_results(self, scenario_results, scenario_name):
"""可视化仿真结果"""
# 创建一个画布
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 1. 绘制模式分担率
ax1 = axes[0, 0]
for mode, shares in scenario_results['mode_share'].items():
ax1.plot(shares, label=mode)
ax1.set_title(f'Trend of pattern sharing rate change ({scenario_name})')
# ax1.set_title(f'每日模式分担率 ({scenario_name})')
ax1.set_xlabel('day')
ax1.set_ylabel('proportion')
ax1.legend()
ax1.grid(True)
# 2. 绘制用户选择概率
ax2 = axes[0, 1]
if scenario_results['choice_probabilities']:
days = list(range(len(scenario_results['choice_probabilities'])))
bike_probs = [day['bike'] for day in scenario_results['choice_probabilities']]
ebike_probs = [day['ebike'] for day in scenario_results['choice_probabilities']]
moped_probs = [day['moped'] for day in scenario_results['choice_probabilities']]
ax2.plot(days, bike_probs, label='bike')
ax2.plot(days, ebike_probs, label='ebike')
ax2.plot(days, moped_probs, label='moped')
ax2.set_title(f'User selection probability change trend ({scenario_name})')
ax2.set_xlabel('day')
ax2.set_ylabel('Selection Probability')
ax2.legend()
ax2.grid(True)
else:
ax2.set_title(f'User selection probability change trend ({scenario_name}) - noDATA')
ax2.grid(True)
# 3. 绘制平均出行成本
ax3 = axes[1, 0]
avg_costs = {}
for mode in scenario_results['trip_cost']:
if scenario_results['trip_cost'][mode]:
avg_costs[mode] = np.mean(scenario_results['trip_cost'][mode])
if avg_costs:
ax3.bar(avg_costs.keys(), avg_costs.values())
ax3.set_title(f'Average travel cost ({scenario_name})')
for i, v in enumerate(avg_costs.values()):
ax3.text(i, v + 0.1, f'{v:.2f}RMB', ha='center')
else:
ax3.set_title(f'Average travel cost ({scenario_name}) - NOdata')
ax3.set_xlabel('vehicle type')
ax3.set_ylabel('cost /RMB')
ax3.grid(True, axis='y')
# 4. 绘制系统性能指标
ax4 = axes[1, 1]
zhibiao = ['TNOT', 'NOUN', 'AWT', 'ACF']
# zhibiao = ['Total number of trips', 'Number of unmet needs', 'Average waiting time (minutes)', 'Average congestion factor']
# 指标 = ['总出行次数', '未满足需求次数', '平均等待时间(分钟)', '平均拥堵因子']
values = [
scenario_results['total_trips'],
scenario_results['unsatisfied_demand'],
np.mean(scenario_results['wait_time']) if scenario_results['wait_time'] else 0,
np.mean(scenario_results['congestion']) if scenario_results['congestion'] else 0
]
ax4.bar(zhibiao, values)
ax4.set_title(f'System performance indicators ({scenario_name})')
for i, v in enumerate(values):
ax4.text(i, v + max(values) * 0.02, f'{v:.2f}', ha='center')
ax4.set_ylabel('value')
ax4.grid(True, axis='y')
plt.tight_layout()
plt.savefig(f'simulation_results_{scenario_name}.png', dpi=300)
plt.close() # 关闭图形,避免内存泄漏
def compare_scenarios(self, results):
"""比较不同场景的结果"""
# 创建一个画布
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 1. 比较总成本
ax1 = axes[0, 0]
scenarios = list(results.keys())
total_costs = [results[scenario]['cost']['total_cost'] for scenario in scenarios]
ax1.bar(scenarios, total_costs)
ax1.set_title('不同场景总成本比较')
for i, v in enumerate(total_costs):
ax1.text(i, v + 10, f'{v:.2f}元', ha='center')
ax1.set_xlabel('场景')
ax1.set_ylabel('总成本 (元)')
ax1.grid(True, axis='y')
# 2. 比较车辆配置
ax2 = axes[0, 1]
bike_counts = [results[scenario]['cost']['bike_count'] for scenario in scenarios]
ebike_counts = [results[scenario]['cost']['ebike_count'] for scenario in scenarios]
moped_counts = [results[scenario]['cost']['moped_count'] for scenario in scenarios]
x = np.arange(len(scenarios))
width = 0.25
ax2.bar(x - width, bike_counts, width, label='自行车')
ax2.bar(x, ebike_counts, width, label='电动车')
ax2.bar(x + width, moped_counts, width, label='助力车')
ax2.set_title('不同场景车辆配置比较')
ax2.set_xlabel('场景')
ax2.set_ylabel('车辆数量')
ax2.set_xticks(x)
ax2.set_xticklabels(scenarios)
ax2.legend()
ax2.grid(True, axis='y')
# 3. 比较未满足需求比例
ax3 = axes[1, 0]
unsatisfied_ratios = [
results[scenario]['performance']['unsatisfied_demand'] / max(results[scenario]['performance']['total_trips'], 1) * 100
for scenario in scenarios
]
ax3.bar(scenarios, unsatisfied_ratios)
ax3.set_title('不同场景未满足需求比例比较')
for i, v in enumerate(unsatisfied_ratios):
ax3.text(i, v + 0.1, f'{v:.2f}%', ha='center')
ax3.set_xlabel('场景')
ax3.set_ylabel('未满足需求比例 (%)')
ax3.grid(True, axis='y')
# 4. 比较平均出行成本
ax4 = axes[1, 1]
avg_costs = []
for scenario in scenarios:
total_cost = 0
total_trips = 0
for mode in results[scenario]['performance']['trip_cost']:
if results[scenario]['performance']['trip_cost'][mode]:
total_cost += sum(results[scenario]['performance']['trip_cost'][mode])
total_trips += len(results[scenario]['performance']['trip_cost'][mode])
if total_trips > 0:
avg_costs.append(total_cost / total_trips)
else:
avg_costs.append(0)
ax4.bar(scenarios, avg_costs)
ax4.set_title('不同场景平均出行成本比较')
for i, v in enumerate(avg_costs):
ax4.text(i, v + 0.05, f'{v:.2f}元', ha='center')
ax4.set_xlabel('场景')
ax4.set_ylabel('平均出行成本 (元)')
ax4.grid(True, axis='y')
plt.tight_layout()
plt.savefig('scenario_comparison.png', dpi=300)
plt.close()
def evaluate_scenarios(self):
"""评估不同场景"""
self.prepare_data()
all_results = {}
for scenario in self.config['scenarios']:
print(f"\n正在运行场景: {scenario}")
results = self.run_simulation(scenario)
# 成本分析(使用仿真得到的实际行驶数据)
usage_data = {
'ebike': results['vehicle_km']['ebike'] / max(results['total_trips'], 1), # 每单平均行驶公里数
'moped': results['vehicle_km']['moped'] / max(results['total_trips'], 1),
'total_trips': max(results['total_trips'], 1) # 确保不为零
}
cost_results = self.cost_analysis(self.config['total_vehicles'], usage_data, scenario)
# 整合结果
scenario_results = {
'performance': results,
'cost': cost_results
}
all_results[scenario] = scenario_results
# exit()
# 可视化该场景的结果
self.visualize_results(results, scenario)
# 比较不同场景的结果
self.compare_scenarios(all_results)
return all_results
def main():
"""主函数,运行评估系统"""
# 创建评估系统实例
config = {
'total_vehicles': 1000,
'simulation_days': 30,
'scenarios': ['base', 'cost_sensitive', 'distance_sensitive', 'mixed_cost_performance']
}
evaluator = SharedVehicleEvaluationSystem(config)
# 准备数据
user_profiles, vehicle_costs, road_capacity = evaluator.prepare_data()
print("用户群体参数:")
print(user_profiles)
print("\n车辆成本参数:")
for vehicle_type, params in vehicle_costs.items():
print(f"{vehicle_type}: {params}")
# 运行场景评估
scenario_results = evaluator.evaluate_scenarios()
# 比较不同场景的结果
print("\n场景比较结果:")
for scenario, results in scenario_results.items():
print(f"\n场景: {scenario}")
print(f"总成本: {results['cost']['total_cost']:.2f}元")
print(f"每单成本: {results['cost']['cost_per_trip']:.2f}元")
print(f"车辆配置: 自行车={results['cost']['bike_count']:.0f}, 电动车={results['cost']['ebike_count']:.0f}, 助力车={results['cost']['moped_count']:.0f}")
print(f"总出行次数: {results['performance']['total_trips']}")
print(f"未满足需求比例: {results['performance']['unsatisfied_demand'] / max(results['performance']['total_trips'], 1) * 100:.2f}%")
print(f"平均等待时间: {np.mean(results['performance']['wait_time']):.2f}分钟" if results['performance']['wait_time'] else "平均等待时间: 无数据")
# print(f"模式分担率: 自行车={results['performance']['mode_share']['bike'][-1]:.2%}, 电动车={results['performance']['mode_share']['ebike'][-1]:.2%}, 助力车={results['performance']['mode_share']['moped'][-1]:.2%}")
# 打印用户选择概率
if results['performance']['choice_probabilities']:
final_choice_probs = results['performance']['choice_probabilities'][-1]
print(f"用户选择概率: 自行车={final_choice_probs['bike']:.2%}, 电动车={final_choice_probs['ebike']:.2%}, 助力车={final_choice_probs['moped']:.2%}")
# 打印平均出行成本
avg_costs = {}
for mode in results['performance']['trip_cost']:
if results['performance']['trip_cost'][mode]:
avg_costs[mode] = np.mean(results['performance']['trip_cost'][mode])
if avg_costs:
print("平均出行成本:")
for mode, cost in avg_costs.items():
print(f" {mode}: {cost:.2f}元")
# 分析不同场景下的系统性能变化
print("\n系统性能变化分析:")
# 基础场景作为参考
base_scenario = 'base'
if base_scenario in scenario_results:
base_results = scenario_results[base_scenario]
for scenario, results in scenario_results.items():
if scenario == base_scenario:
continue
print(f"\n与基础场景相比 - {scenario}:")
# 成本变化
cost_diff = results['cost']['total_cost'] - base_results['cost']['total_cost']
cost_percent_diff = cost_diff / base_results['cost']['total_cost'] * 100
print(f"总成本变化: {cost_diff:.2f}元 ({cost_percent_diff:.2f}%)")
# 车辆配置变化
for vehicle_type in ['bike', 'ebike', 'moped']:
count_diff = results['cost'][f'{vehicle_type}_count'] - base_results['cost'][f'{vehicle_type}_count']
percent_diff = count_diff / base_results['cost'][f'{vehicle_type}_count'] * 100 if base_results['cost'][f'{vehicle_type}_count'] > 0 else 0
print(f"{vehicle_type}配置变化: {count_diff:.0f}辆 ({percent_diff:.2f}%)")
# 未满足需求变化
demand_diff = (results['performance']['unsatisfied_demand'] / max(results['performance']['total_trips'], 1) -
base_results['performance']['unsatisfied_demand'] / max(base_results['performance']['total_trips'], 1)) * 100
print(f"未满足需求比例变化: {demand_diff:.2f}%")
# 平均等待时间变化
if results['performance']['wait_time'] and base_results['performance']['wait_time']:
wait_time_diff = np.mean(results['performance']['wait_time']) - np.mean(base_results['performance']['wait_time'])
print(f"平均等待时间变化: {wait_time_diff:.2f}分钟")
# 模式分担率变化
for vehicle_type in ['bike', 'ebike', 'moped']:
# print(results['performance']['mode_share'][vehicle_type])
share_diff = (results['performance']['mode_share'][vehicle_type][-1] - base_results['performance']['mode_share'][vehicle_type][-1]) * 100
print(f"{vehicle_type}模式分担率变化: {share_diff:.2f}%")
# 用户选择概率变化
if results['performance']['choice_probabilities'] and base_results['performance']['choice_probabilities']:
for vehicle_type in ['bike', 'ebike', 'moped']:
prob_diff = (results['performance']['choice_probabilities'][-1][vehicle_type] -
base_results['performance']['choice_probabilities'][-1][vehicle_type]) * 100
print(f"{vehicle_type}选择概率变化: {prob_diff:.2f}%")
if __name__ == "__main__":
main()
帮我画一下这个代码的结构图或流程图