2015-11-03 78 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文件儘可能減少到儘可能少的規則,是否還有運氣? –

相關問題