Optaplanner生成周时间表如何配置规则确保每日至少1个条目
OptaPlanner周时间表每日最少条目约束编写方案
以下两种实现方式任选其一即可,建议优先使用官方推荐的约束流方案:
方案1:约束流实现(OptaPlanner 7.x及以上版本支持)
假设你的域模型包含Timeslot(时隙类,含date日期字段、isAvailable可用标识字段)和ScheduleEntry(时间表条目类,关联分配到的Timeslot规划变量),示例代码如下:
public Constraint everyAvailableDayHasAtLeastOneEntry(ConstraintFactory constraintFactory) { return constraintFactory.forEach(Timeslot.class) // 筛选所有属于可用日的时隙 .filter(Timeslot::isAvailable) // 按日期分组,统计每个日期下已分配的条目总数 .groupBy(Timeslot::getDate, sum( slot -> (int) constraintFactory.forEach(ScheduleEntry.class) .filter(entry -> entry.getTimeslot() != null) .filter(entry -> entry.getTimeslot().getDate().equals(slot.getDate())) .count() ) ) // 过滤出条目数为0的可用日期 .filter((date, entryCount) -> entryCount == 0) // 硬约束罚分,必须满足的规则建议设置为Hard级别,权重可按需调整 .penalize(HardSoftScore.ONE_HARD) .asConstraint("每个可用日至少1个条目"); }
如果你的域模型直接定义了Day(日期实体),代码可以进一步简化:
public Constraint everyAvailableDayHasAtLeastOneEntry(ConstraintFactory constraintFactory) { return constraintFactory.forEach(Day.class) .filter(Day::isAvailable) .ifNotExists( ScheduleEntry.class, equal(Day::getId, entry -> entry.getTimeslot().getDay().getId()) ) .penalize(HardSoftScore.ONE_HARD) .asConstraint("每个可用日至少1个条目"); }
方案2:DRL规则文件实现
rule "每个可用日至少1个条目" when $availableDay: Day(available == true) not ScheduleEntry(timeslot.day == $availableDay, timeslot != null) then scoreHolder.addHardConstraintMatch(kcontext, -1); end
配置注意事项
- 该规则必须设置为硬约束(Hard Score),OptaPlanner会优先满足硬约束,保证最终解不会出现可用日为空的情况
- 规则内的可用日判断逻辑要和你的业务逻辑保持一致,不要把排除的节假日、休息日计入统计
- 如果该规则优先级高于其他约束,可以提高罚分权重,比如将罚分调整为
HardSoftScore.ofHard(10)
参考时间表示例:
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐


