Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Optaplanner:Drools规则在求解过程中不触发,仅在_Java_Drools_Optaplanner - Fatal编程技术网

Java Optaplanner:Drools规则在求解过程中不触发,仅在

Java Optaplanner:Drools规则在求解过程中不触发,仅在,java,drools,optaplanner,Java,Drools,Optaplanner,我正在处理一个类似于optaplanner中护士排班示例的解算器。员工被分配到班次,员工是计划变量,班次是计划实体,但班次被划分为1小时间隔,员工每天可以在多个班次上工作 其中一个硬约束是每个员工每月只能工作一定的小时数。我目前使用以下规则对此进行建模,并且它是有效的: rule "At most 173h work per month per fulltime employee, assuming roster is only for 1 month" when $e: Employe

我正在处理一个类似于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
现在,由于预计有很多轮班需要计划1000+我想我可以通过跟踪每个员工的工作时间来加快处理速度

为此,我为每个员工提供了一个对象统计信息,该统计信息应该能够跟踪这些信息。对象在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和ShiftasSignementSwapMove,如护士日程安排示例中所示,以确保每个移动都调用setEmployee方法,因此应该更改员工统计信息。现在我想在规则中使用这些递增计算的员工统计数据,如下所示:

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对象之后,规则才会被实际触发,并显示为违反规则

我做错了什么


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

当OptaPlanner修改Shift.employee时,Drools get被告知已修改Shift,以便可以进行增量分数计算。Drools不会被告知员工也被修改了

解决方案:将Employee.stats设为影子变量

Employee应该是shadow@PlanningEntity,其stats字段应该是@CustomShadowVariable,其源是setEmployee Shift.Employee,其侦听器在Shift.setEmployee中执行代码,以便setEmployee可以再次成为简单的setter


不要忘记在解算器配置中将员工注册为规划实体,除非它正在进行扫描。

调用“setEmployee”时是否更新了员工事实?我将如何进行/检查?所有员工都在@PlanningSolution中的一个列表中,该列表用@ProblemFactCollectionProperty注释,setEmployee所接收的员工对象来自我所理解的列表,因此如上所述的setEmployee应该更新该列表中的对象引用,不是吗?@laune我想我刚刚找到了答案。非常感谢你为我指明了正确的方向。解决方案是调用scoreDirector.beforeProblemPropertyChanged和scoreDirector.afterProblemPropertyChanged,在这种情况下,每次调用setEmployee时都会调用班次的员工。现在来看看这是否比需要迭代所有轮班来总结工作时间的表现更差;除了调用setter通知规则引擎以便重新评估规则之外,update是一个单独的调用。我按照如下方式实现了VariableListener:@Override public void afterVariableChangedCoreDirector scoreDirector,Shift Shift{ifshift.getEmployee!=null{scoreDirector.beforeVariableChangedshift.getEmployee,统计信息;shift.getEmployee.getStats.AddWorkedMinuteshift.getTimeSlot;scoreDirector.beforeVariableChangedshift.getEmployee,统计信息;}侦听器的beforeVariableChanged方法是相同的,只是我调用了.subtractWorkedMinutes。我仍然遇到这样一个问题,即解决方案的分数与匹配的规则不符。您是否尝试打开environmentMode FULL_ASSERT?如果没有,则会给出更准确的错误消息。启用此选项后,我得到java.lang.IllegalStateException:分数损坏:解决方案的分数0hard/-260medium/-103900soft不是未损坏的core 0hard/-260medium/-104899soft.at org.optaplanner.core.impl.Score.director.AbstractScoreDirectorFactory.assertScoreFromScratchAbstractScoreDirectorFactory.java:100 at org.optaplanner.core.impl.solver.scope.DefaultSolverScope.assertScoreFromScratchDefaultSolverScope.java:136位于org.optaplanner.core.impl.solver.recaller.BestSolutionRecaller.processWorkingSolutionDuringStepBestSolutionRecaller.java:98