OptaPlanner:分数腐败解决某些数据集?

时间:2018-02-28 13:37:40

标签: java optaplanner

当我尝试解决某个数据集时,我收到此错误(环境模式设置为full_assert)

14:14:40.603 [main] INFO o.o.core.impl.solver.DefaultSolver - Solving started: time spent (39), best score (0hard/0medium/-18soft), environment mode (FULL_ASSERT), random (JDK with seed 0).
14:14:41.608 [main] DEBUG o.o.c.i.l.DefaultLocalSearchPhase -     LS step (0), time spent (1045), score (0hard/0medium/-17soft), new best score (0hard/0medium/-17soft), accepted/selected move count (466/466), picked move (Assignment ID: 14 --- [Employee ID: N/A | Shift ID: 737] {null -> 4 Chef(admin) Bossen}).
14:14:41.667 [main] ERROR org.optaplanner - Caught exception!
java.lang.IllegalStateException: Score corruption: the workingScore (0hard/0medium/-16soft) is not the uncorruptedScore (0hard/-4medium/-16soft) after completedAction (Assignment ID: 17 --- [Employee ID: 4 | Shift ID: 746] {4 Chef(admin) Bossen -> 4 Chef(admin) Bossen}):
  The corrupted scoreDirector has no ConstraintMatch(s) which are in excess.
  The corrupted scoreDirector has 1 ConstraintMatch(s) which are missing:
    org.avalin.optaplannerhellotest.solver/MaximumHoursPerWeekExceeded/[4 Chef(admin) Bossen, Week: 12, org.avalin.optaplanner.service.Service@726a17c4]=0hard/-4medium/0soft
  Check your score constraints.
    at org.optaplanner.core.impl.score.director.AbstractScoreDirector.assertWorkingScoreFromScratch(AbstractScoreDirector.java:496)
    at org.optaplanner.core.impl.solver.scope.DefaultSolverScope.assertWorkingScoreFromScratch(DefaultSolverScope.java:132)
    at org.optaplanner.core.impl.phase.scope.AbstractPhaseScope.assertWorkingScoreFromScratch(AbstractPhaseScope.java:167)
    at org.optaplanner.core.impl.localsearch.decider.LocalSearchDecider.processMove(LocalSearchDecider.java:163)
    at org.optaplanner.core.impl.localsearch.decider.LocalSearchDecider.doMove(LocalSearchDecider.java:148)
    at org.optaplanner.core.impl.localsearch.decider.LocalSearchDecider.decideNextStep(LocalSearchDecider.java:120)
    at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.solve(DefaultLocalSearchPhase.java:70)
    at org.optaplanner.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:87)
    at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:167)
    at org.avalin.optaplanner.main.EmployeeRoster.main(EmployeeRoster.java:77)

这是我的约束:

rule "MaximumHoursPerWeekExceeded"
    when
         $employee : Employee()
         $week : Week()

         $service : Service
         (
             getWeeklyDurationForEmployee($employee, $week) > $employee.getDuration($employee.getMaxHoursPerWeek)
         )
         eval(isDroolActivated("MaximumHoursPerWeekExceeded", $service))
    then
        setDroolRating(scoreHolder, kcontext, $service.getDroolStrength(drools),  $service.getDroolWeight(drools) + (int) ($service.getWeeklyDurationForEmployee($employee, $week)/3600 -  $employee.getDuration($employee.getMaxHoursPerWeek())/3600)-1);
end

出于某种原因,这种情况不会发生在我测试的其他数据集中,它们具有不同的约束和约束设置(软/中/硬和不同的权重),但当然仍然保持“MaximumHoursPerWeek”约束。

我了解到如果我更换这一行:

getWeeklyDurationForEmployee($employee, $week)

使用随机数字,它会在不说分数损坏的情况下运行。

此方法循环执行当前已发送给给定员工的分配。 “作业”是我的计划实体。这可能是个问题吗?阴影变量是否方便?我尝试将我的作业列表设为“@InverseRelationShadowVariable(...)”,但它没有改变任何内容

1 个答案:

答案 0 :(得分:0)

我怀疑在RHS中调用的任何方法都可能依赖于规划实体中的规划变量,这是规则模式的一部分,因此drools在获取事件时不会重新评估规则计划实体的计划变量已被修改。