Timefold员工排班:标记硬约束违规班次可行性问询
Timefold实现硬约束违反标记与合规组合筛选
Timefold完全可以满足你的需求,以下是具体实现方案:
1. 标记违反硬约束的Shift对象
方式一:在DRL规则中直接标记实体
在Shift实体类中添加一个布尔字段用于标记是否违反硬约束:
public class Shift { private boolean hardConstraintViolated; // 其他字段、getter、setter public boolean isHardConstraintViolated() { return hardConstraintViolated; } public void setHardConstraintViolated(boolean hardConstraintViolated) { this.hardConstraintViolated = hardConstraintViolated; } }
在DRL规则文件中,当触发硬约束违规时,设置该标记:
rule "禁止员工连续12小时内排两个班次" when Shift($employee : employee, $currentShift : this, hardConstraintViolated == false) Shift(employee == $employee, startDate after $currentShift.endDate, startDate before $currentShift.endDate.plusHours(12)) then scoreHolder.addHardConstraintMatch(kcontext, -1); $currentShift.setHardConstraintViolated(true); end
方式二:利用Timefold约束匹配查询
无需修改实体类,直接通过Timefold的约束匹配API获取违规的Shift:
// 求解完成后获取结果 MyRosterSolution solution = solver.solve(problem); Score totalScore = solution.getScore(); if (totalScore.getHardScore() < 0) { // 遍历所有硬约束的匹配结果 for (ConstraintMatchTotal<?> constraintMatchTotal : solver.getConstraintMatchTotalMap().values()) { if (constraintMatchTotal.getScore().getHardScore() < 0) { // 获取该约束下所有违规的Shift实例 for (ConstraintMatch<?> match : constraintMatchTotal.getConstraintMatchSet()) { Shift violatedShift = (Shift) match.getJustificationList().get(0); // 可在此处对违规Shift做标记或收集 } } } }
2. 筛选符合硬约束的班次与员工组合
求解完成后,通过标记或约束匹配结果筛选合规数据:
// 基于实体标记筛选 List<Shift> compliantShifts = solution.getShifts().stream() .filter(shift -> !shift.isHardConstraintViolated()) .collect(Collectors.toList()); // 或基于约束匹配结果筛选(需先收集违规Shift) Set<Shift> violatedShiftSet = new HashSet<>(); // 先通过约束匹配API填充violatedShiftSet... List<Shift> compliantShifts = solution.getShifts().stream() .filter(shift -> !violatedShiftSet.contains(shift)) .collect(Collectors.toList());
内容的提问来源于stack exchange,提问作者naokeziteng
相关产品推荐
相关产品推荐

