You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Timefold带时间窗VRP:医护人员按时返家方案设计咨询

设计合理性分析与约束实现建议

一、你的修改方案整体合理,细节优化建议如下

1. 添加@NextElementShadowVariable注解的nextVisit

完全合理。在Timefold的VRP任务链中,仅靠previousVisit只能从后往前遍历任务,新增双向关联的nextVisit后,能快速定位每个任务的后续节点——尤其是要找医护的最后一个出诊任务时,直接筛选nextVisit == null的节点即可,无需遍历整个任务链。而且@NextElementShadowVariable会自动维护previousVisit和nextVisit的一致性,不用手动处理关联更新逻辑,减少出错概率。

2. 在Providers类添加下班时间字段

这个需求是必要的,但字段命名建议调整:你计划用arrivalTime,但这个名称和Visits类中代表到达出诊点的arrivalTime语义冲突,容易混淆。建议改为shiftEndTime(班次结束时间)或homeReturnDeadline(返家截止时间),语义更清晰。

3. 最后一个任务nextVisit为null + 返家时间不超下班时间

逻辑正确。最后一个出诊任务没有后续任务,所以nextVisit设为null是合理的。这里需要注意:返家时间的计算逻辑是最后任务的结束时间 + 最后任务地点到医护住所的行驶时间,这个时间必须小于等于医护的下班时间。

二、按时返家的约束实现示例

你需要添加一个硬约束(如果超时直接判定方案不可行)或软约束(超时则根据时长惩罚,允许部分超时的次优方案),以下是基于Timefold ConstraintProvider的实现示例:

public class VrpConstraintProvider implements ConstraintProvider {
    @Override
    public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
        return new Constraint[]{
            // 硬约束:必须按时返家
            returnHomeOnTimeHardConstraint(constraintFactory),
            // 如果允许超时,可添加软约束按超时时长惩罚
            returnHomeOnTimeSoftConstraint(constraintFactory)
        };
    }

    private Constraint returnHomeOnTimeHardConstraint(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Visit.class)
            // 筛选最后一个出诊任务(无后续任务)
            .filter(visit -> visit.getNextVisit() == null)
            // 关联对应的医护人员
            .join(Provider.class, Joiners.equal(Visit::getProvider))
            // 计算返家时间:任务结束时间 + 任务地点到住所的行驶时间
            .filter((visit, provider) -> {
                LocalDateTime returnHomeTime = visit.getEndTime().plusMinutes(
                    calculateTravelMinutes(visit.getLocation(), provider.getHomeLocation())
                );
                // 返家时间超过下班时间则触发约束
                return returnHomeTime.isAfter(provider.getShiftEndTime());
            })
            .penalize("Return home after shift end", HardSoftScore.ONE_HARD)
            .asConstraint();
    }

    private Constraint returnHomeOnTimeSoftConstraint(ConstraintFactory constraintFactory) {
        return constraintFactory.from(Visit.class)
            .filter(visit -> visit.getNextVisit() == null)
            .join(Provider.class, Joiners.equal(Visit::getProvider))
            .filter((visit, provider) -> {
                LocalDateTime returnHomeTime = visit.getEndTime().plusMinutes(
                    calculateTravelMinutes(visit.getLocation(), provider.getHomeLocation())
                );
                return returnHomeTime.isAfter(provider.getShiftEndTime());
            })
            // 按超时分钟数惩罚,超时越久惩罚越重
            .penalize("Return home late", HardSoftScore.ONE_SOFT,
                (visit, provider) -> Duration.between(provider.getShiftEndTime(),
                    visit.getEndTime().plusMinutes(calculateTravelMinutes(visit.getLocation(), provider.getHomeLocation()))).toMinutes())
            .asConstraint();
    }

    // 这里需要你实现根据地点计算行驶时间的方法
    private long calculateTravelMinutes(Location visitLocation, Location homeLocation) {
        // 示例:根据经纬度计算距离,再转换为行驶时间
        double distance = calculateDistance(visitLocation, homeLocation);
        return (long) (distance / 60); // 假设时速60公里,转换为分钟
    }

    private double calculateDistance(Location a, Location b) {
        // 实现实际的距离计算逻辑(比如Haversine公式)
        return 0;
    }
}

约束说明

  • 硬约束:如果医护返家时间超过下班时间,直接标记方案为不可行,适合必须严格遵守工作时长的场景。
  • 软约束:允许超时,但根据超时时长进行惩罚,Timefold会优先选择超时时间更短的方案,适合偶尔可以弹性加班的场景。

内容的提问来源于stack exchange,提问作者Edmanan Khandelwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 15:55:53