2015-11-03 111 views
0

在求解器配置我的本地搜索的部分看起来像:IllegalStateException异常分数腐败

<acceptor> 
    <lateAcceptanceSize>400</lateAcceptanceSize> 
    <entityTabuSize>9</entityTabuSize> 
</acceptor> 
<forager> 
    <acceptedCountLimit>2000</acceptedCountLimit> 
</forager> 

,一切工作正常,但是当我将其更改为(是什么导致优化增益,我认为):

<acceptor> 
<lateAcceptanceSize>600</lateAcceptanceSize> 
</acceptor> 
<forager> 
<acceptedCountLimit>4</acceptedCountLimit> 
</forager> 

求解器开始工作后,我得到异常

Score corruption: the solution's score (-20hard/-8medium/-4soft) is not the uncorruptedScore (-20hard/-8medium/-8soft) 

是什么原因问题? (距离FULL_ASSERT模式仅供参考)

编辑:

东西可以连接到治:

// Boundary lessons have to be schedulead at the beginning/end in a day 
rule "boundaryLesson" 
    when 
     $oddzial : Oddzial() 
     $boundaryLesson : Lesson(scheduled == true, containsOddzial($oddzial), base.lessonLimits.isBoundaryLesson == true, $base : base) 
     exists Lesson(scheduled == true, containsOddzial($oddzial), dayLessonNumber.day == $base.day, base.lessonNumberFrom < $base.lessonNumberFrom) 
     and exists Lesson(scheduled == true, containsOddzial($oddzial), dayLessonNumber.day == $base.day, base.lessonNumberTo > $base.lessonNumberTo) 
    then 
     scoreHolder.addHardConstraintMatch(kcontext, -1); 
end 

,因为有时我得到下面的错误也:

Score corruption: the workingScore (0hard/-2medium/0soft) is not the uncorruptedScore (-1hard/-2medium/0soft) after completedAction (8848-537:Tuesday-3 {[email protected] -> [email protected]}): 
    The corrupted scoreDirector has no ConstraintMatch(s) which are in excess. 
    The corrupted scoreDirector has 1 ConstraintMatch(s) which are missing: 
    com.praca.mgr.cp.algorytm.solver/boundaryLesson/level0/[8854-537:Tuesday-2, [email protected]]=-1 
    Check your score constraints. 

我知道增量分数计算是如何工作的,但我看不出这条规则会出现什么问题

+0

错误信息应该输出更多的信息,特别是如果你使用6.3.0.Final或更高版本。 –

+0

在您的方法中是否存在任何被调用的方法(存在Lesson(... containsOddzial($ oddzial),...'也查看其他Lessons?这可以解释其他Lesson改变,但Drools没有意识到这会影响这个教训,因为它已经收到了本课的modify()事件 –

+0

有两个独立的问题在玩,因为第一个分数腐败是关于一个软约束,第二个是关于一个硬约束 –

回答

1

在这两种情况下,您都会有潜在的分数损坏,但只会在第二种情况下出现。对于生产的可靠性,你一定要修复它。

请参阅有关“增量分数计算”的文档以了解腐败分数。常见原因:

  • 阴影变量腐败。使用OptaPlanner 6.3.0.Final或更高版本,它将显示为“VariableListener腐败”而不是“分数损坏”并提供更多信息。
  • 坏的自定义由于不良的撤消移动而移动。通常这会显示为“撤消移动腐败”而不是“分数腐败”。
  • 不好的自定义移动在第二次在相同的解决方案状态下完成后会发生变化。这将在processWorkingSolutionDuringStep()期间检测到。

如果使用Drools的计算:

导致 “分数腐败”
  • 坏评分规则。从OptaPlanner 6.1开始,这是不太可能的,因为写出不好的分数规则要困难得多。尝试评论出分数规则,找出应该责怪哪一个。
  • Drools中的一个错误。不太可能,但可能。创建一个专用的复制器并提交一个jira。

如果您使用增量分数计算:

  • 一个坏的Java增量分数计算。使用<assertScoreDirectorFactor>也有简单的分数计算器。祝你好运在这种情况下。
0

综上所述:

  • 我使用OptaPlanner 6.3.0。最终以FullAssert环境模式
  • 我删除定制移动排除该节中的错误的可能性
  • 有两个规划一些变量:萨拉(室)和DzienNrLekcji(对象包括白天和教训号)
  • 有没有任何影子变量存在于每一个
  • 与损坏的得分问题得分水平,所以我离开了 只有硬约束规则部分,它看起来就像是:

    // ############# ################################################## ############# //硬约束 // ########################################### #################################

    // two Lessons at the same time should be in another rooms. 
    rule "salaOccupancy" 
        when 
          $leftLesson : Lesson($id : base.numericId, scheduled == true, $sala : sala) 
          not Lesson(scheduled == true, timeCollision($leftLesson), sala == $sala, base.numericId < $id) 
          $rightLesson : Lesson(scheduled == true, timeCollision($leftLesson), sala == $sala, base.numericId > $id) 
        then 
         scoreHolder.addHardConstraintMatch(kcontext, -10); 
    end 
    
    // each oddzial and nauczyciel can't have two lessons at the same time 
    rule "przydzialCollision" 
        when 
          $przydzialConflict : PrzydzialConflict($leftPrzydzial : leftPrzydzial, $rightPrzydzial : rightPrzydzial) 
          $leftLesson : Lesson(scheduled == true, base.przydzial == $leftPrzydzial) 
          $rightLesson : Lesson(scheduled == true, base.przydzial == $rightPrzydzial, timeCollision($leftLesson), this != $leftLesson) 
         then 
          scoreHolder.addHardConstraintMatch(kcontext, -2 * $przydzialConflict.getConflictCount()); 
    end 
    
    // sala's capacity shouldn't be exceeded 
    rule "salaCapacity" 
        when 
         $sala : Sala($capacity : ograniczenia.maxLiczbaUczniow.max) 
         $lesson : Lesson(scheduled == true, sala == $sala) 
         $limit : LessonStudentLimit(lesson == $lesson, numberOfStudents > $capacity) 
        then 
         scoreHolder.addHardConstraintMatch(kcontext, -2); 
    end 
    
    // cannot put lesson into not available time period in Sala or Przydzial 
    rule "availability" 
        when 
         Lesson(scheduled == true , dostepnaSala == false) 
         or Lesson(scheduled == true , dostepnyPrzydzial == false) 
        then 
         scoreHolder.addHardConstraintMatch(kcontext, -2); 
    end 
    
    // Oddzials cannot have gaps between classes during a day 
    rule "gaps" 
        when 
         $oddzial : Oddzial() 
         $dzien : DzienTygodnia() 
         $lessonList : ArrayList(LessonBlockCounter.calculateOddzialGaps($lessonList,TimetableSolution.maxLessonNr)>0) from collect (
          Lesson(scheduled == true, containsOddzial($oddzial), dzienNrLekcji.dzien == $dzien) 
         ) 
        then 
         scoreHolder.addHardConstraintMatch(kcontext, -5*LessonBlockCounter.calculateOddzialGaps($lessonList,TimetableSolution.maxLessonNr)); 
    end 
    
    // If Przydzial has blocks distribution defined, only one lesson per day is allowed 
    rule "blocks" 
        when 
         $przydzial : Przydzial(ograniczenia.ograniczeniaBlokiLekcyjnePrzydzialu.czyTylkoJednaLekcjaNaDzien.isAktywne() == true) 
         $dzien : DzienTygodnia() 
         $lessonCount : Number(intValue > 1) from accumulate (
          $lesson : Lesson(scheduled == true, base.przydzial == $przydzial,dzienNrLekcji.dzien == $dzien), 
          count($lesson) 
         ) 
        then 
         scoreHolder.addHardConstraintMatch(kcontext, -2); 
    end 
    
    // Boundary lessons have to be schedulead at the beginning/end in a day 
    rule "boundaryLesson" 
        when 
         $oddzial : Oddzial() 
         $boundaryLesson : Lesson(scheduled == true, containsOddzial($oddzial), base.ograniczeniaLekcja.czyLekcjaGraniczna.aktywne == true, $base : base) 
         exists Lesson(scheduled == true, containsOddzial($oddzial), dzienNrLekcji.dzien == $base.dzien, base.lekcjaNrOd < $base.lekcjaNrOd) 
         and exists Lesson(scheduled == true, containsOddzial($oddzial), dzienNrLekcji.dzien == $base.dzien, base.lekcjaNrDo > $base.lekcjaNrDo) 
        then 
         scoreHolder.addHardConstraintMatch(kcontext, -1); 
    end 
    
    // Linked lessons have to take place at the same time 
    rule "linkedLesson" 
        when 
         $linkedLesson : Lesson(scheduled == true, base.ograniczeniaLekcja.lekcjePolaczone.empty == false, $dzienNrLekcji : dzienNrLekcji) 
         Lesson(scheduled == true, base.ograniczeniaLekcja.lekcjePolaczone contains $linkedLesson.base, dzienNrLekcji != $dzienNrLekcji) 
        then 
         scoreHolder.addHardConstraintMatch(kcontext, -5); 
    end 
    
    // Linked lessons have to take place at the same time 
    rule "scheduledLinkedLesson" 
        when 
         $linkedLesson : Lesson(scheduled == false, base.ograniczeniaLekcja.lekcjePolaczone.empty == false) 
        then 
         scoreHolder.addHardConstraintMatch(kcontext, -10*$linkedLesson.getBase().getCzasTrwania()); 
    end 
    
    
    // Lessons have to be placed in the school time boundaries 
    rule "schoolTime" 
        when 
         $lesson : Lesson(scheduled == true, base.czasTrwania > 1 , base.lekcjaNrOd > TimetableSolution.maxLessonNr - base.czasTrwania) 
        then 
         scoreHolder.addHardConstraintMatch(kcontext, -5); 
    end 
    
    // Lessons have to be scheduled in one of the preferred sala 
    rule "assignedSalaPrzydzialu" 
        when 
         $lesson : Lesson(scheduled == true, 
         sala not memberOf base.przydzial.ograniczenia.perferowaneSale.preferowaneSale.saleList) 
        then 
         scoreHolder.addHardConstraintMatch(kcontext, -1); 
    end 
    
    // ############################################################################ 
    // Medium constraints 
    // ############################################################################ 
    
    //lesson have to have sala and day assigned, not assigned lessons are acceptable in overconstrained problem 
    rule "scheduledLesson" 
        when 
         $lesson : Lesson(scheduled == false) 
        then 
         scoreHolder.addMediumConstraintMatch(kcontext, -$lesson.getBase().getCzasTrwania()); 
    end 
    

运行的算法,我'后越来越例外:

2015-11-04 10:39:21,493 [http-8080-3] INFO org.optaplanner.core.impl.solver.DefaultSolver - Solving started: time spent (426), best score (uninitialized/-160hard/-165medium/0soft), environment mode (FULL_ASSERT), random (JDK with seed 0). 
2015-11-04 10:39:23,969 [http-8080-3] INFO org.optaplanner.core.impl.constructionheuristic.DefaultConstructionHeuristicPhase - Construction Heuristic phase (0) ended: step total (165), time spent (2903), best score (-160hard/-165medium/0soft). 
2015-11-04 10:39:24,615 [http-8080-3] ERROR org.apache.struts2.dispatcher.Dispatcher - Exception occurred during processing request: Score corruption: the solution's score (-123hard/-161medium/0soft) is not the uncorruptedScore (-126hard/-160medium/0soft). 
java.lang.IllegalStateException: Score corruption: the solution's score (-123hard/-161medium/0soft) is not the uncorruptedScore (-126hard/-160medium/0soft). 
    at org.optaplanner.core.impl.score.director.AbstractScoreDirectorFactory.assertScoreFromScratch(AbstractScoreDirectorFactory.java:100) 
    at org.optaplanner.core.impl.solver.scope.DefaultSolverScope.assertScoreFromScratch(DefaultSolverScope.java:127) 
    at org.optaplanner.core.impl.solver.recaller.BestSolutionRecaller.processWorkingSolutionDuringStep(BestSolutionRecaller.java:107) 
    ... 

研究的问题后,我敢肯定,它与增量分值计算和DRL文件连接。我认为这个问题导致“差距”规则,因为“calulateOddzialGaps”方法检查收集到的$ lessonList的日期和课程编号,但在评论此规则问题后依然存在。任何其他规则不会在java方法中的WHEN部分使用课程(planningEntity)。什么可能是错误的?我没有任何其他的想法...

+0

您是否可以更多地减少DRL文件?删除所有不需要的规则来重现异常。剩下1或2个最简单的形式,而FULL_ASSERT仍然会抛出一个分数腐败异常,我会验证它们是否有效。如果它们是有效的并且如你之前所说的那样不使用自定义移动,没有影子变量监听器和6.3,那么它必定是一个在drools中的错误。我认为这是不太可能的,因为在您的案例中再现所有3个约束级别的错误的机会非常小,从来没有在我们的测试覆盖范围或其他用户中。 –

+0

一旦剩下1条规则仍然会重现问题,您可能还会看看''以独立使用''来独立声明分数,这可能会很快看到损坏。 –

+0

将DRL文件尽可能减少到尽可能少的规则,是否还有运气? –