
本文介绍通过自定义目标函数(而非约束)的方式,在 jsprit 路径优化中对乘客在车内的额外停留时间施加线性软惩罚,从而鼓励更紧凑的接送顺序(如先接远途乘客、后接近途乘客),提升乘客体验与调度合理性。
本文介绍通过自定义目标函数(而非约束)的方式,在 jsprit 路径优化中对乘客在车内的额外停留时间施加线性软惩罚,从而鼓励更紧凑的接送顺序(如先接远途乘客、后接近途乘客),提升乘客体验与调度合理性。
在 JSprit 中实现“乘客车内时间最小化”这一业务目标时,不推荐使用自定义硬/软约束(如继承 HardActivityConstraint 或 SoftActivityConstraint),因为该目标本质上是全局路径质量度量,而非单点活动可行性判断。更简洁、高效且符合 JSprit 设计哲学的做法是:重写目标函数(Objective Function),将每位乘客在车内的累计滞留时间(以秒为单位)转化为可量化的成本项,并纳入总成本计算。
核心思想是:每当车辆从一个活动(如 pickup 或 delivery)移动到下一个活动时,当前车上所有乘客都会经历这段行驶时间;因此,该段行程产生的“乘客-秒”(passenger-seconds)成本 = 当前乘客数 × 行驶时长。该成本乘以单位惩罚系数(如 0.001 /秒/人),即可平滑地引导算法偏好更短的车内总暴露时间。
以下是一个完整、可直接集成的目标函数实现示例:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
public double getCosts(VehicleRoutingProblemSolution solution) {
double costPerPassengerSecond = 0.001; // 可调参数:每乘客每秒的隐含成本(需根据固定成本量级校准)
double totalCosts = 0.0;
for (VehicleRoute route : solution.getRoutes()) {
// 加入车辆固定使用成本
totalCosts += route.getVehicle().getType().getVehicleCostParams().fix;
TourActivity prevAct = route.getStart();
int passengersInVehicle = 0;
// 遍历所有服务活动(pickup/delivery)
for (TourActivity act : route.getActivities()) {
// 累加路段运输成本(距离/时间基础成本)
double transportCost = vrp.getTransportCosts()
.getTransportCost(prevAct.getLocation(), act.getLocation(),
prevAct.getEndTime(), route.getDriver(), route.getVehicle());
totalCosts += transportCost;
// 【关键】累加乘客时间惩罚:当前乘客数 × 本段行驶时长 × 单位惩罚
double travelTime = vrp.getTransportCosts()
.getTransportTime(prevAct.getLocation(), act.getLocation(),
prevAct.getEndTime(), route.getDriver(), route.getVehicle());
totalCosts += costPerPassengerSecond * passengersInVehicle * travelTime;
// 更新乘客数量:pickup +1,delivery -1(假设 size[0] 表示乘客数变化)
passengersInVehicle += act.getSize().get(0);
prevAct = act;
}
// 加入从最后一项活动到路线终点的返程成本(含时间惩罚,此时车上已无乘客,故不加 passenger-time 成本)
totalCosts += vrp.getTransportCosts()
.getTransportCost(prevAct.getLocation(), route.getEnd().getLocation(),
prevAct.getEndTime(), route.getDriver(), route.getVehicle());
}
return totalCosts;
}
? 注意事项与最佳实践:
- ✅ 参数校准至关重要:
costPerPassengerSecond应显著小于车辆固定成本(fix)和单位时间运输成本(perTransportTimeUnit),否则算法会过度牺牲车辆利用率来压缩乘客时间。建议初始设为0.0005–0.002,再根据实际解的质量微调。 - ✅ 乘客计数需准确建模:确保
act.getSize().get(0)正确反映每次 pickup/delivery 的人数增减(例如:pickup返回+1,delivery返回-1)。若支持多人同单,需统一约定 size 维度语义。 - ✅ 避免重复计算:本实现仅在移动过程中累加时间惩罚,未对服务等待或空闲时间计罚——这符合“车内时间”定义,也更贴近真实体验。
- ⚠️ 勿混淆
getTransportTime与getTransportCost:前者返回纯时间(秒),用于计算 passenger-seconds;后者返回综合成本(可能含距离、时间、拥堵等),应单独计入基础成本。
通过该方法,JSprit 将自然倾向于生成“先接远途、后接近途、就近释放”的优质路径——既保障多乘客共乘效率,又显著降低平均车内滞留时间,无需复杂约束逻辑,兼具可解释性与工程鲁棒性。










