当前位置: 首页 > 知识库问答 >
问题:

optaplanner:口水规则在求解过程中不开火,只有在求解之后才开火

岳城
2023-03-14

我正在开发一个类似于optaplanner中护士排班示例的求解器(员工被分配到轮班,员工是计划变量,轮班是计划实体),只不过轮班被拆分为1小时间隔,一个员工每天可以工作多个轮班。

其中一个硬限制是每个雇员每月只能工作一个设定的小时数。我目前使用以下规则对此进行建模,并且它起作用:

rule "At most 173h work per month per fulltime employee, assuming roster is only for 1 month"
when
    $e: Employee(type == EmployeeType.FULLTIME)
    $total  : Number(intValue() > 10320) 
              from accumulate(
                            Shift(employee == $e,
                            $minutes : getTimeSlot().getMinutesInterval()),
                            sum($minutes))
then
    scoreHolder.addHardConstraintMatch(kcontext, -1);
end

为此,我给每个员工一个对象(stats)来跟踪这些信息。对象在Shift对象的setEmployee方法期间更新,如下所示:

public void setEmployee(Employee employee) {
    if(this.employee != null){
        this.employee.getStats().subtractWorkedMinutes(this.timeSlot);
    }
    this.employee = employee;
    if(this.employee != null){
        this.employee.getStats().addWorkedMinutes(this.timeSlot);
    }
}

我还实现了EmployeeChangeMove和ShiftAssignmentSwapMove,就像nurse scheduling示例中一样,以确保每个移动都调用setEmployee()方法,因此应该更改employee统计信息。现在,我想在规则中使用这些递增计算的员工统计数据,如下所示:

rule "At most 173h work per month per fulltime employee, assuming roster is only for 1 month"
when
    Employee(type == EmployeeType.FULLTIME,
      getStats().getTotalMinutesWorked() > 10320)                    
then
    scoreHolder.addHardConstraintMatch(kcontext, -1);
end

然而,我遇到的问题是,这些规则在求解过程中从未被激发,并且在计算分数时没有被求解器考虑。只有在求解器完成并且我从解决方案生成一个新的ScoreDirector以获得ConstraintMatchTotal对象之后,规则才是实际激发的,并且显示为违反的规则。

我做错了什么?

在求解过程中跟踪变化的变量以在约束规则中使用它们的最佳方法是什么?

共有1个答案

子车成和
2023-03-14

当Shift.Employee被OptaPlanner修改时,Drools被告知Shift被修改了(因此它可以进行增量分数计算)。Drools没有被告知员工也被修改了...

解决方案:使Employee.stats成为影子变量。

Employee应该是一个阴影@PlanningEntity,它的stats字段应该是一个@CustomShadowVariable,它的源是setEmployeeShift.Employee,它的侦听器在Shift.setEmployee中执行代码,这样setEmployee就可以再次成为一个简单的setter。

不要忘记在求解器配置中将Employee注册为计划实体,除非它正在进行扫描。

 类似资料:
  • 我想写一个心率在160以上持续5分钟时触发的规则,我想出的规则如下: 我的心率类别有以下字段: 我面临的问题是,每当心率超过160时,这条规则就会启动。相反,我希望它只有在心率保持在160以上5分钟时才会启动。如何调整此规则?

  • 我是optaplanner的新手,希望能用它来解决VRPTW的取货和送货问题(VRPTWPD)。 我从repo示例中的VRPTW代码开始。我正在努力增加它来解决我的问题。然而,我无法返回一个遵守优先/车辆约束的解决方案(必须在交付之前完成取货,并且两者必须由同一车辆完成)。 我总是返回一个解决方案,其中硬得分是我对这种解决方案的期望(即,我可以将一个小样本问题中的所有违规行为相加,并看到硬得分与我

  • 我不太会流口水和咕噜。 我有一个关于规则流的基本问题。 我在guvnor插件上使用引导编辑器创建了3条规则。现在我想根据第一条规则的结果调用第二条或第三条规则。 e、 g.如果患者年龄小于18岁,则进行第二条规则的小检查,否则请调用第三条规则由高级医生进行检查。 那么,这可以通过使用规则流来实现吗?如果是,如何?是否有任何示例链接和文档来演示它?非常感谢您的帮助。 谢啦

  • 假设我有一个这样的drools文件, 所有这些都将出现在一个文件中。就像在规则中一样,规则的顺序将基于最高的突出数。我需要一些东西, 我知道我可以更改when条件以满足我的标准,但我想知道Drools中是否有规则的选项?

  • 在为我的项目实现了一些规则之后,我做了一个“ScoreConsistencyCheck”,以确保规则得到了正确的实现。 表示实现我自己的方法,该方法将在我提前终止求解或通过配置终止后调用,输出预期分数。该方法的参数是一个实例,基于解决方案的状态计算预期分数,然后将其与来自解决方案实例的“分数”变量的分数进行比较。 当我使用时,它不会抛出异常,但是当我这样尝试时,我有时会在构建启发式或本地搜索的特定

  • 我试图使用他们的Firebase API递归获取黑客新闻故事的所有评论。一个故事有一个属性,它是一个表示注释的ID数组。每个注释都可以有自己的 在第一级注释promise解决后触发(这是有意义的,因为所有的都解决了。)然而,我想知道一旦所有嵌套的promise都解决了。我该怎么做呢?