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

Optaplanner Drools规则如何仅处罚单个实体并最小化课程间时间间隔

OptaPlanner课程排期间隔优化问题解答

1. 查询课程A最近的前序课程B的实现方案

你可以通过Drools规则的accumulate聚合函数,从所有符合条件的前序课程中筛选出结束时间最靠近A的那一个,避免匹配到所有更早的课程:

  • 首先假设你的课程实体类为Lesson,包含字段:dayOfWeek(上课日期)、startGrain(开始时间粒索引)、endGrain(结束时间粒索引)
  • 规则匹配逻辑示例:
rule "Minimize gap between lessons"
when
    // 匹配当前课程A
    $lessonA: Lesson(dayOfWeek != null, startGrain != null, 
                    $day: dayOfWeek, $startA: startGrain)
    // 聚合所有同天、早于A的课程,取最大的结束时间粒,就是最近前序的结束时间
    accumulate(
        Lesson(dayOfWeek == $day, endGrain != null, endGrain < $startA),
        $lastEndGrain: max(endGrain)
    )
    // 匹配到最近的前序课程B
    $lessonB: Lesson(dayOfWeek == $day, endGrain == $lastEndGrain)
then
    // 处罚的权重就是两个课程之间的空隔时间粒数:$startA - $lastEndGrain -1
    scoreHolder.addSoftConstraintMatch(kcontext, - ($startA - $lastEndGrain - 1));
end

这个逻辑只会匹配到和A最近的一个前序课程,不会触发多余的处罚。

2. 规则匹配多实体时仅处罚单个实体的方法

完全可以,ScoreHolder的addConstraintMatch/addSoftConstraintMatch方法的末尾参数是该处罚关联的实体列表,你只需要传入你想要处罚的单个实体即可。
以你给出的八皇后规则示例为例,要实现仅处罚$queen1,修改如下:

rule "Horizontal conflict"
    when
        $queen1: Queen($id : id, row != null, $i : rowIndex)
        $queen2: Queen(id > $id, rowIndex == $i)
    then
        // 仅传入$queen1作为关联实体,处罚只会绑定到$queen1上
        scoreHolder.addConstraintMatch(kcontext, -1, $queen1);
end

如果使用OptaPlanner更推荐的Constraint Streams API实现,逻辑会更简洁,不需要编写Drools规则,直接通过Java流操作筛选最近前序、指定处罚关联的实体即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 08:36:04